From e39ac6c470c3db6225856fb863e7d84eac203a0f Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 11:40:05 -0700 Subject: [PATCH 01/16] Update dependencies (Astro, Starlight, and related packages) to latest versions. --- astro.config.mjs | 4 +- package-lock.json | 3055 ++++++++++++++++++++++----------------------- package.json | 6 +- 3 files changed, 1524 insertions(+), 1541 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index b990f72..06a1652 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -42,7 +42,7 @@ export default defineConfig({ sidebar: [ { label: 'Concepts', - autogenerate: { directory: 'concepts' }, + items: [{ autogenerate: { directory: 'concepts' } }], }, { label: 'Guides', @@ -50,7 +50,7 @@ export default defineConfig({ { label: 'Charms Apps', collapsed: false, - autogenerate: { directory: 'guides/charms-apps' }, + items: [{ autogenerate: { directory: 'guides/charms-apps' } }], }, { label: 'Wallet Integration', diff --git a/package-lock.json b/package-lock.json index 7536228..a30ec50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,153 +9,170 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "@astrojs/starlight": "^0.37.6", - "astro": "^5.18.0", - "sharp": "^0.34.0" + "@astrojs/starlight": "^0.40.0", + "astro": "^6.4.7", + "sharp": "^0.35.1" } }, "node_modules/@astrojs/compiler": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz", - "integrity": "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-4.0.0.tgz", + "integrity": "sha512-eouss7G8ygdZqHuke033VMcVw5HTZUu+PXd/h06DGDUg/jt5btPYPqh66ENWw/mU78rBrf/oeC4oqoBwMtDMNA==", "license": "MIT" }, "node_modules/@astrojs/internal-helpers": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.6.1.tgz", - "integrity": "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A==", - "license": "MIT" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.10.0.tgz", + "integrity": "sha512-Ry2R3VPeIN4uPCSA4xQc+e+vsJXkalKpEbDc07hV+a/o5Bs2N/s/uDcPJH/05L19DKh9tAy7e6JM3YZ6Cxfezw==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "js-yaml": "^4.1.1", + "picomatch": "^4.0.4", + "retext-smartypants": "^6.2.0", + "shiki": "^4.0.2", + "smol-toml": "^1.6.0", + "unified": "^11.0.5" + } }, "node_modules/@astrojs/markdown-remark": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.1.tgz", - "integrity": "sha512-c5F5gGrkczUaTVgmMW9g1YMJGzOtRvjjhw6IfGuxarM6ct09MpwysP10US729dy07gg8y+ofVifezvP3BNsWZg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-7.2.0.tgz", + "integrity": "sha512-+YxmVQu1Bd+MFfSzjq1rOJvD9+nIOJzz5YIIhdIH01RrxRkKbyKoEgyIqP3yv51MhzMDgd79QaPv+kCVPT8vHw==", "license": "MIT", "dependencies": { - "@astrojs/internal-helpers": "0.6.1", - "@astrojs/prism": "3.2.0", + "@astrojs/internal-helpers": "0.10.0", + "@astrojs/prism": "4.0.2", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", - "import-meta-resolve": "^4.1.0", - "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.1", + "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", - "shiki": "^3.0.0", - "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "unist-util-visit-parents": "^6.0.1", + "unist-util-visit": "^5.1.0", + "unist-util-visit-parents": "^6.0.2", "vfile": "^6.0.3" } }, "node_modules/@astrojs/mdx": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.2.3.tgz", - "integrity": "sha512-oteB88udzzZmix5kWWUMeMJfeB2Dj8g7jy9LVNuTzGlBh3mEkGhQr6FsIR43p0JKCN11fl5J7P/Ev4Q0Nf0KQQ==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-6.0.3.tgz", + "integrity": "sha512-+4P3ZvwsRAqAbBgY+uZMewFo3ficlIBPZfu/Luk+v4ia/ZOuFhpsw7r+7672uT2Fc1UPdp7yW0eU5egvSq0wbw==", "license": "MIT", "dependencies": { - "@astrojs/markdown-remark": "6.3.1", - "@mdx-js/mdx": "^3.1.0", - "acorn": "^8.14.1", - "es-module-lexer": "^1.6.0", + "@astrojs/internal-helpers": "0.10.0", + "@astrojs/markdown-remark": "7.2.0", + "@mdx-js/mdx": "^3.1.1", + "acorn": "^8.16.0", + "es-module-lexer": "^2.0.0", "estree-util-visit": "^2.0.0", "hast-util-to-html": "^9.0.5", - "kleur": "^4.1.5", + "piccolore": "^0.1.3", "rehype-raw": "^7.0.0", "remark-gfm": "^4.0.1", "remark-smartypants": "^3.0.2", - "source-map": "^0.7.4", - "unist-util-visit": "^5.0.0", + "source-map": "^0.7.6", + "unist-util-visit": "^5.1.0", "vfile": "^6.0.3" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=22.0.0" + "node": ">=22.12.0" }, "peerDependencies": { - "astro": "^5.0.0" + "@astrojs/markdown-satteri": "0.3.0", + "astro": "^6.4.0" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-satteri": { + "optional": true + } } }, "node_modules/@astrojs/prism": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.2.0.tgz", - "integrity": "sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-4.0.2.tgz", + "integrity": "sha512-KTivpmnz6lDsC6o9H4+DNm2SrE/GHzw8cNAvEJwAvUT+eoaEnn/4NtbDNfRRaxaJHdp15gf+tfHAWiXR4wB3BA==", "license": "MIT", "dependencies": { - "prismjs": "^1.29.0" + "prismjs": "^1.30.0" }, "engines": { - "node": "^18.17.1 || ^20.3.0 || >=22.0.0" + "node": ">=22.12.0" } }, "node_modules/@astrojs/sitemap": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.3.0.tgz", - "integrity": "sha512-nYE4lKQtk+Kbrw/w0G0TTgT724co0jUsU4tPlHY9au5HmTBKbwiCLwO/15b1/y13aZ4Kr9ZbMeMHlXuwn0ty4Q==", + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.3.tgz", + "integrity": "sha512-f8euLVsyeAmAkSm/1M2Kb8sL8byQmfgbvBNaHFItCheTj/IpiJYSEWVcqDHZ/yEHxiS7+w87mQkzwZaPHmk5GA==", "license": "MIT", "dependencies": { - "sitemap": "^8.0.0", + "sitemap": "^9.0.0", "stream-replace-string": "^2.0.0", - "zod": "^3.24.2" + "zod": "^4.3.6" } }, "node_modules/@astrojs/starlight": { - "version": "0.37.6", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.37.6.tgz", - "integrity": "sha512-wQrKwH431q+8FsLBnNQeG+R36TMtEGxTQ2AuiVpcx9APcazvL3n7wVW8mMmYyxX0POjTnxlcWPkdMGR3Yj1L+w==", + "version": "0.40.0", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.40.0.tgz", + "integrity": "sha512-H1NBIXx4Xw6YzKMsoMkazYxFgnTTj6pD4IReUGWj1fqw82AOAgj+WnZLpTDWRExf3b9ZM7Popbl583i4IvDNVQ==", "license": "MIT", "dependencies": { - "@astrojs/markdown-remark": "^6.3.1", - "@astrojs/mdx": "^4.2.3", - "@astrojs/sitemap": "^3.3.0", + "@astrojs/markdown-remark": "^7.2.0", + "@astrojs/mdx": "^6.0.2", + "@astrojs/sitemap": "^3.7.2", "@pagefind/default-ui": "^1.3.0", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", "@types/mdast": "^4.0.4", - "astro-expressive-code": "^0.41.1", + "astro-expressive-code": "^0.43.1", "bcp-47": "^2.1.0", - "hast-util-from-html": "^2.0.1", - "hast-util-select": "^6.0.2", - "hast-util-to-string": "^3.0.0", - "hastscript": "^9.0.0", - "i18next": "^23.11.5", - "js-yaml": "^4.1.0", + "hast-util-from-html": "^2.0.3", + "hast-util-select": "^6.0.4", + "hast-util-to-string": "^3.0.1", + "hastscript": "^9.0.1", + "i18next": "^26.0.7", + "js-yaml": "^4.1.1", "klona": "^2.0.6", - "magic-string": "^0.30.17", - "mdast-util-directive": "^3.0.0", - "mdast-util-to-markdown": "^2.1.0", + "magic-string": "^0.30.21", + "mdast-util-directive": "^3.1.0", + "mdast-util-to-markdown": "^2.1.2", "mdast-util-to-string": "^4.0.0", - "pagefind": "^1.3.0", - "rehype": "^13.0.1", - "rehype-format": "^5.0.0", - "remark-directive": "^3.0.0", + "pagefind": "^1.5.2", + "rehype": "^13.0.2", + "rehype-format": "^5.0.1", + "remark-directive": "^4.0.0", "ultrahtml": "^1.6.0", "unified": "^11.0.5", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.2" + "unist-util-visit": "^5.1.0", + "vfile": "^6.0.3" }, "peerDependencies": { - "astro": "^5.5.0" + "@astrojs/markdown-satteri": "^0.2.0", + "astro": "^6.4.5" + }, + "peerDependenciesMeta": { + "@astrojs/markdown-satteri": { + "optional": true + } } }, "node_modules/@astrojs/telemetry": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", - "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.2.tgz", + "integrity": "sha512-j8DNruA8ors99Al39RYZPJK4DC1bKkoNm93mAMuBhY9TCNC4R8n1q7ovFnJ5qhGh5Lsh7pa1gpQVpYpsJPeTHQ==", "license": "MIT", "dependencies": { - "ci-info": "^4.2.0", - "debug": "^4.4.0", - "dlv": "^1.1.3", + "ci-info": "^4.4.0", "dset": "^3.1.4", - "is-docker": "^3.0.0", - "is-wsl": "^3.1.0", + "is-docker": "^4.0.0", + "is-wsl": "^3.1.1", "which-pm-runs": "^1.1.0" }, "engines": { @@ -163,30 +180,30 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.28.5" + "@babel/types": "^7.29.7" }, "bin": { "parser": "bin/babel-parser.js" @@ -195,41 +212,57 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", - "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.14.0" + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "node_modules/@capsizecss/unpack": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.1.tgz", + "integrity": "sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==", "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" + "fontkitten": "^1.0.3" }, "engines": { - "node": ">=6.9.0" + "node": ">=18" } }, - "node_modules/@capsizecss/unpack": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-4.0.0.tgz", - "integrity": "sha512-VERIM64vtTP1C4mxQ5thVT9fK0apjPFobqybMtA1UdUujWka24ERHbRHFGmpbbhp73MhV+KSsHQH9C6uOTdEQA==", + "node_modules/@clack/core": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@clack/core/-/core-1.4.1.tgz", + "integrity": "sha512-FILJa1gGKEFTGZAJE9RpVhrjKz3c3h4ar60dSv6cGuDqufQ84YEIS3GAGvZiN+H6yaLbbvTFNejjCC4tXpZEuw==", "license": "MIT", "dependencies": { - "fontkitten": "^1.0.0" + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" }, "engines": { - "node": ">=18" + "node": ">= 20.12.0" + } + }, + "node_modules/@clack/prompts": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@clack/prompts/-/prompts-1.5.1.tgz", + "integrity": "sha512-zccHj2z2oCCO4yrDiRSlFOxWerGqRiysP7a5jPK6uoI9URKAquwY42Dd/iUP8JWHxEzdRe4TlbvZCo8z1/mhrw==", + "license": "MIT", + "dependencies": { + "@clack/core": "1.4.1", + "fast-string-width": "^3.0.2", + "fast-wrap-ansi": "^0.2.0", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 20.12.0" } }, "node_modules/@ctrl/tinycolor": { @@ -242,9 +275,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz", - "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", "license": "MIT", "optional": true, "dependencies": { @@ -252,9 +285,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", "cpu": [ "ppc64" ], @@ -268,9 +301,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", "cpu": [ "arm" ], @@ -284,9 +317,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", "cpu": [ "arm64" ], @@ -300,9 +333,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", "cpu": [ "x64" ], @@ -316,9 +349,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ "arm64" ], @@ -332,9 +365,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], @@ -348,9 +381,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ "arm64" ], @@ -364,9 +397,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], @@ -380,9 +413,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", "cpu": [ "arm" ], @@ -396,9 +429,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", "cpu": [ "arm64" ], @@ -412,9 +445,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", "cpu": [ "ia32" ], @@ -428,9 +461,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", "cpu": [ "loong64" ], @@ -444,9 +477,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", "cpu": [ "mips64el" ], @@ -460,9 +493,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", "cpu": [ "ppc64" ], @@ -476,9 +509,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", "cpu": [ "riscv64" ], @@ -492,9 +525,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", "cpu": [ "s390x" ], @@ -508,9 +541,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", "cpu": [ "x64" ], @@ -524,9 +557,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", "cpu": [ "arm64" ], @@ -540,9 +573,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", "cpu": [ "x64" ], @@ -556,9 +589,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", "cpu": [ "arm64" ], @@ -572,9 +605,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", "cpu": [ "x64" ], @@ -588,9 +621,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", "cpu": [ "arm64" ], @@ -604,9 +637,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", "cpu": [ "x64" ], @@ -620,9 +653,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", "cpu": [ "arm64" ], @@ -636,9 +669,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", "cpu": [ "ia32" ], @@ -652,9 +685,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", "cpu": [ "x64" ], @@ -668,9 +701,9 @@ } }, "node_modules/@expressive-code/core": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.5.tgz", - "integrity": "sha512-II5TEy5eOoXiqPwqtpSqwamUd7lZS3YH3ofxR1ZyQMmygqORZn8/7SzgfF8G0kB7uKCBzFZT6RgKgCuHcJuPpA==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.43.1.tgz", + "integrity": "sha512-H4rUJXKyS6y2q9Ig9bIp3dFhWhkZQIeH/jRGl3DROlslrGvfD4OC9qzmvKEFExm+/DtdvvHMQ8/Olmrcfxp+wQ==", "license": "MIT", "dependencies": { "@ctrl/tinycolor": "^4.0.4", @@ -685,46 +718,46 @@ } }, "node_modules/@expressive-code/plugin-frames": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.5.tgz", - "integrity": "sha512-qU0cvAQGfRLX7XwGf3/+hqIVmAc/mNNTlqVLR0iBfJF6EKvtP3R7/uAlPrAxnxQxn0meTazCz8D+PsPyOpHKrQ==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.43.1.tgz", + "integrity": "sha512-tENfLw2UDeq5h749tTLvUtQYvgjIiQc6W7PBCR5xQ4yuE/QftManKJfUQjwJo6RRsAimVQDN4alhFTJ3aq1Khg==", "license": "MIT", "dependencies": { - "@expressive-code/core": "^0.41.5" + "@expressive-code/core": "^0.43.1" } }, "node_modules/@expressive-code/plugin-shiki": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.5.tgz", - "integrity": "sha512-gw6OWvnmDmvcKJ5AZSzl2VkuixJMQ/zWSwPLFNzitqCa8aPfIFunb0K8IIOsE43LELgOWkie9lRFspOxwDVwrg==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.43.1.tgz", + "integrity": "sha512-NdceinYEROXODNgB/ix+7oCdIg+nGyok+E+p2lU9YlWd1xKshXdXpmmptKfkuU27MJ5jjnfhMCI78YYBGi9GtQ==", "license": "MIT", "dependencies": { - "@expressive-code/core": "^0.41.5", - "shiki": "^3.2.2" + "@expressive-code/core": "^0.43.1", + "shiki": "^4.0.2" } }, "node_modules/@expressive-code/plugin-text-markers": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.5.tgz", - "integrity": "sha512-0DSiTsjWFEz6/iuLOGNNy2GaeCW41OwnVJMKx1tS+XKeQxAL89UkZP3egWNzxjWNHNMzEv3ZWWWYqbonEQlv/Q==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.43.1.tgz", + "integrity": "sha512-JWf8wdbZSNoGY4TFv3lmt3/NNDaCP7iYL6rRYD05g8YYjKL62hKUHLl5+B47+v0+bqbuMhXDN7qz2wywFUvMkg==", "license": "MIT", "dependencies": { - "@expressive-code/core": "^0.41.5" + "@expressive-code/core": "^0.43.1" } }, "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.1.tgz", + "integrity": "sha512-T15JRWOubQ3f5+GxnWeIvo47u5qV0M9HBgJhT+f2gE1e9e6OhR6K73Re52Hm80qWcu1DNb3GweKmpr/MnuP2Ow==", "cpu": [ "arm64" ], @@ -734,19 +767,19 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" + "@img/sharp-libvips-darwin-arm64": "1.3.0" } }, "node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.1.tgz", + "integrity": "sha512-t1CPD0cr7XCHjwUj6tQ5MC0pCi866I+gUW6zbUX4aFPnKd1DFBtk0M+gWcjX8VeEzgfCNiSiNTVFZ6b7kvdbnQ==", "cpu": [ "x64" ], @@ -756,19 +789,38 @@ "darwin" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" + "@img/sharp-libvips-darwin-x64": "1.3.0" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.1.tgz", + "integrity": "sha512-MBSQXqNPThW9EcZ905H6N4sEdX5EwZEYzGx5EBq9ncDCGJALMiY1xPFJxNdzuB1iBjLOpIfxajM6YxdvwmQSLA==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.1" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.0.tgz", + "integrity": "sha512-EKbmBKtyTH+GPFDRw2TgK2oV6hyxxlJVIar4hoTYSNmIwipgMFdxPQqR392GmfdsPGWga0mCFN1cCKjRb9cljw==", "cpu": [ "arm64" ], @@ -782,9 +834,9 @@ } }, "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.0.tgz", + "integrity": "sha512-Pl2OmOvrJ42adUllESxBsG54PfXLo1OYg9i3c5/5Ln/qJ0gZuTM9YMhQJPIbXqwidLRc/c2zuHt4RsrymmNv7A==", "cpu": [ "x64" ], @@ -798,12 +850,15 @@ } }, "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.0.tgz", + "integrity": "sha512-A8UpHoUDW4DwnXoV6+q3C1s7QLRAHtPDEjWuNZjwHMyoCNZnm0GeNN8ls9f/bsEYTRQRW96C/n34XJQHJ2fT7A==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -814,12 +869,15 @@ } }, "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.0.tgz", + "integrity": "sha512-C0SqjoFKnszqa44EQ7xoaT48nnO0lOyXEULfXMWi8krrjOPGYkeK30Okzla6ATbBYsyZ0ySinK0FVkpv3DwzfQ==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -830,12 +888,15 @@ } }, "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.0.tgz", + "integrity": "sha512-WOpkVxAjFd369iaIzEgNRreFD+gWdUMIGD5zplhNKNeqS6mm5dac3q2AFyCBmzYoAdouzZvRBgxy4z8QHZb4/A==", "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -846,12 +907,15 @@ } }, "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.0.tgz", + "integrity": "sha512-DRWw0mOHusrCCuw2rqP87oLg6PGlkomVDFqw2hIwsSfwWpu4k3XLcBPaKKl6ct/GtL/cwNkgwjV/tc0Mqht3VA==", "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -862,12 +926,15 @@ } }, "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.0.tgz", + "integrity": "sha512-9APy+nFWhHS+kzLgWZfLcyrUd7YqnAQVa4BPOo4xkoHpdoktOAPG4cEr9+Jpl0TtqfVmcMJimNL5qNTyyOHZNA==", "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -878,12 +945,15 @@ } }, "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.0.tgz", + "integrity": "sha512-y9RNUYDe2A1UAdhLyfeOodGRszQdaEoe4nfOpp/sNVPl2CWIcUyFaDoCh4vPLPxu19803j2naLqZup2WxDXCLA==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -894,12 +964,15 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.0.tgz", + "integrity": "sha512-cC1wkC0Mlucd0KSiGrLkJnB/ZqPvZCntc/Lk7ZnYO5ZSbF2euNek4Xvxafojq+wN1q/W0eprdpUIjUr/EV2PBg==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -910,12 +983,15 @@ } }, "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.0.tgz", + "integrity": "sha512-LiYMhUZicB1QG//+RvmYZpXJO8fYRENfp+MZUCnG9aw+AKvGAy9gPaCnuwsPcBFs8EV66M0NNxj9VHcNklE8zw==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -926,204 +1002,244 @@ } }, "node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.1.tgz", + "integrity": "sha512-jygmR02PpCYypt7xB7nst1vqjZp/BpRA/Kf9nK7qRponJ/KrLPaZWEG4G15z1d2FZ6XqI+T0350ha3RSnKx24A==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" + "@img/sharp-libvips-linux-arm": "1.3.0" } }, "node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.1.tgz", + "integrity": "sha512-ErCRyGU7LeoaFBZ0xW8hhLlXzhAg80sc4vxePB86qvtEvW1jEhhmbiNBP4oEzZfPMnu6HwHXfzD2W2kBU+RnCw==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" + "@img/sharp-libvips-linux-arm64": "1.3.0" } }, "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.1.tgz", + "integrity": "sha512-LUWZ2+r2UoLCd8j0RLCwQ4gL6w47+Y7igxtVnPIDXOOEjV86LpBkAHq5VpJeg+GHbw0KN/JWlPJOdZjyZnFqFQ==", "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" + "@img/sharp-libvips-linux-ppc64": "1.3.0" } }, "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.1.tgz", + "integrity": "sha512-i7x6J3mwF4JgT0sM4V4WlAWdJ0bucPtA9rzO1bTji1n5qgBq/W5nn87RvOQPleuuxahNoLdTngByD8/vDDLArw==", "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" + "@img/sharp-libvips-linux-riscv64": "1.3.0" } }, "node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.1.tgz", + "integrity": "sha512-0zSaTUjTF0kIWTSYxD4EG/nvCU4jez53+3RdURtoY3HvbXtIQ98W90JnrGz/oLRFuEnfIy9+7xeq883euc0ZWw==", "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" + "@img/sharp-libvips-linux-s390x": "1.3.0" } }, "node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.1.tgz", + "integrity": "sha512-NbJD4mWdeyrNQKluO/tR/wBDOelcowSVGNBWxI0e3ZtlXc6F/UOVKDj1MLD4zl3oHTuvKW3s+MA9N54YTldAYw==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" + "@img/sharp-libvips-linux-x64": "1.3.0" } }, "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.1.tgz", + "integrity": "sha512-VoW2sQCWI+0YIKQEmWJ8vzaQjTg9wIyfkFpvEfAS2h43X6iHu7GTk1hhOgB4IpSzCHe8UwQZIcx7b81VTaOrJA==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + "@img/sharp-libvips-linuxmusl-arm64": "1.3.0" } }, "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.1.tgz", + "integrity": "sha512-LjBoSd/c5JU0/K5MwzDMlgsSRP2bPn98JQGFFQAOLQ0bU/1z4ekxUdSKY9BmlwSh/cA+OrvpgsWqfZyYfVHBRw==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + "@img/sharp-libvips-linuxmusl-x64": "1.3.0" } }, "node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.1.tgz", + "integrity": "sha512-PCQUoQdZyE8tp3HpbevuihfUmgSP4qWI0FGEPWoeXqaS+cUrFfemabHQiebUmUmlUhCuNnQMxGrQ+CPqK4hnxg==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.0" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.1.tgz", + "integrity": "sha512-xU2ml2bU2OPxYVvW2A6ae4M1g5QKyhKG06P4FAt+YEaFQQO0919Qx+XxIZEUuWTMoDViLpMws2/dQwoe/VcA6A==", "cpu": [ "wasm32" ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "license": "Apache-2.0", "optional": true, "dependencies": { - "@emnapi/runtime": "^1.7.0" + "@img/sharp-wasm32": "0.35.1" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.1.tgz", + "integrity": "sha512-IkmHwuFhYpd3bTsN5SAahjwhiAcyXPooBt8vEUgxY3T0IP70sSJ0nU1xiPzZY8AH/OB1XpV3j8aZSVSOSfTbdA==", "cpu": [ "arm64" ], @@ -1133,16 +1249,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.1.tgz", + "integrity": "sha512-wQahqCi9MD8Yxzg4gVM4fNrZxh+r6vD55PyIg+WJPaM5ZRUyF35iQpwJCuma3r6viU9/8Pxlc+XHV+woVa6nCQ==", "cpu": [ "ia32" ], @@ -1152,16 +1268,16 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": "^20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" } }, "node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.1.tgz", + "integrity": "sha512-WzBtkYtZHATLPe8XRharxZXxQ9cdLrQWHiwxt+BJ5rBsisQrKeeV86ErxPSVhcG6xCEuNhs0SqLpWr7XDa2k6w==", "cpu": [ "x64" ], @@ -1171,7 +1287,7 @@ "win32" ], "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" @@ -1184,15 +1300,16 @@ "license": "MIT" }, "node_modules/@mdx-js/mdx": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", - "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", + "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", + "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", @@ -1226,9 +1343,9 @@ "license": "MIT" }, "node_modules/@pagefind/darwin-arm64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.3.0.tgz", - "integrity": "sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.5.2.tgz", + "integrity": "sha512-MXpI+7HsAdPkvJ0gk9xj9g541BCqBZOBbdwj9g6lB5LCj6kSV6nqDSjzcAJwvOsfu0fjwvC8hQU+ecfhp+MpiQ==", "cpu": [ "arm64" ], @@ -1239,9 +1356,9 @@ ] }, "node_modules/@pagefind/darwin-x64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.3.0.tgz", - "integrity": "sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.5.2.tgz", + "integrity": "sha512-IojxFWMEJe0RQ7PQ3KXQsPIImNsbpPYpoZ+QUDrL8fAl/O27IX+LVLs74/UzEZy5uA2LD8Nz1AiwKr72vrkZQw==", "cpu": [ "x64" ], @@ -1252,15 +1369,28 @@ ] }, "node_modules/@pagefind/default-ui": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.3.0.tgz", - "integrity": "sha512-CGKT9ccd3+oRK6STXGgfH+m0DbOKayX6QGlq38TfE1ZfUcPc5+ulTuzDbZUnMo+bubsEOIypm4Pl2iEyzZ1cNg==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.5.2.tgz", + "integrity": "sha512-pm1LMnQg8N2B3n2TnjKlhaFihpz6zTiA4HiGQ6/slKO/+8K9CAU5kcjdSSPgpuk1PMuuN4hxLipUIifnrkl3Sg==", "license": "MIT" }, + "node_modules/@pagefind/freebsd-x64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.5.2.tgz", + "integrity": "sha512-7EVzo9+0w+2cbe671BtMj10UlNo83I+HrLVLfRxO731svHRJKUfJ/mo05gU14pe9PCfpKNQT8FS3Xc/oDN6pOA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, "node_modules/@pagefind/linux-arm64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.3.0.tgz", - "integrity": "sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.5.2.tgz", + "integrity": "sha512-Ovt9+K35sqzn8H3ZMXGwls4TD/wMJuvRtShHIsmUQREmaxjrDEX7gHckRCrwYJ4XE1H1p6HkLz3wukrAnsfXQw==", "cpu": [ "arm64" ], @@ -1271,9 +1401,9 @@ ] }, "node_modules/@pagefind/linux-x64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.3.0.tgz", - "integrity": "sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.5.2.tgz", + "integrity": "sha512-V+tFqHKXhQKq/WqPBD67AFy7scn1/aZID00ws4fSDd+1daSi5UHR9VVlRrOUYKxn3VuFQYRD7lYXdZK1WED1YA==", "cpu": [ "x64" ], @@ -1283,10 +1413,23 @@ "linux" ] }, + "node_modules/@pagefind/windows-arm64": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/windows-arm64/-/windows-arm64-1.5.2.tgz", + "integrity": "sha512-hN9Nh90fNW61nNRCW9ZyQrAj/mD0eRvmJ8NlTUzkbuW8kIzGJUi3cxjFkEcMZ5h/8FsKWD/VcouZl4yo1F7B6g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@pagefind/windows-x64": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.3.0.tgz", - "integrity": "sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.5.2.tgz", + "integrity": "sha512-Fa2Iyw7kaDRzGMfNYNUXNW2zbL5FQVDgSOcbDHdzBrDEdpqOqg8TcZ68F22ol6NJ9IGzvUdmeyZypLW5dyhqsg==", "cpu": [ "x64" ], @@ -1297,9 +1440,9 @@ ] }, "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", "license": "MIT", "dependencies": { "@types/estree": "^1.0.0", @@ -1325,9 +1468,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.0.tgz", + "integrity": "sha512-IPIQ55ythEHkfEd9jMEi32OQ7SxURsGA43JI22lj01OLZNt2NUbJX8YUHxkVWyQ6daHPNn0truF5nSj3DQp6YQ==", "cpu": [ "arm" ], @@ -1338,9 +1481,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.0.tgz", + "integrity": "sha512-M6s9cr10MibETyo8JsOkq+Lo1+lU6hcvb1MApnUql5qte/5hMEgzlN8/ReIKNfRV8rrqX50W1BX9zoUhC192RA==", "cpu": [ "arm64" ], @@ -1351,9 +1494,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.0.tgz", + "integrity": "sha512-BqCoMoIbn0keKys+dEAdBa70EtOwV1bEsQCUgU9FdiZmmMge/Zk7LlkYGqbrdHR+Frnt0E1FOanly+rlwvvQzw==", "cpu": [ "arm64" ], @@ -1364,9 +1507,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.0.tgz", + "integrity": "sha512-SIMzST3VFNXDAbeIWDWiFCNM5qncUBDWaEV7NfE7oZbDt2mgfW4MvbKdbYiGOLoM32gbTv608UMd0XktEYSD7w==", "cpu": [ "x64" ], @@ -1377,9 +1520,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.0.tgz", + "integrity": "sha512-ezjfSQMP7ArdUsbBwbQIfwAlhE84I2iVnzQNCFSveqV42q+BmKlzVpf7mxv5EchLcoWU4y6/heFzVg1F+hodUQ==", "cpu": [ "arm64" ], @@ -1390,9 +1533,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.0.tgz", + "integrity": "sha512-9+qTWGW9AZRhnUgwtTwzNwcPlL87ngkeN0LA+q1bADvmY9aNvWaF2TFW8BZgnQPYxpDI7+rMVLivcd4V737TAQ==", "cpu": [ "x64" ], @@ -1403,12 +1546,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.0.tgz", + "integrity": "sha512-T1dMEQhXA/jkJ/jyMIw9IovK8bSUq7A8kLIlvZTb/6YIVsp2zLavr4F3oyllHWo7eIVJRyE5n3tUjQJEbE1IuQ==", "cpu": [ "arm" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1416,12 +1562,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.0.tgz", + "integrity": "sha512-2as0LgT7qQpyceQq6VUJYnumUMUrgGQCWIiDIN9DE0/tglsk6o66uCB4f3djRawAltvfCNLyZZrsqbPA6inCsA==", "cpu": [ "arm" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1429,12 +1578,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.0.tgz", + "integrity": "sha512-bVURMg+6eNN9C/yc0aVjooZcwTTtYF4YW3xta5pP0//r3o1V8gXEHXWCndj47w/HhwsFroZrFhR+6uQP5T0n0g==", "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1442,12 +1594,15 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.0.tgz", + "integrity": "sha512-Ful8pM/2yYI83PViWdFdpZhdI8HJ5qsXANe5atypbHDf+KIBBDsZsbyy8hbXnULVvW9NsTh5DHwbcBftyLTfiw==", "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1455,12 +1610,15 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.0.tgz", + "integrity": "sha512-9Gp/DgrkzfUBmNPVTyPTvay+4xEP7M/clXpj3efXBcm6uTIVIgDg4rqUpqKXvLEuFRVuEpSAOkhgNeecvaZ4Cg==", "cpu": [ "loong64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1468,12 +1626,15 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.0.tgz", + "integrity": "sha512-m9tsJz54LUXkSYM8+8PG81B9IKK5r+2T0clMq4QrS16xFosufU7firBDAZEsDheDs7wTlP7h3++S7lMsU955HA==", "cpu": [ "loong64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1481,12 +1642,15 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.0.tgz", + "integrity": "sha512-3UvJ5PNVU16aJf6M3tFI24pWzAl2/ynfbyRN3ICyQajK1lSkrnVYNnLz3v04J32qKa0FczJc22zeToc0lr2A3w==", "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1494,12 +1658,15 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.0.tgz", + "integrity": "sha512-vRWUAbYLGHBZS6Q8Msb2sfnf1fvJf+47t8l/TwOerM2qArzy+IeNMTHrYLHXh95h8MoatPHI5hhSZNs+mGXKPg==", "cpu": [ "ppc64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1507,12 +1674,15 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.0.tgz", + "integrity": "sha512-c00T5SYENHAt86cfW47URaP3Us5vLC/4QO7GYud1G5VNRffCwwCuBspwqYrriuJB+5m0WFzClCn9wed0FBjKvg==", "cpu": [ "riscv64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1520,12 +1690,15 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.0.tgz", + "integrity": "sha512-krrCDilhXOwFkSkO3Wm9I/f9H0L92XHHwy2fwxjukxIbh0dem8gZqOW5Y8BsHrpJv5qwlRBV+Wl4ZFyRWhUpwg==", "cpu": [ "riscv64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1533,12 +1706,15 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.0.tgz", + "integrity": "sha512-7pfYFSTc4/rUC/FtAI0Qp6QthDBCIi6/AuP1xYqFk5vanI6KnL5dWKP60OM/05LOsbwTmIcvr6eXC4CJuJ75IA==", "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1546,12 +1722,15 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.0.tgz", + "integrity": "sha512-7SDIalKeIpG0Ifogbbdn58HmSotYMlf23K3dCJEmiVd9Fg36Vmni82iPQec27N3wY4Bvbxftkxz6vSx9OcouTg==", "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1559,12 +1738,15 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.0.tgz", + "integrity": "sha512-eRZevouTH2i1HeAVLqJuLnt256krQkGY0TN6WsTmsIhuzbh457HuWDMakKwmi0Cjadux983CoSr8Lim2QhUIFw==", "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1572,9 +1754,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.0.tgz", + "integrity": "sha512-3oVS7FLGa4U1qcvao9ylGxrjXZyUQqR8UwxEcnUEyPX53O/C/mKDZegNXTdHCP+h3e6ta/f1EN38Yif1mmZHYg==", "cpu": [ "x64" ], @@ -1585,9 +1767,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.0.tgz", + "integrity": "sha512-yTB9TgfWj5wHe5QgktAgXTLLot1gvEjl1NiPPAUiCs4oPrIWFl5V4nC3GrkNdj9LaAU4s94nVrGbGOCqUpyWsg==", "cpu": [ "arm64" ], @@ -1598,9 +1780,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.0.tgz", + "integrity": "sha512-5LOhoaesY3doG1c+ac/2JtgREpKoJr5bUHH8tKY0V8di7+uSV6BwLs2PlR0/yzefGOkR+wE7ZolZphHCsyG5Rw==", "cpu": [ "arm64" ], @@ -1611,9 +1793,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.0.tgz", + "integrity": "sha512-yYkWHhmbhRTWTnWos5HC4GcPQfjlzzCNbM9e/+GXrLuaBXYA3qSDR9f0Vgufd5S8yX81U8jPKp7ZnAjZFMtRnw==", "cpu": [ "ia32" ], @@ -1624,9 +1806,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.0.tgz", + "integrity": "sha512-SoTb6lPg25xZlA2ibwQ++ahCCnH+FP0qmEuafMJ4gznZKOlXioKEAeJLgCrqjM98ACziXM9V1amFjICVL4IFoA==", "cpu": [ "x64" ], @@ -1637,9 +1819,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.0.tgz", + "integrity": "sha512-5L+T1fMX4RIEBoZzT0+sQ0PhTS36NULFmMXtl1TZo44TMAROIMHbZufSOjVWt/Y622BtxgxtaNOokbTDvfsrZA==", "cpu": [ "x64" ], @@ -1650,64 +1832,97 @@ ] }, "node_modules/@shikijs/core": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.21.0.tgz", - "integrity": "sha512-AXSQu/2n1UIQekY8euBJlvFYZIw0PHY63jUzGbrOma4wPxzznJXTXkri+QcHeBNaFxiiOljKxxJkVSoB3PjbyA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-4.2.0.tgz", + "integrity": "sha512-Hc87Ab1Ld/vEbZRCbwx344I5v+4RU8CVToUTRkqXL1+TjbuOp9U5Xa0M23V4GEWHxVn+yO5otb+HkQVm3ptWQQ==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.21.0", + "@shikijs/primitive": "4.2.0", + "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/engine-javascript": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.21.0.tgz", - "integrity": "sha512-ATwv86xlbmfD9n9gKRiwuPpWgPENAWCLwYCGz9ugTJlsO2kOzhOkvoyV/UD+tJ0uT7YRyD530x6ugNSffmvIiQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-4.2.0.tgz", + "integrity": "sha512-fjETeq1k5ffyXqRgS6+3hpvqseLalp1kjNfRbXpUgWR8FpZ1CmQfiNHovc5lncYjt/Vg5JK/WJEmLahjwMa0og==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.21.0", + "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.4" + "oniguruma-to-es": "^4.3.6" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.21.0.tgz", - "integrity": "sha512-OYknTCct6qiwpQDqDdf3iedRdzj6hFlOPv5hMvI+hkWfCKs5mlJ4TXziBG9nyabLwGulrUjHiCq3xCspSzErYQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-4.2.0.tgz", + "integrity": "sha512-hTorK1dffPkpbMUk6Z+828PgRo7d07HbnizoP0hNPFjhxMHctj0Px/qoHeGMYafc6ju+u9iMldN4JbVzNQM++g==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.21.0", + "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/langs": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.21.0.tgz", - "integrity": "sha512-g6mn5m+Y6GBJ4wxmBYqalK9Sp0CFkUqfNzUy2pJglUginz6ZpWbaWjDB4fbQ/8SHzFjYbtU6Ddlp1pc+PPNDVA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-4.2.0.tgz", + "integrity": "sha512-bwrVRlJ0wUhZxAbVdvBbv2TTC9yLsh4C/IO5Ofz0T8MQntgDvyVnkbjw9vi50r1kx7RCIJdnJnjZAwmAsXFLZQ==", + "license": "MIT", + "dependencies": { + "@shikijs/types": "4.2.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@shikijs/primitive": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/primitive/-/primitive-4.2.0.tgz", + "integrity": "sha512-NOq+DtUkVBJtZMVXL5A0vI0Xk8nvDYaXetFHSJFlOqjDZIVhIPRYFdGkSoElDqNuegikcc3A76SNUa8dTqtAYA==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.21.0" + "@shikijs/types": "4.2.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/themes": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.21.0.tgz", - "integrity": "sha512-BAE4cr9EDiZyYzwIHEk7JTBJ9CzlPuM4PchfcA5ao1dWXb25nv6hYsoDiBq2aZK9E3dlt3WB78uI96UESD+8Mw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-4.2.0.tgz", + "integrity": "sha512-RX8IHYeLv8Cu2W6ruc3RxUqWn0IYCqSrMBzi/uRGAmfyDNOnNO5BF/Px7o97n4XTpmFTo5GbRaazuOWj+2ak2w==", "license": "MIT", "dependencies": { - "@shikijs/types": "3.21.0" + "@shikijs/types": "4.2.0" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/types": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.21.0.tgz", - "integrity": "sha512-zGrWOxZ0/+0ovPY7PvBU2gIS9tmhSUUt30jAcNV0Bq0gb2S98gwfjIs1vxlmH5zM7/4YxLamT6ChlqqAJmPPjA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-4.2.0.tgz", + "integrity": "sha512-VT/MKtlpOhEPZloSH3Pb9WCZEBDoQVMa9jedp5UAwmJOar1DVc9DRODAxmYPW9M93IK4ryuqRejFfmlvlVDemw==", "license": "MIT", "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/@shikijs/vscode-textmate": { @@ -1717,18 +1932,18 @@ "license": "MIT" }, "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", "license": "MIT" }, "node_modules/@types/estree-jsx": { @@ -1765,9 +1980,9 @@ } }, "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", + "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", "license": "MIT" }, "node_modules/@types/ms": { @@ -1786,12 +2001,12 @@ } }, "node_modules/@types/node": { - "version": "22.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.0.tgz", - "integrity": "sha512-Kmpl+z84ILoG+3T/zQFyAJsU6EPTmOCj8/2+83fSN6djd6I4o7uOuGIH6vq3PrjY5BGitSbFuMN18j3iknubbA==", + "version": "24.13.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.2.tgz", + "integrity": "sha512-fRa09kZTgu8o71KFcDjUFuc7F+dEbZYZmkI0mg5YBTRs0yMKjYHsq/c0urDKeDb+D5qVgXOdFcuu+DZPKOITwA==", "license": "MIT", "dependencies": { - "undici-types": "~6.21.0" + "undici-types": "~7.18.0" } }, "node_modules/@types/sax": { @@ -1810,15 +2025,15 @@ "license": "MIT" }, "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", "license": "ISC" }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -1836,80 +2051,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -1924,9 +2065,9 @@ } }, "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "license": "MIT", "engines": { "node": ">=8.6" @@ -1976,80 +2117,72 @@ } }, "node_modules/astro": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.18.0.tgz", - "integrity": "sha512-CHiohwJIS4L0G6/IzE1Fx3dgWqXBCXus/od0eGUfxrZJD2um2pE7ehclMmgL/fXqbU7NfE1Ze2pq34h2QaA6iQ==", + "version": "6.4.7", + "resolved": "https://registry.npmjs.org/astro/-/astro-6.4.7.tgz", + "integrity": "sha512-5vsXx0H52u23Jpshs9tM81D03Tb3Oh2Vt2Zo0bpqjXN+njkAWjFyGjTfmWJLAcrCQd9Q+iWB1eqfhR1sZJEaUA==", "license": "MIT", "dependencies": { - "@astrojs/compiler": "^2.13.0", - "@astrojs/internal-helpers": "0.7.5", - "@astrojs/markdown-remark": "6.3.10", - "@astrojs/telemetry": "3.3.0", + "@astrojs/compiler": "^4.0.0", + "@astrojs/internal-helpers": "0.10.0", + "@astrojs/markdown-remark": "7.2.0", + "@astrojs/telemetry": "3.3.2", "@capsizecss/unpack": "^4.0.0", + "@clack/prompts": "^1.1.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.3.0", - "acorn": "^8.15.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", - "boxen": "8.0.1", - "ci-info": "^4.3.1", + "ci-info": "^4.4.0", "clsx": "^2.1.1", - "common-ancestor-path": "^1.0.1", + "common-ancestor-path": "^2.0.0", "cookie": "^1.1.1", - "cssesc": "^3.0.0", - "debug": "^4.4.3", - "deterministic-object-hash": "^2.0.2", - "devalue": "^5.6.2", + "devalue": "^5.8.1", "diff": "^8.0.3", - "dlv": "^1.1.3", "dset": "^3.1.4", - "es-module-lexer": "^1.7.0", + "es-module-lexer": "^2.0.0", "esbuild": "^0.27.3", - "estree-walker": "^3.0.3", "flattie": "^1.1.1", - "fontace": "~0.4.0", + "fontace": "~0.4.1", + "get-tsconfig": "5.0.0-beta.4", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", - "import-meta-resolve": "^4.2.0", "js-yaml": "^4.1.1", + "jsonc-parser": "^3.3.1", "magic-string": "^0.30.21", - "magicast": "^0.5.1", + "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", - "p-limit": "^6.2.0", - "p-queue": "^8.1.1", + "obug": "^2.1.1", + "p-limit": "^7.3.0", + "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", - "picomatch": "^4.0.3", - "prompts": "^2.4.2", + "picomatch": "^4.0.4", "rehype": "^13.0.2", - "semver": "^7.7.3", - "shiki": "^3.21.0", + "semver": "^7.7.4", + "shiki": "^4.0.2", "smol-toml": "^1.6.0", - "svgo": "^4.0.0", - "tinyexec": "^1.0.2", + "svgo": "^4.0.1", + "tinyclip": "^0.1.12", + "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", - "tsconfck": "^3.1.6", "ultrahtml": "^1.6.0", - "unifont": "~0.7.3", - "unist-util-visit": "^5.0.0", - "unstorage": "^1.17.4", + "unifont": "~0.7.4", + "unist-util-visit": "^5.1.0", + "unstorage": "^1.17.5", "vfile": "^6.0.3", - "vite": "^6.4.1", - "vitefu": "^1.1.1", + "vite": "^7.3.2", + "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", - "yargs-parser": "^21.1.1", - "yocto-spinner": "^0.2.3", - "zod": "^3.25.76", - "zod-to-json-schema": "^3.25.1", - "zod-to-ts": "^1.2.0" + "yargs-parser": "^22.0.0", + "zod": "^4.3.6" }, "bin": { - "astro": "astro.js" + "astro": "bin/astro.mjs" }, "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0", + "node": ">=22.12.0", "npm": ">=9.6.5", "pnpm": ">=7.1.0" }, @@ -2062,519 +2195,564 @@ } }, "node_modules/astro-expressive-code": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.5.tgz", - "integrity": "sha512-6jfABbPO0fkRD1ROAPBQtJR2p7gjbmk/GjfblOpo5Z7F+gwhL7+s8bEhLz9GdW10yfbn+gJvwEf7f9Lu2clh2A==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.43.1.tgz", + "integrity": "sha512-xddgwQxFRwpnnAnU7kSfrO82SsOAq7sQrYpXxVcrN9k/0aqNlTH2+mLrOMm1wXm6jdFKepst3hd8/qWojwuunw==", "license": "MIT", "dependencies": { - "rehype-expressive-code": "^0.41.5" + "rehype-expressive-code": "^0.43.1" }, "peerDependencies": { - "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" - } - }, - "node_modules/astro/node_modules/@astrojs/internal-helpers": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.5.tgz", - "integrity": "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==", - "license": "MIT" - }, - "node_modules/astro/node_modules/@astrojs/markdown-remark": { - "version": "6.3.10", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.10.tgz", - "integrity": "sha512-kk4HeYR6AcnzC4QV8iSlOfh+N8TZ3MEStxPyenyCtemqn8IpEATBFMTJcfrNW32dgpt6MY3oCkMM/Tv3/I4G3A==", - "license": "MIT", - "dependencies": { - "@astrojs/internal-helpers": "0.7.5", - "@astrojs/prism": "3.3.0", - "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.3", - "hast-util-to-text": "^4.0.2", - "import-meta-resolve": "^4.2.0", - "js-yaml": "^4.1.1", - "mdast-util-definitions": "^6.0.0", - "rehype-raw": "^7.0.0", - "rehype-stringify": "^10.0.1", - "remark-gfm": "^4.0.1", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.2", - "remark-smartypants": "^3.0.2", - "shiki": "^3.19.0", - "smol-toml": "^1.5.2", - "unified": "^11.0.5", - "unist-util-remove-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "unist-util-visit-parents": "^6.0.2", - "vfile": "^6.0.3" + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0 || ^6.0.0-beta" } }, - "node_modules/astro/node_modules/@astrojs/prism": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", - "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", - "license": "MIT", - "dependencies": { - "prismjs": "^1.30.0" - }, - "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" - } - }, - "node_modules/astro/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/astro/node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/astro/node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "node_modules/astro/node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "node_modules/astro/node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", "cpu": [ "x64" ], - "license": "MIT", + "license": "Apache-2.0", "optional": true, "os": [ - "android" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "node_modules/astro/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "node_modules/astro/node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", "cpu": [ "x64" ], - "license": "MIT", + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "node_modules/astro/node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", "cpu": [ - "arm64" + "arm" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "node_modules/astro/node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", "cpu": [ - "x64" + "arm64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "freebsd" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "node_modules/astro/node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", "cpu": [ - "arm" + "ppc64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "node_modules/astro/node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", "cpu": [ - "arm64" + "riscv64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "node_modules/astro/node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", "cpu": [ - "ia32" + "s390x" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "node_modules/astro/node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", "cpu": [ - "loong64" + "x64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "node_modules/astro/node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", "cpu": [ - "mips64el" + "arm64" ], - "license": "MIT", + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "node_modules/astro/node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", "cpu": [ - "ppc64" + "x64" ], - "license": "MIT", + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", "optional": true, "os": [ "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "node_modules/astro/node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", "cpu": [ - "riscv64" + "arm" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "node_modules/astro/node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", "cpu": [ - "s390x" + "arm64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "node_modules/astro/node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", "cpu": [ - "x64" + "ppc64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "node_modules/astro/node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", "cpu": [ - "arm64" + "riscv64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "node_modules/astro/node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", "cpu": [ - "x64" + "s390x" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "node_modules/astro/node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", "cpu": [ - "arm64" + "x64" ], - "license": "MIT", + "libc": [ + "glibc" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "node_modules/astro/node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", "cpu": [ - "x64" + "arm64" ], - "license": "MIT", + "libc": [ + "musl" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "openbsd" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "node_modules/astro/node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", "cpu": [ - "arm64" + "x64" ], - "license": "MIT", + "libc": [ + "musl" + ], + "license": "Apache-2.0", "optional": true, "os": [ - "openharmony" + "linux" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" } }, - "node_modules/astro/node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "node_modules/astro/node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", "cpu": [ - "x64" + "wasm32" ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, - "os": [ - "sunos" - ], + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "node_modules/astro/node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", "cpu": [ "arm64" ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "node_modules/astro/node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", "cpu": [ "ia32" ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "node_modules/astro/node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", "cpu": [ "x64" ], - "license": "MIT", + "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/astro/node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "node_modules/astro/node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" }, "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" } }, "node_modules/axobject-query": { @@ -2596,12 +2774,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/base-64": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", - "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", - "license": "MIT" - }, "node_modules/bcp-47": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", @@ -2633,40 +2805,6 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "license": "ISC" }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -2677,18 +2815,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/chalk": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", - "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -2745,9 +2871,9 @@ } }, "node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.4.0.tgz", + "integrity": "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg==", "funding": [ { "type": "github", @@ -2759,18 +2885,6 @@ "node": ">=8" } }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/clsx": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", @@ -2810,10 +2924,13 @@ } }, "node_modules/common-ancestor-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", - "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", - "license": "ISC" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-2.0.0.tgz", + "integrity": "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">= 18" + } }, "node_modules/cookie": { "version": "1.1.1", @@ -2829,9 +2946,9 @@ } }, "node_modules/cookie-es": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", - "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.3.tgz", + "integrity": "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw==", "license": "MIT" }, "node_modules/crossws": { @@ -2876,13 +2993,13 @@ "license": "MIT" }, "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "license": "MIT", "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" @@ -2963,9 +3080,9 @@ } }, "node_modules/decode-named-character-reference": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.1.0.tgz", - "integrity": "sha512-Wy+JTSbFThEOXQIR2L6mxJvEs+veIzpmqD7ynWxMXGpnk3smkHQOp6forLdHsKpAMW9iJpaBBIxz285t1n1C3w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz", + "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==", "license": "MIT", "dependencies": { "character-entities": "^2.0.0" @@ -2976,9 +3093,9 @@ } }, "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "version": "6.1.7", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", "license": "MIT" }, "node_modules/dequal": { @@ -3005,22 +3122,10 @@ "node": ">=8" } }, - "node_modules/deterministic-object-hash": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", - "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", - "license": "MIT", - "dependencies": { - "base-64": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/devalue": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.3.tgz", - "integrity": "sha512-nc7XjUU/2Lb+SvEFVGcWLiKkzfw8+qHI7zn8WYXKkLMgfGSHbgCEaR6bJpev8Cm6Rmrb19Gfd/tZvGqx9is3wg==", + "version": "5.8.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.1.tgz", + "integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==", "license": "MIT" }, "node_modules/devlop": { @@ -3037,9 +3142,9 @@ } }, "node_modules/diff": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz", - "integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-8.0.4.tgz", + "integrity": "sha512-DPi0FmjiSU5EvQV0++GFDOJ9ASQUVFh5kD+OzOnYdi7n3Wpm9hWWGfB/O2blfHcMVTL5WkQXSnRiK9makhrcnw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" @@ -3058,12 +3163,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "license": "MIT" - }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -3078,6 +3177,18 @@ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", @@ -3128,16 +3239,10 @@ "node": ">=4" } }, - "node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "license": "MIT" - }, "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -3147,9 +3252,9 @@ } }, "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", "license": "MIT" }, "node_modules/esast-util-from-estree": { @@ -3185,9 +3290,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -3197,32 +3302,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, "node_modules/escape-string-regexp": { @@ -3329,21 +3434,21 @@ } }, "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "license": "MIT" }, "node_modules/expressive-code": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.5.tgz", - "integrity": "sha512-iXl9BgDogQgzgE/WRSrcyU8upOcRZrXPMiu6tegEHML57YLQ65S0E3/sjAXmMZy0GXoPs60s9jbwoMo/mdEQOg==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.43.1.tgz", + "integrity": "sha512-JdOzanoU825iNvslmk6Kg8Ro61eSHmDK2Zz7BynOxObVrpIXZNzrIZOwQO2uDQcGsjSYShL/8vTrXgeWYnq3NA==", "license": "MIT", "dependencies": { - "@expressive-code/core": "^0.41.5", - "@expressive-code/plugin-frames": "^0.41.5", - "@expressive-code/plugin-shiki": "^0.41.5", - "@expressive-code/plugin-text-markers": "^0.41.5" + "@expressive-code/core": "^0.43.1", + "@expressive-code/plugin-frames": "^0.43.1", + "@expressive-code/plugin-shiki": "^0.43.1", + "@expressive-code/plugin-text-markers": "^0.43.1" } }, "node_modules/extend": { @@ -3352,6 +3457,30 @@ "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", "license": "MIT" }, + "node_modules/fast-string-truncated-width": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-string-truncated-width/-/fast-string-truncated-width-3.0.3.tgz", + "integrity": "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g==", + "license": "MIT" + }, + "node_modules/fast-string-width": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/fast-string-width/-/fast-string-width-3.0.2.tgz", + "integrity": "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg==", + "license": "MIT", + "dependencies": { + "fast-string-truncated-width": "^3.0.2" + } + }, + "node_modules/fast-wrap-ansi": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/fast-wrap-ansi/-/fast-wrap-ansi-0.2.2.tgz", + "integrity": "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q==", + "license": "MIT", + "dependencies": { + "fast-string-width": "^3.0.2" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -3379,18 +3508,18 @@ } }, "node_modules/fontace": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.0.tgz", - "integrity": "sha512-moThBCItUe2bjZip5PF/iZClpKHGLwMvR79Kp8XpGRBrvoRSnySN4VcILdv3/MJzbhvUA5WeiUXF5o538m5fvg==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.4.1.tgz", + "integrity": "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw==", "license": "MIT", "dependencies": { - "fontkitten": "^1.0.0" + "fontkitten": "^1.0.2" } }, "node_modules/fontkitten": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.0.tgz", - "integrity": "sha512-b0RdzQeztiiUFWEDzq6Ka26qkNVNLCehoRtifOIGNbQ4CfxyYRh73fyWaQX/JshPVcueITOEeoSWPy5XQv8FUg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/fontkitten/-/fontkitten-1.0.3.tgz", + "integrity": "sha512-Wp1zXWPVUPBmfoa3Cqc9ctaKuzKAV6uLstRqlR56kSjplf5uAce+qeyYym7F+PHbGTk+tCEdkCW6RD7DX/gBZw==", "license": "MIT", "dependencies": { "tiny-inflate": "^1.0.3" @@ -3413,16 +3542,19 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "node_modules/get-tsconfig": { + "version": "5.0.0-beta.4", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-5.0.0-beta.4.tgz", + "integrity": "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ==", "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, "engines": { - "node": ">=18" + "node": ">=20.20.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, "node_modules/github-slugger": { @@ -3432,14 +3564,14 @@ "license": "ISC" }, "node_modules/h3": { - "version": "1.15.5", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.5.tgz", - "integrity": "sha512-xEyq3rSl+dhGX2Lm0+eFQIAzlDN6Fs0EcC4f7BNUmzaRX/PTzeuM+Tr2lHB8FoXggsQIeXLj8EDVgs5ywxyxmg==", + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.11.tgz", + "integrity": "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg==", "license": "MIT", "dependencies": { - "cookie-es": "^1.2.2", + "cookie-es": "^1.2.3", "crossws": "^0.3.5", - "defu": "^6.1.4", + "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", @@ -3736,15 +3868,15 @@ } }, "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.1.tgz", + "integrity": "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==", "license": "MIT", "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", - "property-information": "^6.0.0", + "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" @@ -3754,16 +3886,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/hast-util-to-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, "node_modules/hast-util-to-string": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", @@ -3856,42 +3978,37 @@ "license": "BSD-2-Clause" }, "node_modules/i18next": { - "version": "23.16.8", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", - "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "version": "26.3.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.3.1.tgz", + "integrity": "sha512-txQqd5EULsqEh9OJqRH15aCaOuy/nLJyhw5EHCSKLKJE1aBbb3Zve2+uQIxgWhPm1QqUQoWyQBm2kfmmIrzkcQ==", "funding": [ { "type": "individual", - "url": "https://locize.com" + "url": "https://www.locize.com/i18next" }, { "type": "individual", - "url": "https://locize.com/i18next.html" + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" }, { "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + "url": "https://www.locize.com" } ], "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.2" - } - }, - "node_modules/import-meta-resolve": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", - "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" + "peerDependencies": { + "typescript": "^5 || ^6" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/inline-style-parser": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==", + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", "license": "MIT" }, "node_modules/iron-webcrypto": { @@ -3936,31 +4053,22 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + }, + "node_modules/is-docker": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-4.0.0.tgz", + "integrity": "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA==", "license": "MIT", "bin": { "is-docker": "cli.js" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-hexadecimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", @@ -3989,6 +4097,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -4002,9 +4125,9 @@ } }, "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", "license": "MIT", "dependencies": { "is-inside-container": "^1.0.0" @@ -4017,9 +4140,19 @@ } }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4028,14 +4161,11 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "license": "MIT" }, "node_modules/klona": { "version": "2.0.6", @@ -4057,9 +4187,9 @@ } }, "node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", + "version": "11.5.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.1.tgz", + "integrity": "sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==", "license": "BlueOak-1.0.0", "engines": { "node": "20 || >=22" @@ -4075,13 +4205,13 @@ } }, "node_modules/magicast": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", - "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", + "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", + "@babel/parser": "^7.29.3", + "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, @@ -4160,9 +4290,9 @@ } }, "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", @@ -4431,9 +4561,9 @@ } }, "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "license": "CC0-1.0" }, "node_modules/micromark": { @@ -4506,9 +4636,9 @@ } }, "node_modules/micromark-extension-directive": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", - "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-4.0.0.tgz", + "integrity": "sha512-/C2nqVmXXmiseSSuCdItCMho7ybwwop6RrrRPk0KbOHW21JKoCldC+8rFOaundDoRBUWBnJJcxeA/Kvi34WQXg==", "license": "MIT", "dependencies": { "devlop": "^1.0.0", @@ -5188,9 +5318,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "funding": [ { "type": "github", @@ -5260,6 +5390,19 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/obug": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.3.tgz", + "integrity": "sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==", + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, "node_modules/ofetch": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", @@ -5278,60 +5421,60 @@ "license": "MIT" }, "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.2.tgz", + "integrity": "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw==", "license": "MIT" }, "node_modules/oniguruma-to-es": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", - "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.6.tgz", + "integrity": "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA==", "license": "MIT", "dependencies": { - "oniguruma-parser": "^0.12.1", - "regex": "^6.0.1", + "oniguruma-parser": "^0.12.2", + "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "node_modules/p-limit": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", - "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-7.3.0.tgz", + "integrity": "sha512-7cIXg/Z0M5WZRblrsOla88S4wAK+zOQQWeBYfV3qJuJXMr+LnbYjaadrFaS0JILfEDPVqHyKnZ1Z/1d6J9VVUw==", "license": "MIT", "dependencies": { - "yocto-queue": "^1.1.1" + "yocto-queue": "^1.2.1" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-queue": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", - "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.3.0.tgz", + "integrity": "sha512-7NED7xhQ74Ngp4JP/2e0VZHp7vSWfJfqeiR92jPgxsz6m0Se4P03YoTKa9dDXyZ3r6P616gUXttrB6nnHYKang==", "license": "MIT", "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" + "eventemitter3": "^5.0.4", + "p-timeout": "^7.0.0" }, "engines": { - "node": ">=18" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-timeout": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", - "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", "license": "MIT", "engines": { - "node": ">=14.16" + "node": ">=20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5344,19 +5487,21 @@ "license": "MIT" }, "node_modules/pagefind": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.3.0.tgz", - "integrity": "sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.5.2.tgz", + "integrity": "sha512-XTUaK0hXMCu2jszWE584JGQT7y284TmMV9l/HX3rnG5uo3rHI/uHU56XTyyyPFjeWEBxECbAi0CaFDJOONtG0Q==", "license": "MIT", "bin": { "pagefind": "lib/runner/bin.cjs" }, "optionalDependencies": { - "@pagefind/darwin-arm64": "1.3.0", - "@pagefind/darwin-x64": "1.3.0", - "@pagefind/linux-arm64": "1.3.0", - "@pagefind/linux-x64": "1.3.0", - "@pagefind/windows-x64": "1.3.0" + "@pagefind/darwin-arm64": "1.5.2", + "@pagefind/darwin-x64": "1.5.2", + "@pagefind/freebsd-x64": "1.5.2", + "@pagefind/linux-arm64": "1.5.2", + "@pagefind/linux-x64": "1.5.2", + "@pagefind/windows-arm64": "1.5.2", + "@pagefind/windows-x64": "1.5.2" } }, "node_modules/parse-entities": { @@ -5403,12 +5548,12 @@ } }, "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", "license": "MIT", "dependencies": { - "entities": "^4.5.0" + "entities": "^6.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -5427,9 +5572,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "license": "MIT", "engines": { "node": ">=12" @@ -5439,9 +5584,9 @@ } }, "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "funding": [ { "type": "opencollective", @@ -5458,7 +5603,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5492,9 +5637,9 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -5513,32 +5658,10 @@ "node": ">=6" } }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prompts/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/property-information": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.0.0.tgz", - "integrity": "sha512-7D/qOz/+Y4X/rzSB6jKxKUsQnphO046ei8qxG59mtM3RG3DHgTK81HrxrmoDVINJb8NKT5ZsRbwHvQ6B68Iyhg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.2.0.tgz", + "integrity": "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg==", "license": "MIT", "funding": { "type": "github", @@ -5580,9 +5703,9 @@ } }, "node_modules/recma-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz", - "integrity": "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", + "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", "license": "MIT", "dependencies": { "acorn-jsx": "^5.0.0", @@ -5594,6 +5717,9 @@ "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/recma-parse": { @@ -5628,12 +5754,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", - "license": "MIT" - }, "node_modules/regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", @@ -5675,12 +5795,12 @@ } }, "node_modules/rehype-expressive-code": { - "version": "0.41.5", - "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.5.tgz", - "integrity": "sha512-SzKJyu7heDpkt+XE/AqeWsYMSMocE/5mpJXD6CMgstqJHSE9bxGNcLp3zL9Wne3M5iBsS4GJyOD2syV77kRveA==", + "version": "0.43.1", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.43.1.tgz", + "integrity": "sha512-CUOGQVlUcSMSXZgpcq9xL6B+dZqnI3w1R6EZj932XpGgj2Hmy7H6oMqa9W/Z7X2HOILWLWhqu1b9kuYcD+nd6w==", "license": "MIT", "dependencies": { - "expressive-code": "^0.41.5" + "expressive-code": "^0.43.1" } }, "node_modules/rehype-format": { @@ -5758,14 +5878,14 @@ } }, "node_modules/remark-directive": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", - "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-4.0.0.tgz", + "integrity": "sha512-7sxn4RfF1o3izevPV1DheyGDD6X4c9hrGpfdUpm7uC++dqrnJxIZVkk7CoKqcLm0VUMAuOol7Mno3m6g8cfMuA==", "license": "MIT", "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-directive": "^3.0.0", - "micromark-extension-directive": "^3.0.0", + "micromark-extension-directive": "^4.0.0", "unified": "^11.0.0" }, "funding": { @@ -5792,9 +5912,9 @@ } }, "node_modules/remark-mdx": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", - "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", + "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", "license": "MIT", "dependencies": { "mdast-util-mdx": "^3.0.0", @@ -5868,6 +5988,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/retext": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", @@ -5930,12 +6059,12 @@ } }, "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "version": "4.62.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.0.tgz", + "integrity": "sha512-nc72Wgq62I7rtDV4izT5/aaS0zxy3kttkinf9586ApknY3jZO9NYsmtc24fUckA0X7Q2v+ML4a15pdUlV5V/jA==", "license": "MIT", "dependencies": { - "@types/estree": "1.0.8" + "@types/estree": "1.0.9" }, "bin": { "rollup": "dist/bin/rollup" @@ -5945,44 +6074,47 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", + "@rollup/rollup-android-arm-eabi": "4.62.0", + "@rollup/rollup-android-arm64": "4.62.0", + "@rollup/rollup-darwin-arm64": "4.62.0", + "@rollup/rollup-darwin-x64": "4.62.0", + "@rollup/rollup-freebsd-arm64": "4.62.0", + "@rollup/rollup-freebsd-x64": "4.62.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.0", + "@rollup/rollup-linux-arm-musleabihf": "4.62.0", + "@rollup/rollup-linux-arm64-gnu": "4.62.0", + "@rollup/rollup-linux-arm64-musl": "4.62.0", + "@rollup/rollup-linux-loong64-gnu": "4.62.0", + "@rollup/rollup-linux-loong64-musl": "4.62.0", + "@rollup/rollup-linux-ppc64-gnu": "4.62.0", + "@rollup/rollup-linux-ppc64-musl": "4.62.0", + "@rollup/rollup-linux-riscv64-gnu": "4.62.0", + "@rollup/rollup-linux-riscv64-musl": "4.62.0", + "@rollup/rollup-linux-s390x-gnu": "4.62.0", + "@rollup/rollup-linux-x64-gnu": "4.62.0", + "@rollup/rollup-linux-x64-musl": "4.62.0", + "@rollup/rollup-openbsd-x64": "4.62.0", + "@rollup/rollup-openharmony-arm64": "4.62.0", + "@rollup/rollup-win32-arm64-msvc": "4.62.0", + "@rollup/rollup-win32-ia32-msvc": "4.62.0", + "@rollup/rollup-win32-x64-gnu": "4.62.0", + "@rollup/rollup-win32-x64-msvc": "4.62.0", "fsevents": "~2.3.2" } }, "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", - "license": "ISC" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } }, "node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.4.tgz", + "integrity": "sha512-rUCObTnP32Q08R2uuIrt7r9PlEonuTmtuXYcW6s5kjdlj3xbnwe+21yXptAUYcMAABLkYYTtnmzb3w3EDZfueA==", "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -5992,63 +6124,66 @@ } }, "node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.1.tgz", + "integrity": "sha512-lW979AMi+ESidzMv/Lnv+F9bknzLyxLqFI05Sm433vOeRcltgxQmXpnfOOFIAlKtwXU/ksupm2srQoFCkR214g==", "license": "Apache-2.0", "dependencies": { - "@img/colour": "^1.0.0", + "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", - "semver": "^7.7.3" + "semver": "^7.8.4" }, "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + "node": ">=20.9.0" }, "funding": { "url": "https://opencollective.com/libvips" }, "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" + "@img/sharp-darwin-arm64": "0.35.1", + "@img/sharp-darwin-x64": "0.35.1", + "@img/sharp-freebsd-wasm32": "0.35.1", + "@img/sharp-libvips-darwin-arm64": "1.3.0", + "@img/sharp-libvips-darwin-x64": "1.3.0", + "@img/sharp-libvips-linux-arm": "1.3.0", + "@img/sharp-libvips-linux-arm64": "1.3.0", + "@img/sharp-libvips-linux-ppc64": "1.3.0", + "@img/sharp-libvips-linux-riscv64": "1.3.0", + "@img/sharp-libvips-linux-s390x": "1.3.0", + "@img/sharp-libvips-linux-x64": "1.3.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.0", + "@img/sharp-libvips-linuxmusl-x64": "1.3.0", + "@img/sharp-linux-arm": "0.35.1", + "@img/sharp-linux-arm64": "0.35.1", + "@img/sharp-linux-ppc64": "0.35.1", + "@img/sharp-linux-riscv64": "0.35.1", + "@img/sharp-linux-s390x": "0.35.1", + "@img/sharp-linux-x64": "0.35.1", + "@img/sharp-linuxmusl-arm64": "0.35.1", + "@img/sharp-linuxmusl-x64": "0.35.1", + "@img/sharp-webcontainers-wasm32": "0.35.1", + "@img/sharp-win32-arm64": "0.35.1", + "@img/sharp-win32-ia32": "0.35.1", + "@img/sharp-win32-x64": "0.35.1" } }, "node_modules/shiki": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.21.0.tgz", - "integrity": "sha512-N65B/3bqL/TI2crrXr+4UivctrAGEjmsib5rPMMPpFp1xAx/w03v8WZ9RDDFYteXoEgY7qZ4HGgl5KBIu1153w==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-4.2.0.tgz", + "integrity": "sha512-hjNax6o/ylDy9lefQEaSDtzaT3iVNtZ3WmpQnbuQNoG4xvnSKf2kSKbihZVO4JRG1TTMejs7CmNRYlWgAL66pQ==", "license": "MIT", "dependencies": { - "@shikijs/core": "3.21.0", - "@shikijs/engine-javascript": "3.21.0", - "@shikijs/engine-oniguruma": "3.21.0", - "@shikijs/langs": "3.21.0", - "@shikijs/themes": "3.21.0", - "@shikijs/types": "3.21.0", + "@shikijs/core": "4.2.0", + "@shikijs/engine-javascript": "4.2.0", + "@shikijs/engine-oniguruma": "4.2.0", + "@shikijs/langs": "4.2.0", + "@shikijs/themes": "4.2.0", + "@shikijs/types": "4.2.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" + }, + "engines": { + "node": ">=20" } }, "node_modules/sisteransi": { @@ -6058,34 +6193,28 @@ "license": "MIT" }, "node_modules/sitemap": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.0.tgz", - "integrity": "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz", + "integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==", "license": "MIT", "dependencies": { - "@types/node": "^17.0.5", + "@types/node": "^24.9.2", "@types/sax": "^1.2.1", "arg": "^5.0.0", - "sax": "^1.2.4" + "sax": "^1.4.1" }, "bin": { - "sitemap": "dist/cli.js" + "sitemap": "dist/esm/cli.js" }, "engines": { - "node": ">=14.0.0", - "npm": ">=6.0.0" + "node": ">=20.19.5", + "npm": ">=10.8.2" } }, - "node_modules/sitemap/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "license": "MIT" - }, "node_modules/smol-toml": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.0.tgz", - "integrity": "sha512-4zemZi0HvTnYwLfrpk/CF9LOd9Lt87kAt50GnqhMpyF9U3poDAP2+iukq2bZsO/ufegbYehBkqINbsWxj4l4cw==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.6.1.tgz", + "integrity": "sha512-dWUG8F5sIIARXih1DTaQAX4SsiTXhInKf1buxdY9DIg4ZYPZK5nGM1VRIYmEbDbsHt7USo99xSLFu5Q1IqTmsg==", "license": "BSD-3-Clause", "engines": { "node": ">= 18" @@ -6095,12 +6224,12 @@ } }, "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "version": "0.7.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", + "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", "license": "BSD-3-Clause", "engines": { - "node": ">= 8" + "node": ">= 12" } }, "node_modules/source-map-js": { @@ -6128,23 +6257,6 @@ "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==", "license": "MIT" }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -6159,43 +6271,28 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, "node_modules/style-to-js": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.16.tgz", - "integrity": "sha512-/Q6ld50hKYPH3d/r6nr117TZkHR0w0kGGIVfpG9N6D8NymRPM9RqCUv4pRpJ62E5DqOYx2AFpbZMyCPnjQCnOw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", + "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", "license": "MIT", "dependencies": { - "style-to-object": "1.0.8" + "style-to-object": "1.0.14" } }, "node_modules/style-to-object": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.8.tgz", - "integrity": "sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==", + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", "license": "MIT", "dependencies": { - "inline-style-parser": "0.2.4" + "inline-style-parser": "0.2.7" } }, "node_modules/svgo": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", - "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.1.tgz", + "integrity": "sha512-XDpWUOPC6FEibaLzjfe0ucaV0YrOjYotGJO1WpF0Zd+n6ZGEQUsSugaoLq9QkEZtAfQIxT42UChcssDVPP3+/w==", "license": "MIT", "dependencies": { "commander": "^11.1.0", @@ -6204,7 +6301,7 @@ "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", - "sax": "^1.4.1" + "sax": "^1.5.0" }, "bin": { "svgo": "bin/svgo.js" @@ -6223,23 +6320,32 @@ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", "license": "MIT" }, + "node_modules/tinyclip": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/tinyclip/-/tinyclip-0.1.14.tgz", + "integrity": "sha512-F1oWdz8tjT17qe1d5JgDK6z03WGOhYYAN0lK3/D/fzNiy93xswLLEw7pk+3g05onhAy6Bsc6PLNUGhdgVjemMQ==", + "license": "MIT", + "engines": { + "node": "^16.14.0 || >= 17.3.0" + } + }, "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.4.tgz", + "integrity": "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg==", "license": "MIT", "engines": { "node": ">=18" } }, "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "license": "MIT", "dependencies": { "fdir": "^6.5.0", - "picomatch": "^4.0.3" + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -6268,26 +6374,6 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/tsconfck": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", - "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", - "license": "MIT", - "bin": { - "tsconfck": "bin/tsconfck.js" - }, - "engines": { - "node": "^18 || >=20" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -6295,36 +6381,10 @@ "license": "0BSD", "optional": true }, - "node_modules/type-fest": { - "version": "4.39.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.39.1.tgz", - "integrity": "sha512-uW9qzd66uyHYxwyVBYiwS4Oi0qZyUqwjU+Oevr6ZogYiXt99EOYtwvzMSLw1c3lYo2HzJsep/NB23iEVEgjG/w==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "node_modules/ufo": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.3.tgz", - "integrity": "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==", + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", "license": "MIT" }, "node_modules/ultrahtml": { @@ -6340,9 +6400,9 @@ "license": "MIT" }, "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", "license": "MIT" }, "node_modules/unified": { @@ -6390,9 +6450,9 @@ } }, "node_modules/unist-util-is": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", - "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0" @@ -6470,9 +6530,9 @@ } }, "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz", + "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6512,16 +6572,16 @@ } }, "node_modules/unstorage": { - "version": "1.17.4", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.4.tgz", - "integrity": "sha512-fHK0yNg38tBiJKp/Vgsq4j0JEsCmgqH58HAn707S7zGkArbZsVr/CwINoi+nh3h98BRCwKvx1K3Xg9u3VV83sw==", + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", + "integrity": "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg==", "license": "MIT", "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", - "h3": "^1.15.5", - "lru-cache": "^11.2.0", + "h3": "^1.15.10", + "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" @@ -6642,9 +6702,9 @@ } }, "node_modules/vfile-message": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", - "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", "license": "MIT", "dependencies": { "@types/unist": "^3.0.0", @@ -6656,23 +6716,23 @@ } }, "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz", + "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==", "license": "MIT", "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -6681,14 +6741,14 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", - "less": "*", + "less": "^4.0.0", "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" @@ -6730,9 +6790,9 @@ } }, "node_modules/vitefu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", - "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", "license": "MIT", "workspaces": [ "tests/deps/*", @@ -6740,7 +6800,7 @@ "tests/projects/workspace/packages/*" ], "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "vite": { @@ -6767,38 +6827,6 @@ "node": ">=4" } }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/xxhash-wasm": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", @@ -6806,18 +6834,18 @@ "license": "MIT" }, "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", "license": "ISC", "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yocto-queue": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", - "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", "license": "MIT", "engines": { "node": ">=12.20" @@ -6826,60 +6854,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/yocto-spinner": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", - "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", - "license": "MIT", - "dependencies": { - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": ">=18.19" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, - "node_modules/zod-to-json-schema": { - "version": "3.25.1", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", - "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - }, - "node_modules/zod-to-ts": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", - "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", - "peerDependencies": { - "typescript": "^4.9.4 || ^5.0.2", - "zod": "^3" - } - }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", diff --git a/package.json b/package.json index 27ebaa5..430f0f0 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,8 @@ "astro": "astro" }, "dependencies": { - "@astrojs/starlight": "^0.37.6", - "astro": "^5.18.0", - "sharp": "^0.34.0" + "@astrojs/starlight": "^0.40.0", + "astro": "^6.4.7", + "sharp": "^0.35.1" } } From 21fc0edceca950e9d0fb4d2dd95f280e06248a78 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 11:53:35 -0700 Subject: [PATCH 02/16] Add endpoint to serve raw Markdown at .md URLs - Create src/pages/[...slug].md.ts Astro endpoint - Serves exact original source (from src/content/docs/) as text/markdown - Enables /index.md, /guides/.../*.md etc. for LLMs/agents - Works in dev and static builds --- src/pages/[...slug].md.ts | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/pages/[...slug].md.ts diff --git a/src/pages/[...slug].md.ts b/src/pages/[...slug].md.ts new file mode 100644 index 0000000..7c55dc1 --- /dev/null +++ b/src/pages/[...slug].md.ts @@ -0,0 +1,43 @@ +import { getCollection } from 'astro:content'; +import type { APIRoute } from 'astro'; +import { readFileSync, existsSync } from 'node:fs'; +import { join } from 'node:path'; + +const DOCS_DIR = 'src/content/docs'; + +export const getStaticPaths = async () => { + const entries = await getCollection('docs'); + return entries.map((entry) => ({ + params: { slug: entry.id }, + })); +}; + +function resolveDocsFile(id: string): string { + const base = join(process.cwd(), DOCS_DIR, id); + const md = `${base}.md`; + if (existsSync(md)) return md; + const mdx = `${base}.mdx`; + if (existsSync(mdx)) return mdx; + throw new Error(`No source file found for docs entry: ${id}`); +} + +export const GET: APIRoute = ({ params }) => { + const { slug } = params; + + if (!slug) { + return new Response('Not found', { status: 404 }); + } + + try { + const filePath = resolveDocsFile(slug); + const content = readFileSync(filePath, 'utf-8'); + + return new Response(content, { + headers: { + 'Content-Type': 'text/markdown; charset=utf-8', + }, + }); + } catch { + return new Response('Not found', { status: 404 }); + } +}; From cd4ba1c04699dacd8825b346b92ebbb12a5f020a Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 11:58:40 -0700 Subject: [PATCH 03/16] Normalize internal links in raw .md output to not end with trailing slash - Add stripTrailingSlashesFromInternalLinks() helper in the endpoint - Rewrites Markdown links like [text](/path/) -> [text](/path) (and handles #fragments/?queries) - Ensures plain-text Markdown served at *.md URLs uses consistent non-trailing-slash page links - External links and non-page links are left untouched --- astro.config.mjs | 19 ++++++++++--------- src/pages/[...slug].md.ts | 13 ++++++++++++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 06a1652..bc5ccf2 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -4,6 +4,7 @@ import starlight from '@astrojs/starlight'; // https://astro.build/config export default defineConfig({ + trailingSlash: 'never', integrations: [ starlight({ title: 'Charms', @@ -58,11 +59,11 @@ export default defineConfig({ items: [ { label: 'Introduction', - link: '/guides/wallet-integration/introduction/', + link: '/guides/wallet-integration/introduction', }, { label: 'Charms Visualization', - link: '/guides/wallet-integration/visualization/', + link: '/guides/wallet-integration/visualization', }, { label: 'Charms Transactions', @@ -70,27 +71,27 @@ export default defineConfig({ items: [ { label: 'Transactions Overview', - link: '/guides/wallet-integration/transactions/overview/', + link: '/guides/wallet-integration/transactions/overview', }, { label: 'NFT Transfers', - link: '/guides/wallet-integration/transactions/nft/', + link: '/guides/wallet-integration/transactions/nft', }, { label: 'Token Transfers', - link: '/guides/wallet-integration/transactions/token/', + link: '/guides/wallet-integration/transactions/token', }, { label: 'Prover API', - link: '/guides/wallet-integration/transactions/prover-api/', + link: '/guides/wallet-integration/transactions/prover-api', }, { label: 'Signing Transactions', - link: '/guides/wallet-integration/transactions/signing/', + link: '/guides/wallet-integration/transactions/signing', }, { label: 'Broadcasting Transactions', - link: '/guides/wallet-integration/transactions/broadcasting/', + link: '/guides/wallet-integration/transactions/broadcasting', }, ], }, @@ -104,7 +105,7 @@ export default defineConfig({ items: [ { label: 'Spell JSON Reference', - link: '/references/spell-json/', + link: '/references/spell-json', }, ], }, diff --git a/src/pages/[...slug].md.ts b/src/pages/[...slug].md.ts index 7c55dc1..40f3c6e 100644 --- a/src/pages/[...slug].md.ts +++ b/src/pages/[...slug].md.ts @@ -21,6 +21,16 @@ function resolveDocsFile(id: string): string { throw new Error(`No source file found for docs entry: ${id}`); } +function stripTrailingSlashesFromInternalLinks(md: string): string { + // Remove trailing / from internal docs links in Markdown syntax, + // e.g. [text](/guides/foo/) → [text](/guides/foo) + // Also handles fragments: [text](/guides/foo/#bar) and query strings. + return md.replace( + /(\]\()((?:\/[^)\s#?]+?))\/(?=[?#)]|$)/g, + '$1$2' + ); +} + export const GET: APIRoute = ({ params }) => { const { slug } = params; @@ -31,8 +41,9 @@ export const GET: APIRoute = ({ params }) => { try { const filePath = resolveDocsFile(slug); const content = readFileSync(filePath, 'utf-8'); + const normalized = stripTrailingSlashesFromInternalLinks(content); - return new Response(content, { + return new Response(normalized, { headers: { 'Content-Type': 'text/markdown; charset=utf-8', }, From 9e78188915f19d9f32e779f6e88b1fab82ca2a3d Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 13:27:10 -0700 Subject: [PATCH 04/16] =?UTF-8?q?Reorganize=20docs=20per=20Di=C3=A1taxis?= =?UTF-8?q?=20and=20bring=20up=20to=20date=20for=20v15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Restructure the site into the four Diátaxis sections — Tutorials, How-to guides, Explanation, and Reference — replacing the old concepts/guides/references layout, with redirects from every old URL. Update everything to Charms v15 and fill the major gaps: - Explanation: why, apps, spells, transactions, beaming, Scrolls - Reference: CLI, spell structure (logical + serialized + on-chain Bitcoin/Cardano), SDK, Prover API, Scrolls canister - How-to: install, Bitcoin node, app contracts, app keys (versioned apps), call/run the prover (SP1 Prover Network), beaming (eBTC), Scroll outputs, and wallet integration - Tutorials: build an app, cast your first spell on testnet4 Correct stale facts: protocol v15, SP1 -> Groth16 proofs, single-tx OP_RETURN on Bitcoin (no commit/reveal), versioned apps, Cardano. Replace the Starlight-boilerplate README with a real project README and set the `site` config. Co-Authored-By: Claude Opus 4.8 (1M context) --- README.md | 88 ++++---- astro.config.mjs | 121 +++++----- src/content/docs/concepts/apps.md | 59 ----- src/content/docs/concepts/spells.md | 82 ------- src/content/docs/concepts/why.md | 74 ------ src/content/docs/explanation/apps.md | 110 +++++++++ src/content/docs/explanation/beaming.md | 84 +++++++ src/content/docs/explanation/index.md | 24 ++ src/content/docs/explanation/scrolls.md | 78 +++++++ src/content/docs/explanation/spells.md | 113 ++++++++++ src/content/docs/explanation/transactions.md | 86 +++++++ src/content/docs/explanation/why-charms.md | 96 ++++++++ .../docs/guides/charms-apps/cast-spell.md | 62 ------ .../docs/guides/charms-apps/get-started.md | 73 ------ .../docs/guides/charms-apps/introduction.md | 19 -- .../docs/guides/charms-apps/pre-reqs.md | 60 ----- .../guides/wallet-integration/introduction.md | 43 ---- .../transactions/broadcasting.md | 20 -- .../wallet-integration/transactions/nft.md | 119 ---------- .../transactions/overview.md | 48 ---- .../transactions/prover-api.md | 163 -------------- .../transactions/signing.md | 30 --- .../wallet-integration/transactions/token.md | 114 ---------- .../wallet-integration/visualization.md | 120 ---------- src/content/docs/how-to/beam-charms.md | 103 +++++++++ .../docs/how-to/call-the-prover-api.md | 81 +++++++ src/content/docs/how-to/index.md | 34 +++ src/content/docs/how-to/install-charms.md | 53 +++++ src/content/docs/how-to/manage-app-keys.md | 85 +++++++ .../docs/how-to/run-a-prover-server.md | 92 ++++++++ .../docs/how-to/set-up-a-bitcoin-node.md | 73 ++++++ .../docs/how-to/spend-scroll-outputs.md | 62 ++++++ .../wallet-integration/display-charms.md | 69 ++++++ .../docs/how-to/wallet-integration/index.md | 37 +++ .../wallet-integration/sign-and-broadcast.md | 41 ++++ .../wallet-integration/transfer-nfts.md | 54 +++++ .../wallet-integration/transfer-tokens.md | 56 +++++ .../docs/how-to/write-an-app-contract.md | 140 ++++++++++++ src/content/docs/index.mdx | 39 +++- src/content/docs/reference/cli.md | 196 ++++++++++++++++ src/content/docs/reference/index.md | 26 +++ src/content/docs/reference/prover-api.md | 114 ++++++++++ .../docs/reference/scrolls-canister.md | 137 ++++++++++++ src/content/docs/reference/sdk.md | 177 +++++++++++++++ src/content/docs/reference/spell.md | 210 ++++++++++++++++++ src/content/docs/references/spell-json.md | 125 ----------- .../docs/tutorials/build-a-charms-app.md | 108 +++++++++ .../docs/tutorials/cast-your-first-spell.md | 104 +++++++++ src/content/docs/tutorials/index.md | 17 ++ 49 files changed, 2800 insertions(+), 1319 deletions(-) delete mode 100644 src/content/docs/concepts/apps.md delete mode 100644 src/content/docs/concepts/spells.md delete mode 100644 src/content/docs/concepts/why.md create mode 100644 src/content/docs/explanation/apps.md create mode 100644 src/content/docs/explanation/beaming.md create mode 100644 src/content/docs/explanation/index.md create mode 100644 src/content/docs/explanation/scrolls.md create mode 100644 src/content/docs/explanation/spells.md create mode 100644 src/content/docs/explanation/transactions.md create mode 100644 src/content/docs/explanation/why-charms.md delete mode 100644 src/content/docs/guides/charms-apps/cast-spell.md delete mode 100644 src/content/docs/guides/charms-apps/get-started.md delete mode 100644 src/content/docs/guides/charms-apps/introduction.md delete mode 100644 src/content/docs/guides/charms-apps/pre-reqs.md delete mode 100644 src/content/docs/guides/wallet-integration/introduction.md delete mode 100644 src/content/docs/guides/wallet-integration/transactions/broadcasting.md delete mode 100644 src/content/docs/guides/wallet-integration/transactions/nft.md delete mode 100644 src/content/docs/guides/wallet-integration/transactions/overview.md delete mode 100644 src/content/docs/guides/wallet-integration/transactions/prover-api.md delete mode 100644 src/content/docs/guides/wallet-integration/transactions/signing.md delete mode 100644 src/content/docs/guides/wallet-integration/transactions/token.md delete mode 100644 src/content/docs/guides/wallet-integration/visualization.md create mode 100644 src/content/docs/how-to/beam-charms.md create mode 100644 src/content/docs/how-to/call-the-prover-api.md create mode 100644 src/content/docs/how-to/index.md create mode 100644 src/content/docs/how-to/install-charms.md create mode 100644 src/content/docs/how-to/manage-app-keys.md create mode 100644 src/content/docs/how-to/run-a-prover-server.md create mode 100644 src/content/docs/how-to/set-up-a-bitcoin-node.md create mode 100644 src/content/docs/how-to/spend-scroll-outputs.md create mode 100644 src/content/docs/how-to/wallet-integration/display-charms.md create mode 100644 src/content/docs/how-to/wallet-integration/index.md create mode 100644 src/content/docs/how-to/wallet-integration/sign-and-broadcast.md create mode 100644 src/content/docs/how-to/wallet-integration/transfer-nfts.md create mode 100644 src/content/docs/how-to/wallet-integration/transfer-tokens.md create mode 100644 src/content/docs/how-to/write-an-app-contract.md create mode 100644 src/content/docs/reference/cli.md create mode 100644 src/content/docs/reference/index.md create mode 100644 src/content/docs/reference/prover-api.md create mode 100644 src/content/docs/reference/scrolls-canister.md create mode 100644 src/content/docs/reference/sdk.md create mode 100644 src/content/docs/reference/spell.md delete mode 100644 src/content/docs/references/spell-json.md create mode 100644 src/content/docs/tutorials/build-a-charms-app.md create mode 100644 src/content/docs/tutorials/cast-your-first-spell.md create mode 100644 src/content/docs/tutorials/index.md diff --git a/README.md b/README.md index f9f6d31..abcdd87 100644 --- a/README.md +++ b/README.md @@ -1,54 +1,52 @@ -# Starlight Starter Kit: Basics +# Charms documentation -[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](https://starlight.astro.build) +The documentation site for [Charms](https://charms.dev) — programmable tokens on +Bitcoin (and beyond). Built with [Astro](https://astro.build) + +[Starlight](https://starlight.astro.build) and deployed to +[charms.dev](https://charms.dev). -``` -npm create astro@latest -- --template starlight -``` - -[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/withastro/starlight/tree/main/examples/basics) -[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/withastro/starlight/tree/main/examples/basics) -[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/withastro/starlight&create_from_path=examples/basics) -[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fwithastro%2Fstarlight%2Ftree%2Fmain%2Fexamples%2Fbasics&project-name=my-starlight-docs&repository-name=my-starlight-docs) +This site documents **Charms v15**. The protocol source lives at +[github.com/CharmsDev/charms](https://github.com/CharmsDev/charms). -> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! +## Structure -## 🚀 Project Structure +Content lives in `src/content/docs/` and is organized with the +[Diátaxis](https://diataxis.fr) framework — four sections, each serving a +distinct need: -Inside of your Astro + Starlight project, you'll see the following folders and files: - -``` -. -├── public/ -├── src/ -│ ├── assets/ -│ ├── content/ -│ │ ├── docs/ -│ └── content.config.ts -├── astro.config.mjs -├── package.json -└── tsconfig.json -``` +| Section | Directory | For | +| --- | --- | --- | +| **Tutorials** | `tutorials/` | Learning by doing (start here). | +| **How-to guides** | `how-to/` | Accomplishing specific tasks. | +| **Explanation** | `explanation/` | Understanding the concepts. | +| **Reference** | `reference/` | Looking up exact formats and APIs. | -Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory. Each file is exposed as a route based on its file name. +The sidebar and redirects from old URLs are configured in `astro.config.mjs`. +Each page is also served as raw Markdown at its `.md` URL (see +`src/pages/[...slug].md.ts`). -Images can be added to `src/assets/` and embedded in Markdown with a relative link. +## Develop -Static assets, like favicons, can be placed in the `public/` directory. - -## 🧞 Commands - -All commands are run from the root of the project, from a terminal: - -| Command | Action | -| :------------------------ | :----------------------------------------------- | -| `npm install` | Installs dependencies | -| `npm run dev` | Starts local dev server at `localhost:4321` | -| `npm run build` | Build your production site to `./dist/` | -| `npm run preview` | Preview your build locally, before deploying | -| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | -| `npm run astro -- --help` | Get help using the Astro CLI | - -## 👀 Want to learn more? +```sh +npm install +npm run dev # local dev server at http://localhost:4321 +``` -Check out [Starlight’s docs](https://starlight.astro.build/), read [the Astro documentation](https://docs.astro.build), or jump into the [Astro Discord server](https://astro.build/chat). +| Command | Action | +| --- | --- | +| `npm install` | Install dependencies | +| `npm run dev` | Start the dev server | +| `npm run build` | Build the production site to `./dist/` | +| `npm run preview` | Preview the production build locally | + +## Contributing + +- Put each page in the section that matches its *purpose*, not its topic — a + single topic (e.g. spells) legitimately appears across tutorials, how-to, + explanation, and reference. +- Keep the types distinct: tutorials don't dwell on options, how-to guides don't + explain theory, reference stays factual, explanation avoids step-by-step + instructions. +- Internal links are root-relative and omit the trailing slash + (`/reference/spell`), matching `trailingSlash: 'never'`. +- Verify changes build with `npm run build` before opening a PR. diff --git a/astro.config.mjs b/astro.config.mjs index bc5ccf2..e5c5014 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -4,7 +4,27 @@ import starlight from '@astrojs/starlight'; // https://astro.build/config export default defineConfig({ + site: 'https://charms.dev', trailingSlash: 'never', + // Redirects from the pre-Diátaxis URLs to their new homes. + redirects: { + '/concepts/why': '/explanation/why-charms', + '/concepts/apps': '/explanation/apps', + '/concepts/spells': '/explanation/spells', + '/guides/charms-apps/introduction': '/tutorials', + '/guides/charms-apps/pre-reqs': '/how-to/set-up-a-bitcoin-node', + '/guides/charms-apps/get-started': '/tutorials/build-a-charms-app', + '/guides/charms-apps/cast-spell': '/tutorials/cast-your-first-spell', + '/guides/wallet-integration/introduction': '/how-to/wallet-integration', + '/guides/wallet-integration/visualization': '/how-to/wallet-integration/display-charms', + '/guides/wallet-integration/transactions/overview': '/how-to/wallet-integration', + '/guides/wallet-integration/transactions/nft': '/how-to/wallet-integration/transfer-nfts', + '/guides/wallet-integration/transactions/token': '/how-to/wallet-integration/transfer-tokens', + '/guides/wallet-integration/transactions/prover-api': '/how-to/call-the-prover-api', + '/guides/wallet-integration/transactions/signing': '/how-to/wallet-integration/sign-and-broadcast', + '/guides/wallet-integration/transactions/broadcasting': '/how-to/wallet-integration/sign-and-broadcast', + '/references/spell-json': '/reference/spell', + }, integrations: [ starlight({ title: 'Charms', @@ -40,79 +60,70 @@ export default defineConfig({ label: 'GitHub', }, ], + // The sidebar follows the Diátaxis framework (https://diataxis.fr): + // Tutorials (learning), How-to guides (tasks), Explanation + // (understanding), and Reference (information). sidebar: [ { - label: 'Concepts', - items: [{ autogenerate: { directory: 'concepts' } }], + label: 'Tutorials', + items: [ + { label: 'Overview', link: '/tutorials' }, + { label: 'Build a Charms app', link: '/tutorials/build-a-charms-app' }, + { label: 'Cast your first spell', link: '/tutorials/cast-your-first-spell' }, + ], }, { - label: 'Guides', + label: 'How-to guides', items: [ + { label: 'Overview', link: '/how-to' }, + { label: 'Install Charms', link: '/how-to/install-charms' }, + { label: 'Set up a Bitcoin node', link: '/how-to/set-up-a-bitcoin-node' }, + { label: 'Write an app contract', link: '/how-to/write-an-app-contract' }, + { label: 'Manage app keys', link: '/how-to/manage-app-keys' }, + { label: 'Call the Prover API', link: '/how-to/call-the-prover-api' }, + { label: 'Run a prover server', link: '/how-to/run-a-prover-server' }, + { label: 'Beam charms across chains', link: '/how-to/beam-charms' }, + { label: 'Spend Scroll outputs', link: '/how-to/spend-scroll-outputs' }, { - label: 'Charms Apps', - collapsed: false, - items: [{ autogenerate: { directory: 'guides/charms-apps' } }], - }, - { - label: 'Wallet Integration', - collapsed: false, + label: 'Wallet integration', items: [ - { - label: 'Introduction', - link: '/guides/wallet-integration/introduction', - }, - { - label: 'Charms Visualization', - link: '/guides/wallet-integration/visualization', - }, - { - label: 'Charms Transactions', - collapsed: false, - items: [ - { - label: 'Transactions Overview', - link: '/guides/wallet-integration/transactions/overview', - }, - { - label: 'NFT Transfers', - link: '/guides/wallet-integration/transactions/nft', - }, - { - label: 'Token Transfers', - link: '/guides/wallet-integration/transactions/token', - }, - { - label: 'Prover API', - link: '/guides/wallet-integration/transactions/prover-api', - }, - { - label: 'Signing Transactions', - link: '/guides/wallet-integration/transactions/signing', - }, - { - label: 'Broadcasting Transactions', - link: '/guides/wallet-integration/transactions/broadcasting', - }, - ], - }, + { label: 'Overview', link: '/how-to/wallet-integration' }, + { label: 'Display charms', link: '/how-to/wallet-integration/display-charms' }, + { label: 'Transfer NFTs', link: '/how-to/wallet-integration/transfer-nfts' }, + { label: 'Transfer tokens', link: '/how-to/wallet-integration/transfer-tokens' }, + { label: 'Sign and broadcast', link: '/how-to/wallet-integration/sign-and-broadcast' }, ], }, ], }, { - label: 'References', - collapsed: false, + label: 'Explanation', items: [ - { - label: 'Spell JSON Reference', - link: '/references/spell-json', - }, + { label: 'Overview', link: '/explanation' }, + { label: 'Why Charms?', link: '/explanation/why-charms' }, + { label: 'Apps', link: '/explanation/apps' }, + { label: 'Spells', link: '/explanation/spells' }, + { label: 'Transactions', link: '/explanation/transactions' }, + { label: 'Beaming', link: '/explanation/beaming' }, + { label: 'Scrolls', link: '/explanation/scrolls' }, + ], + }, + { + label: 'Reference', + items: [ + { label: 'Overview', link: '/reference' }, + { label: 'CLI', link: '/reference/cli' }, + { label: 'Spell structure', link: '/reference/spell' }, + { label: 'SDK', link: '/reference/sdk' }, + { label: 'Prover API', link: '/reference/prover-api' }, + { label: 'Scrolls canister', link: '/reference/scrolls-canister' }, ], }, { label: 'Whitepaper', link: '/Charms-whitepaper.pdf', - } + attrs: { target: '_blank' }, + }, ], }), ], diff --git a/src/content/docs/concepts/apps.md b/src/content/docs/concepts/apps.md deleted file mode 100644 index 43e632f..0000000 --- a/src/content/docs/concepts/apps.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Apps -description: "Everything is an app" -sidebar: - order: 3 ---- - -Charms exist to make programmable assets possible on Bitcoin. - -So, what are Charms apps? - -Here's the code structure of such app contract (in Rust): - -```rust -use charms_sdk::data::{ - charm_values, check, sum_token_amount, App, Data, Transaction, NFT, TOKEN, -}; - -/// The entry point of the app. This function defines the app contract -/// that needs to be satisfied for the transaction spell to be correct. -pub fn app_contract(app: &App, tx: &Transaction, x: &Data, w: &Data) -> bool { - match app.tag { - NFT => { - check!(nft_contract_satisfied(app, tx, w)) - } - TOKEN => { - check!(token_contract_satisfied(app, tx)) - } - _ => unreachable!(), - } - true -} - -fn nft_contract_satisfied(app: &App, tx: &Transaction, w: &Data) -> bool { - let token_app = &App { - tag: TOKEN, - identity: app.identity.clone(), - vk: app.vk.clone(), - }; - check!(can_mint_nft(app, tx, w) || can_mint_token(&token_app, tx)); - true -} - -fn token_contract_satisfied(token_app: &App, tx: &Transaction) -> bool { - check!(can_mint_token(token_app, tx)); - true -} - -// ... `can_mint_nft` and `can_mint_token` implementations ... -``` - -Get a full working example by running: - -```sh -charms app new my-tokens -``` - -`app_contract` is the predicate that needs to be satisfied by the transaction. If all such predicates (for all apps participating in the spell) are satisfied AND all pre-requisite transactions have correct spells, then and only then this transaction's spell is correct. - \ No newline at end of file diff --git a/src/content/docs/concepts/spells.md b/src/content/docs/concepts/spells.md deleted file mode 100644 index 61dd4f5..0000000 --- a/src/content/docs/concepts/spells.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Spells -description: "What are spells and how do they work?" -sidebar: - order: 2 ---- - -Every Charms transaction contains a **spell**: Charms-related metadata added to the blockchain transaction (similar to Runes' *runestones*). - -Spells are **client-side validated**, meaning that **the users** choose to interpret or ignore them. If they choose to interpret them, they can use `charms` — similar to Ordinals and Runes interpreted by `ord`. - -A *spell* is said to be *correct* if and only if all of these are true: -- it is successfully parsed and interpreted -- makes sense for the transaction (e.g., doesn't produce more Charms outputs than there are Bitcoin outputs) -- has a valid proof - -*Correct spells* can mint, burn and transfer tokens. The practical effect of a *spell* is that tokens are considered parts of the enhanced transaction outputs. - -*Incorrect spells* are ignored. - -Double-spending is prevented by Bitcoin. - -![](../../../assets/images/one-does-not.jpg) - -## What Spells Look Like - -*Spells* create and transform _charms_ via Bitcoin transactions. - -A spell is stored in an `OP_RETURN` output of the transaction: - -``` -OP_RETURN - OP_PUSH "spell" - OP_PUSH $spell_and_proof -``` -where: -- `OP_PUSH "spell"` is a marker identifying the output as a Charms spell. -- `OP_PUSH $spell_and_proof` — CBOR-encoded `(NormalizedSpell, Proof)` tuple (see [v11.0.1 source](https://github.com/CharmsDev/charms/blob/v11.0.1/charms-client/src/lib.rs)). The proof is a Groth16 proof attesting to the correctness of the spell. - - -## Logical Structure of a Spell - -Here is an example of a spell that sends an NFT and some fungible tokens, and also mints some tokens: - -```yaml -version: 11 -tx: - ins: - - 33027a870a0f8c7b3d3114d970b6e67d11b32316ad5b6c58bdc7e0d8e77f7e6a:1 - - 92077a14998b31367efeec5203a00f1080facdb270cbf055f09b66ae0a273c7d:0 - outs: - - 0: - ticker: TOAD - remaining: 30160 - 1: 42 - - 2: 69420 - coins: - - amount: 1000 - dest: 2f7e10b8f6e2089b5bb5dcce96e8dd49ca01012f6506af0fe7bf5d2f2f5db531 - - amount: 1000 - dest: 009fb48961bca8ec68f01ec882f7ec0dc7dc5cc6bcf4ad154f129ea2338f6cd1 -app_public_inputs: - n/f54f6d40bd4ba808b188963ae5d72769ad5212dd1d29517ecc4063dd9f033faa/7df792057addc74f1a6ca23da5b8b82475a7c31c3a4d45266c16a604c62eba4c: - t/7e7e5623a8b44556021171f533a3404b009e7c66edd5a47362c8e54c54a6e058/b25ddd68cd441a2bb0f7113abaaef74983c4e01fc66c7465e1f18363fc80454d: - t/f54f6d40bd4ba808b188963ae5d72769ad5212dd1d29517ecc4063dd9f033faa/7df792057addc74f1a6ca23da5b8b82475a7c31c3a4d45266c16a604c62eba4c: -``` - -In this example we have: - -- `app_public_inputs` — a map of all apps involved in the spell. App is a tuple of `tag/identity/VK` where: - - `tag` is a single character representing the app type (`n` for NFTs, `t` for fungible tokens). - `tag` can be anything, but `n` and `t` have special meaning (simple transfers of NFTs and tokens don't need app contract proofs, so the recursive spell proof can be generated faster). - - `identity` is a 32-byte array identifying the asset within this app. - - `VK` is the verification key hash of the app [implementing the logic](/concepts/apps) of the asset: how it can be minted or burned, staked or used. - - each app value is that app's public input data (may be empty for simple transfers). - -- `tx.ins` — a list of input UTXOs (`txid:vout`) to be spent by the transaction. - -- `tx.outs` — a list of outputs (strings of charms) created by this spell. In each output, keys are app indexes (`0`, `1`, `2`, ...) pointing to apps in `app_public_inputs`, and values are charm data for those apps. - -- `tx.coins` — native coin outputs (Bitcoin sats or Cardano lovelace) for the resulting transaction outputs. - diff --git a/src/content/docs/concepts/why.md b/src/content/docs/concepts/why.md deleted file mode 100644 index 7475176..0000000 --- a/src/content/docs/concepts/why.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Why Charms? -description: "Why should you use Charms to build your next Bitcoin app?" -sidebar: - order: 1 ---- - -Charms is a **programmable assets** protocol and software for Bitcoin (and soon, cross-chain), designed to be -**developer-friendly**. - -Q: There are already a few token standards out there, even on Bitcoin. why create another one? - -In short, because none of them are **programmable**, or particularly developer friendly. And we are fixing this. - -We believe in the magic of programmability. We also believe in decentralization and security of Bitcoin. An -under-appreciated aspect of Bitcoin's security is its UTXO model. It's widely believed that the UTXO model is "hard" to -make programmable. But, with Charms, not impossible 😼 - -Let us introduce: **developer-friendly**, **programmable assets**, implemented directly **on Bitcoin**. - -Because this is kind of magical, we call such tokens *charms*. - -## What are Charms - -Put simply, _charms_ are programmable tokens on top of Bitcoin UTXOs. - -Programmability is needed to do **one thing**: create *apps*. Apps are: - -- tokens -- NFT collections -- DEXes -- Auctions -- ... you (create and) name it! - -App state needs to be stored somehow, and that's what *charms* are for. - -A single *charm* is a token, NFT, instance of arbitrary app state. Structurally, it is an entry of mapping `app -> data` -living on top of a Bitcoin UTXO. And you can have as many as you want, creating a _string of charms_. - -Fungible tokens and NFTs are treated as special cases: - -- a fungible token data (within a *charm*) is its amount (a positive integer, e.g. `69420`), -- NFTs carry **arbitrary** data, which is useful for all kinds of use cases (e.g. remaining token supply — if a - fungible token is managed by an NFT). - -Combining tokens, NFTs and arbitrary apps in *strings of charms* allows for **composability**: - -- a limit order to trade one token for another, -- artist royalty policies for NFTs -- bridging -- ... limitless other things. - -A *string of charms* gets created or spent as one unit, just like a Bitcoin UTXO. *Charms* can **only** exist on top of -UTXOs (such outputs are said to be *charmed*). Because of this, whoever owns a Bitcoin UTXO, can do whatever they want -with the *charms* in it (even destroy them). - -## How are Charms Created - -*Charms* come into existence by the magic of *[spells](/concepts/spells)* added to Bitcoin transactions. - -## Difference from Runes - -[Runes](https://docs.ordinals.com/runes.html) and Ordinals are an inspiration for Charms (among other things). - -Runes are tokens on top of Bitcoin, managed by *runestones* — metadata messages (in `OP_RETURN` -outputs), directing minting and transferring of *runes* (the Runes tokens). Runestones can be viewed as a kind -of [spells](/concepts/spells). - -Runes seem to lean towards [digital artifacts](https://docs.ordinals.com/digital-artifacts.html), collectibles (with -concepts like rarity of a name). - -Charms aim to address **programmability** and **composability**: you can have multiple apps interacting with each other. -Charms -could (perhaps in a not too distant future) even work with Runes. diff --git a/src/content/docs/explanation/apps.md b/src/content/docs/explanation/apps.md new file mode 100644 index 0000000..bfb60f6 --- /dev/null +++ b/src/content/docs/explanation/apps.md @@ -0,0 +1,110 @@ +--- +title: Apps +description: "Everything is an app" +sidebar: + order: 2 +--- + +Charms exist to make programmable assets possible on Bitcoin. The unit of +programmability is the **app**. + +## What an app is + +An app is identified by a triple `tag/identity/vk`: + +- **`tag`** — a single character describing the kind of app. Three tags have + special meaning: `t` for fungible **tokens**, `n` for **NFTs**, and `s` for + [**Scrolls**](/explanation/scrolls). Any other character denotes a general + app whose logic is defined entirely by its contract. +- **`identity`** — a 32-byte value identifying a particular asset *within* the + app (for example, one NFT collection, or one token). +- **`vk`** — the verification key that pins down the app's code: the logic that + governs how its charms may be minted, burned, or transferred. + +A **charm** is one entry in the `app -> data` map carried by a UTXO. So a single +output can hold several charms from several apps at once — a *string of charms*. + +## The app contract + +An app's logic is a single predicate, the **app contract**: + +```rust +use charms_sdk::data::{ + check, App, Data, Transaction, NFT, TOKEN, +}; + +/// The entry point of the app. This function defines the app contract that +/// must be satisfied for a transaction's spell to be correct. +pub fn app_contract(app: &App, tx: &Transaction, x: &Data, w: &Data) -> bool { + match app.tag { + NFT => check!(nft_contract_satisfied(app, tx, w)), + TOKEN => check!(token_contract_satisfied(app, tx)), + _ => unreachable!(), + } + true +} +``` + +The contract receives: + +- **`app`** — the app being evaluated (`tag/identity/vk`), +- **`tx`** — the transaction, including its inputs, outputs and reference inputs + (each carrying its charms), +- **`x`** — the app's **public input** (visible in the spell), +- **`w`** — the app's **private input** (a witness; never published). + +It returns `true` if and only if the transaction is allowed by the app. If every +app participating in a spell is satisfied — and every prerequisite transaction +also has a correct spell — then the spell is **correct**. This is the only thing +that makes charms appear, change, or disappear. + +Get a full working example by running: + +```sh +charms app new my-token +``` + +For the patterns you'll use when writing one, see +[Write an app contract](/how-to/write-an-app-contract); for the exact SDK types +and helpers, see the [SDK reference](/reference/sdk). + +## Simple transfers need no contract + +Just moving an NFT or some tokens from one UTXO to another does **not** require +running (or proving) the app contract. The protocol recognizes two +*simple-transfer* rules that hold by construction: + +- **NFT**: the NFT charms in the outputs are exactly the NFT charms in the + inputs. +- **Fungible token**: the total token amount across outputs equals the total + across inputs. + +Because these cases don't need an app-contract proof, the recursive spell proof +can be generated much faster. You only pay for proving an app contract when you +do something more interesting than a transfer — minting, burning, or any custom +logic. + +## Apps run as WebAssembly + +An app is ordinary Rust that compiles to a small WebAssembly module +(`wasm32-wasip1`) via `charms app build`. During checking and proving, the +module is executed in a sandboxed [wasmi](https://github.com/wasmi-labs/wasmi) +interpreter that feeds it the `(app, tx, x, w)` tuple and records how many cycles +it used. The proof attests that this execution returned `true`. + +## Immutable and versioned apps + +There are two kinds of apps, distinguished by what the `vk` commits to: + +- **Immutable apps**: `vk = SHA-256(wasm binary)`. The verification key is bound + to one exact binary — the code can never change. +- **Versioned apps**: `vk = SHA-256(signing public key)`. The code may be + upgraded over time. Each spell that uses the app must carry a + [BIP-340 signature](/how-to/manage-app-keys) from the key-holder authorizing + the specific binary (and version number) being run. + +Versioned apps let you ship fixes and new features without invalidating +already-issued assets, at the cost of trusting the key-holder to authorize +binaries. Immutable apps are maximally trustless but frozen forever. See +[Manage app keys and signatures](/how-to/manage-app-keys) for how to work with +versioned apps. diff --git a/src/content/docs/explanation/beaming.md b/src/content/docs/explanation/beaming.md new file mode 100644 index 0000000..9a0b064 --- /dev/null +++ b/src/content/docs/explanation/beaming.md @@ -0,0 +1,84 @@ +--- +title: Beaming +description: "Moving charms across chains without a custodial bridge." +sidebar: + order: 5 +--- + +**Beaming** moves a charm from one UTXO to another — including from one chain to +another (Bitcoin ↔ Cardano) — without a custodial bridge and without wrapping. +It is a *teleport*: the charm is destroyed at a source UTXO on the origin chain +and re-created at a destination UTXO on the target chain, with a zero-knowledge +proof tying the two together. + +The canonical worked example is [eBTC](https://github.com/CharmsDev/ebtc), an +app whose token can live on either Bitcoin or Cardano and hop between them. See +[Beam charms across chains](/how-to/beam-charms) for the hands-on version. + +## Not a bridge + +A typical bridge locks an asset in a vault on chain A and mints a wrapped +representation on chain B, trusting whoever controls the vault. Beaming does +neither. There is no separate bridge contract and no wrapped twin: + +- On the **source** side, the charm is *annihilated* as an on-chain asset. The + output that "sends" it carries no token; it only commits to *where* the charm + is going. +- On the **destination** side, the charm is *re-materialized* natively, and the + app's own contract continues to govern it exactly as before. Continuity of the + app's rules is preserved across the hop. + +Soundness comes from proofs, not from a trusted operator. + +## How a beam is tied together + +Two pieces make a beam safe: a **commitment** linking source to destination, and +a **finality proof** showing the source transaction really happened and can't be +reversed. + +### The commitment + +The source spell marks an output as *beamed out* and records a hash that commits +to the destination: `SHA-256(destination UTXO id [‖ nonce])`. Because the hash +binds a *specific* destination UTXO, only the holder of that UTXO can later claim +the beamed charm — no one else can intercept it. The optional nonce lets the +sender commit to a destination up front and blind the commitment. + +The destination spell then spends that committed UTXO and declares, out of band, +that this input is actually drawing the charm from the source UTXO on the other +chain. The proof checks that the destination UTXO (plus nonce) hashes to exactly +the value the source committed to. If it matches, the charm's value is carried +over from the source spell into the destination transaction, where the app +contract sees it as a genuine input. + +### The finality proof + +Re-materializing a charm from a source transaction that could still be reorged +would let an attacker mint value out of thin air. So a beam is only valid if the +source transaction is proven **final**, and the kind of proof depends on the +origin chain: + +- **From Bitcoin** — a *trustless* proof of work: a Merkle proof that the source + transaction is in a block, plus a chain of subsequent block headers carrying + roughly six blocks' worth of accumulated work. No third party is trusted; only + Bitcoin's own proof-of-work. +- **From Cardano** — a finality *attestation*: an Ed25519 signature from a + [Scrolls](/explanation/scrolls) canister certifying that the Cardano + transaction is settled. (Cardano has no compact proof-of-work analogue, so + finality is attested by the Scrolls signer.) + +The source transaction, together with its finality proof, is passed to the +destination prover as a prerequisite transaction (`prev_txs`). The correctness +check refuses to proceed unless every beam source carries an adequate finality +proof. + +## Beaming and Scrolls + +Beaming and [Scrolls](/explanation/scrolls) are distinct mechanisms that share a +trust anchor. Beaming moves charms between UTXOs and is verified by the +commitment and finality proof above. Scrolls are the Internet Computer canisters +that custody and sign Bitcoin/Cardano UTXOs and that attest Cardano finality. +A beam from Cardano relies on a Scrolls signature for its finality proof; a beam +from Bitcoin does not need Scrolls at all. An asset like eBTC combines both: a +Scrolls-managed vault anchors BTC ⇄ eBTC one-to-one, while beaming lets the +resulting eBTC travel between Bitcoin and Cardano. diff --git a/src/content/docs/explanation/index.md b/src/content/docs/explanation/index.md new file mode 100644 index 0000000..5196acc --- /dev/null +++ b/src/content/docs/explanation/index.md @@ -0,0 +1,24 @@ +--- +title: Explanation +description: "Understand the ideas behind Charms: programmable assets on Bitcoin and beyond." +sidebar: + order: 0 +--- + +This section explains how Charms works and why it is built the way it is. It is +for understanding rather than for getting a specific task done — if you are +looking for steps to follow, see the [How-to guides](/how-to), and if you are +looking up exact formats and APIs, see the [Reference](/reference). + +- **[Why Charms?](/explanation/why-charms)** — the problem Charms solves and how + it compares to other Bitcoin token protocols. +- **[Apps](/explanation/apps)** — everything in Charms is an app; what an app + contract is and how it governs assets. +- **[Spells](/explanation/spells)** — the metadata that creates and transforms + charms, and what makes a spell *correct*. +- **[Transactions](/explanation/transactions)** — how spells and their proofs + are embedded in Bitcoin and Cardano transactions. +- **[Beaming](/explanation/beaming)** — moving charms across chains without a + custodial bridge. +- **[Scrolls](/explanation/scrolls)** — Internet Computer canisters that act as + programmable, keyless signers for Charms. diff --git a/src/content/docs/explanation/scrolls.md b/src/content/docs/explanation/scrolls.md new file mode 100644 index 0000000..37d9e65 --- /dev/null +++ b/src/content/docs/explanation/scrolls.md @@ -0,0 +1,78 @@ +--- +title: Scrolls +description: "Internet Computer canisters that act as programmable, keyless signers for Charms." +sidebar: + order: 6 +--- + +**Scrolls** are [Internet Computer](https://internetcomputer.org/) (ICP) +canisters that act as programmable, keyless custodians and signers for Bitcoin +and Cardano. They let a charm (or plain BTC) be controlled by *on-chain logic* +rather than by a single private key. + +For the exact methods of the Bitcoin canister, see the +[Scrolls canister reference](/reference/scrolls-canister); to spend a +Scroll-controlled output, see [Spend Scroll outputs](/how-to/spend-scroll-outputs). + +## Keyless custody via threshold signing + +A Scrolls canister never holds a private key. Instead it uses the Internet +Computer's native **threshold cryptography**: the signing key is held +collectively by an ICP subnet, and the canister asks the subnet to sign on its +behalf (threshold ECDSA for Bitcoin, Schnorr/Ed25519 for Cardano). Each +Scroll-controlled UTXO gets its own address, derived deterministically from the +transaction that created it. + +The decisive property is the canister's **signing policy**. It will sign a spend +only if the spending transaction: + +1. carries a **valid Charms spell**, and +2. pays the configured protocol **fee**. + +That is what makes the custody *programmable*: funds are released not by +presenting a key, but by satisfying on-chain Charms logic — a verified +zero-knowledge spell proof. The canisters are designed to be *blackholed* (no +controllers), so no human can override the policy. + +## Scroll charms + +The charm tag `s` denotes a **Scroll**. A Bitcoin output carrying a Scroll charm +can only be created at a Scrolls-canister-controlled address. The link is +enforced inside the proof: when a spell creates a Scroll output, the prover asks +the canister for the controlling `scriptPubKey` (via its +[`addresses`](/reference/scrolls-canister#addresses) method, signed by the +canister), pins that address into the output, and the spell proof verifies the +canister's signature. Later, spending that output requires the canister to +co-sign — which it does only for a valid spell. (On Cardano, a Scroll app behaves +like any other non-token app.) + +The result is an output that is provably locked to programmable custody: its +fate is decided by Charms logic, with the Scrolls canister as the agent that +enforces it. + +## What Scrolls enable + +- **Vaults and programmable custody** — e.g. the eBTC vault, where BTC is locked + at a Scrolls address and released only by a spell that mints/burns eBTC + one-to-one. See [Beaming](/explanation/beaming). +- **Automated signing and broadcasting** — a client can build a transaction, + sign its own inputs, and hand the rest to the canister's + [`sign_and_submit`](/reference/scrolls-canister#sign_and_submit) method, which + signs the Scroll inputs, enforces the spell-and-fee policy, broadcasts the + transaction, and returns its txid. +- **Cross-chain finality attestation** — the Cardano Scrolls canister signs + certifications used as finality proofs when [beaming](/explanation/beaming) + out of Cardano. + +## The Bitcoin canister at a glance + +The v15 Bitcoin signer is the `scrolls_bitcoin_v15` canister (mainnet +`rpgc6-oqaaa-aaaak-qy3uq-cai`). In day-to-day use only two methods matter: + +- [**`addresses`**](/reference/scrolls-canister#addresses) — returns (and signs) + the canister-controlled `scriptPubKey`s for given outputs. The prover calls + this automatically while building a spell with Scroll outputs. +- [**`sign_and_submit`**](/reference/scrolls-canister#sign_and_submit) — signs + the Scroll inputs of a transaction, checks the spell and fee, broadcasts it, + and returns the txid. This is the only method a wallet normally needs to call + directly. diff --git a/src/content/docs/explanation/spells.md b/src/content/docs/explanation/spells.md new file mode 100644 index 0000000..1adeb38 --- /dev/null +++ b/src/content/docs/explanation/spells.md @@ -0,0 +1,113 @@ +--- +title: Spells +description: "What spells are and what makes them correct." +sidebar: + order: 3 +--- + +Every Charms transaction carries a **spell**: Charms-related metadata added to a +blockchain transaction (similar to Runes' *runestones*). A spell, together with +its proof, is what creates and transforms charms. + +## Client-side validation + +Spells are **client-side validated**. The base chain (Bitcoin or Cardano) knows +nothing about charms — it only sees an ordinary transaction. It is **the users** +who choose to interpret the spell or ignore it. To interpret spells, you run a +Charms client (the `charms` CLI, the prover API, or the `charms-client` +library), much as Ordinals and Runes are interpreted by `ord`. + +This is why charms can exist on Bitcoin without any consensus change: the heavy +lifting — validating that a spell is allowed — is done off-chain by a +zero-knowledge proof that anyone can verify, while Bitcoin does what it does best +and prevents double-spending. + +## What makes a spell *correct* + +A *spell* is **correct** if and only if all of these hold: + +- it parses and is successfully interpreted; +- it makes sense for the transaction (for example, it doesn't produce more charm + outputs than the transaction has outputs); +- every app contract it invokes is satisfied; +- every prerequisite transaction (the ones producing the inputs it spends) also + carries a correct spell; +- it has a **valid proof** attesting to all of the above. + +*Correct spells* can mint, burn, and transfer charms. The practical effect of a +correct spell is that charms are considered part of the enhanced transaction's +outputs. + +*Incorrect spells are ignored.* If a transaction spends charmed UTXOs but its +spell is incorrect (or absent), the charms in those inputs are simply **burned** +— the underlying Bitcoin transaction is still perfectly valid. + +Double-spending is prevented by the base chain. + +![One does not simply make programmable tokens on Bitcoin](../../../assets/images/one-does-not.jpg) + +## What a spell looks like + +You author a spell as YAML (or JSON). Here is one that sends an NFT and some +fungible tokens, and also mints some tokens: + +```yaml +version: 15 +tx: + ins: + - 33027a870a0f8c7b3d3114d970b6e67d11b32316ad5b6c58bdc7e0d8e77f7e6a:1 + - 92077a14998b31367efeec5203a00f1080facdb270cbf055f09b66ae0a273c7d:0 + outs: + - 0: + ticker: TOAD + remaining: 30160 + 1: 42 + - 2: 69420 + coins: + - amount: 1000 + dest: 2f7e10b8f6e2089b5bb5dcce96e8dd49ca01012f6506af0fe7bf5d2f2f5db531 + - amount: 1000 + dest: 009fb48961bca8ec68f01ec882f7ec0dc7dc5cc6bcf4ad154f129ea2338f6cd1 +app_public_inputs: + n/f54f6d40bd4ba808b188963ae5d72769ad5212dd1d29517ecc4063dd9f033faa/7df792057addc74f1a6ca23da5b8b82475a7c31c3a4d45266c16a604c62eba4c: + t/7e7e5623a8b44556021171f533a3404b009e7c66edd5a47362c8e54c54a6e058/b25ddd68cd441a2bb0f7113abaaef74983c4e01fc66c7465e1f18363fc80454d: + t/f54f6d40bd4ba808b188963ae5d72769ad5212dd1d29517ecc4063dd9f033faa/7df792057addc74f1a6ca23da5b8b82475a7c31c3a4d45266c16a604c62eba4c: +``` + +In this example: + +- **`app_public_inputs`** is the map of all apps involved in the spell. Each key + is an app `tag/identity/vk` (see [Apps](/explanation/apps)), and each value is + that app's public input data (empty here, as it is for simple transfers). +- **`tx.ins`** lists the input UTXOs (`txid:vout`) the transaction spends. +- **`tx.outs`** lists the output *strings of charms*. In each output, the keys + are **app indexes** (`0`, `1`, `2`, …) that point into `app_public_inputs` in + sorted-key order, and the values are the charm data for those apps. +- **`tx.coins`** lists the native coin outputs (Bitcoin sats or Cardano + lovelace) that will carry those charms. + +For the complete field reference — including the serialized on-chain form — see +the [Spell structure reference](/reference/spell). + +## The proof + +The interesting half of a spell is the **proof** that travels with it. Charms +generates it with [SP1](https://docs.succinct.xyz/), a zero-knowledge virtual +machine: + +1. A guest program (`charms-spell-checker`) runs the full correctness check + above — including executing every app contract — inside the zkVM, producing a + recursive STARK proof. +2. A second guest program wraps that proof into a small **Groth16** SNARK over + the BN254 curve. + +The resulting Groth16 proof (~260 bytes plus a short header) is what gets +embedded in the on-chain transaction. Because the proof is *recursive*, it also +absorbs the proofs of all prerequisite transactions, so verifying a single spell +transitively establishes the correctness of the entire history behind it. And +because verification is cheap and deterministic, any client can confirm a spell +is correct in milliseconds — without re-running any app code. + +This proof is produced by the [Prover API](/reference/prover-api). For *how* the +proof and spell are attached to a real transaction, see +[Transactions](/explanation/transactions). diff --git a/src/content/docs/explanation/transactions.md b/src/content/docs/explanation/transactions.md new file mode 100644 index 0000000..c2f47a2 --- /dev/null +++ b/src/content/docs/explanation/transactions.md @@ -0,0 +1,86 @@ +--- +title: Transactions +description: "How spells and their proofs are embedded in Bitcoin and Cardano transactions." +sidebar: + order: 4 +--- + +A spell never travels alone — it rides inside an ordinary blockchain +transaction, alongside a [proof](/explanation/spells#the-proof) of its +correctness. This page explains, conceptually, how a spell becomes part of a +real transaction on each supported chain. For the byte-level layout, see the +[Spell structure reference](/reference/spell). + +## Charms live on UTXOs + +Charms inherit the security of the UTXO model. A charm exists only as part of a +transaction *output*; to move or change it, you spend that output in a new +transaction whose spell describes the result. The base chain guarantees each +output is spent at most once, which is exactly what stops charms from being +double-spent. Everything else — what the charms *become* — is decided by the +spell and enforced by its proof. + +Two ingredients are always serialized together and attached to the hosting +transaction: + +- the **normalized spell** — a compact, canonical form of the spell (the same + information you authored in YAML, minus what can be recovered from the hosting + transaction itself, such as the input list); +- the **proof** — the Groth16 SNARK attesting that the spell is correct. + +They are encoded as a single CBOR-serialized `(spell, proof)` pair. Where that +pair *goes* is the only thing that differs between chains. + +## On Bitcoin + +On Bitcoin, a spell is carried by a **single transaction** with the +`(spell, proof)` bytes in an **`OP_RETURN`** output: + +``` +OP_RETURN + OP_PUSH "spell" # marker identifying this as a Charms spell + OP_PUSH +``` + +That one transaction does everything at once: it spends the input UTXOs, creates +the coin outputs that will carry the resulting charms, includes the `OP_RETURN` +output with the spell and proof, optionally pays a Charms protocol fee, and sends +the remainder to a change address. There is **no** separate commit/reveal step. + +Because the Groth16 proof is small, the whole payload fits comfortably in a +single data push. (Charms transactions use a larger `OP_RETURN` than the +historical 80-byte standardness limit; recent Bitcoin Core releases relay them.) + +To read the charms back out, a client scans a transaction for the `OP_RETURN` +spell marker, parses the `(spell, proof)` pair, re-attaches the input list from +the transaction itself, and verifies the proof. + +## On Cardano + +Cardano is also an (extended) UTXO chain, so the model is the same — but the +mechanics differ in three ways: + +1. **Where the spell goes.** Instead of `OP_RETURN`, the `(spell, proof)` bytes + are wrapped as a Plutus `BoundedBytes` value and attached as the **inline + datum** of a dedicated small-ADA output. A client reads the spell back from + that datum and verifies the same Groth16 proof as on Bitcoin. + +2. **Charms are native assets.** Token and NFT charms are represented as Cardano + **native assets**, minted and burned by per-app Plutus minting policies + parameterized by the app's `vk`. Other (non-token) apps are spent from a + shared proxy script address. + +3. **Collateral is required.** Because the transaction runs Plutus scripts, the + ledger requires a **collateral UTXO** — a normal ADA input that is forfeited + only if script validation fails. You supply it when proving a Cardano spell + (`charms spell prove --collateral-utxo …`). Cardano spell transactions are + also co-signed by a [Scrolls](/explanation/scrolls) canister. + +## Prerequisite transactions + +Verifying a spell requires the transactions that produced its inputs — the +**prerequisite transactions** (`prev_txs`). They let the verifier recover the +charms being spent and confirm that each input's own spell was correct. When you +prove or check a spell, you pass these transactions explicitly. In cross-chain +[beaming](/explanation/beaming), a prerequisite transaction also carries a +*finality proof* showing it is irreversibly confirmed on its origin chain. diff --git a/src/content/docs/explanation/why-charms.md b/src/content/docs/explanation/why-charms.md new file mode 100644 index 0000000..09dad65 --- /dev/null +++ b/src/content/docs/explanation/why-charms.md @@ -0,0 +1,96 @@ +--- +title: Why Charms? +description: "Why should you use Charms to build your next Bitcoin app?" +sidebar: + order: 1 +--- + +Charms is a **programmable assets** protocol and toolkit for Bitcoin (and, as of +v15, Cardano too), designed to be **developer-friendly**. + +Q: There are already several token standards out there, even on Bitcoin. Why +create another one? + +In short, because none of them are **programmable**, or particularly +developer-friendly. And we are fixing this. + +We believe in the magic of programmability. We also believe in the +decentralization and security of Bitcoin. An under-appreciated aspect of +Bitcoin's security is its UTXO model. It's widely believed that the UTXO model +is "hard" to make programmable. But, with Charms, not impossible 😼 + +Let us introduce: **developer-friendly**, **programmable assets**, implemented +directly **on Bitcoin**. + +Because this is kind of magical, we call such tokens *charms*. + +## What are charms + +Put simply, _charms_ are programmable tokens on top of Bitcoin UTXOs. + +Programmability is needed to do **one thing**: create *apps*. Apps are: + +- tokens +- NFT collections +- DEXes +- auctions +- ... you (create and) name it! + +App state needs to be stored somehow, and that's what *charms* are for. + +A single *charm* is a token, an NFT, or an instance of arbitrary app state. +Structurally, it is an entry of a mapping `app -> data` living on top of a +Bitcoin UTXO. And you can have as many as you want, creating a _string of +charms_. + +Fungible tokens and NFTs are treated as special cases: + +- a fungible token's data (within a *charm*) is its amount (a positive integer, + e.g. `69420`), +- NFTs carry **arbitrary** data, which is useful for all kinds of use cases + (e.g. the remaining token supply — if a fungible token is managed by an NFT). + +Combining tokens, NFTs and arbitrary apps in *strings of charms* allows for +**composability**: + +- a limit order to trade one token for another, +- artist royalty policies for NFTs, +- bridging, +- ... limitless other things. + +A *string of charms* is created or spent as one unit, just like a Bitcoin UTXO. +*Charms* can **only** exist on top of UTXOs (such outputs are said to be +*charmed*). Because of this, whoever owns a Bitcoin UTXO can do whatever they +want with the *charms* in it (even destroy them). + +To learn how apps define and govern charms, read [Apps](/explanation/apps). + +## How are charms created + +*Charms* come into existence by the magic of *[spells](/explanation/spells)* +added to blockchain transactions. + +## Bitcoin and beyond + +Charms started on Bitcoin and the protocol is designed around Bitcoin's UTXO +model. As of v15, the same charms can also live on **Cardano** (an eUTXO chain), +and they can move between chains through [beaming](/explanation/beaming) — a +trust-minimized teleport that needs no custodial bridge. + +## Difference from Runes + +[Runes](https://docs.ordinals.com/runes.html) and Ordinals are an inspiration +for Charms (among other things). + +Runes are tokens on top of Bitcoin, managed by *runestones* — metadata messages +(in `OP_RETURN` outputs) directing the minting and transferring of *runes* (the +Runes tokens). Runestones can be viewed as a kind of +[spells](/explanation/spells). + +Runes lean towards [digital +artifacts](https://docs.ordinals.com/digital-artifacts.html) and collectibles +(with concepts like rarity of a name). + +Charms aim to address **programmability** and **composability**: you can have +multiple apps interacting with each other. Charms could (perhaps in a not too +distant future) even work with Runes. diff --git a/src/content/docs/guides/charms-apps/cast-spell.md b/src/content/docs/guides/charms-apps/cast-spell.md deleted file mode 100644 index 3a6f8d2..0000000 --- a/src/content/docs/guides/charms-apps/cast-spell.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Cast a Spell -sidebar: - order: 3 -next: false ---- - -Now that we have implemented an app, we're ready to cast a spell onto a real Bitcoin transaction. We're going to use -`bitcoin-cli` to interact with the Bitcoin network. - -**Quick note:** Check if you have [pre-requisites](/guides/charms-apps/pre-reqs) installed. - -**Important:** we assume `bitcoin-cli` is aliased as `b`: - -```sh -alias b=bitcoin-cli -``` - -## Using an app - -We've just tested the app with an NFT-minting spell. Let's use it on Bitcoin `testnet4` (we have a node set up -in [pre-requisites](/guides/charms-apps/pre-reqs)). - -Prepare: -```sh -app_bin=$(charms app build) - -# pick from the output of `bitcoin-cli listunspent` -change_address=$(b getrawchangeaddress) - -# set dest and amount env vars used by the spell template -# (dest is a hex-encoded destination derived from a Bitcoin address) -export dest_0=$(charms util dest --addr=$(b getnewaddress)) -export amount_0=1000 - -export RUST_LOG=info -``` - -Run: -```sh -cat ./spells/mint-nft.yaml | envsubst | charms spell prove \ - --app-bins=${app_bin} \ - --prev-txs=$prev_txs \ - --private-inputs=<(cat ./spells/mint-nft-private.yaml | envsubst) \ - --change-address=$change_address -``` - -This will create (but not yet sign) a Bitcoin transaction containing the spell and its proof in an `OP_RETURN` output. - -`charms spell prove` prints the hex-encoded transaction at the end of its output, which looks like a JSON -array (because it is a JSON array): - -``` -[{"bitcoin":"020000000001015f...57505efa00000000"}] -``` - -You can now sign and broadcast the transaction: - -```sh -b signrawtransactionwithwallet "020000000001015f...57505efa00000000" -b sendrawtransaction "020000000001015f...57505efa00000000" -``` diff --git a/src/content/docs/guides/charms-apps/get-started.md b/src/content/docs/guides/charms-apps/get-started.md deleted file mode 100644 index 486af67..0000000 --- a/src/content/docs/guides/charms-apps/get-started.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: Getting Started -sidebar: - order: 2 ---- - -Let's get started with Charms! This guide will walk you through building your Charms app in a few minutes. - -:::note -Make sure you have [Rust](https://rust-lang.org/) and the Protocol Buffers compiler [`protoc`](https://protobuf.dev/downloads/) installed. -::: - -Install Charms CLI: - -```sh -## important to have this end with `/target` (a dependency issue) -export CARGO_TARGET_DIR=$(mktemp -d)/target -cargo install --locked charms -``` - -## Create an app - -This will create a directory initialized with a Git repo for your new Charms app: - -```sh -charms app new my-token - -cd ./my-token -cargo generate-lockfile -``` - -This will print out the verification key for your new app: - -```sh -app_bin=$(charms app build) -charms app vk "$app_bin" -``` - -(something like this:) - -``` -8e877d70518a5b28f5221e70bd7ff7692a603f3a26d7076a5253e21c304a354f -``` - -Test the app for a spell with a simple NFT mint example: - -```sh -export app_vk=$(charms app vk) - -# set to a UTXO you're spending (you can see what you have by running `b listunspent`) -export in_utxo_0="d8fa4cdade7ac3dff64047dc73b58591ebe638579881b200d4fea68fc84521f0:0" - -export app_id=$(echo -n "${in_utxo_0}" | sha256sum | cut -d' ' -f1) - -# convert an address to hex-encoded destination for spell YAML -export dest_0=$(charms util dest --addr="tb1p3w06fgh64axkj3uphn4t258ehweccm367vkdhkvz8qzdagjctm8qaw2xyv") -export amount_0=1000 - -prev_txs=02000000000101a3a4c09a03f771e863517b8169ad6c08784d419e6421015e8c360db5231871eb0200000000fdffffff024331070000000000160014555a971f96c15bd5ef181a140138e3d3c960d6e1204e0000000000002251207c4bb238ab772a2000906f3958ca5f15d3a80d563f17eb4123c5b7c135b128dc0140e3d5a2a8c658ea8a47de425f1d45e429fbd84e68d9f3c7ff9cd36f1968260fa558fe15c39ac2c0096fe076b707625e1ae129e642a53081b177294251b002ddf600000000 - -cat ./spells/mint-nft.yaml | envsubst | charms spell check \ - --prev-txs=${prev_txs} \ - --app-bins=${app_bin} \ - --private-inputs=<(cat ./spells/mint-nft-private.yaml | envsubst) -``` - -The spell template (`./spells/mint-nft.yaml`) references env variables we just set. The private inputs file (`./spells/mint-nft-private.yaml`) passes the minting UTXO to the app contract as a witness. - -If all is well, you should see that the app contract for minting an NFT has been satisfied. - -To continue playing with the other example spells, keep the same `app_id` value: you create the `app_id` value for a -newly minted NFT, and then keep using it for the lifetime of the NFT and any associated fungible tokens (if the app -supports them). diff --git a/src/content/docs/guides/charms-apps/introduction.md b/src/content/docs/guides/charms-apps/introduction.md deleted file mode 100644 index ffbc97c..0000000 --- a/src/content/docs/guides/charms-apps/introduction.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Introduction -sidebar: - order: 0 ---- - -By following this guide, you'll learn how to create Charms apps, enabling use cases such as collectibles, tokens, and programmable assets on Bitcoin without requiring additional blockchains or layer-2 solutions. - -## What You'll Learn - -- How to set up your environment for Charms development -- How to create a Charms app -- How to cast a spell onto a Bitcoin transaction - -## Sections - -1. [Pre-Requisites](/guides/charms-apps/pre-reqs) -2. [Getting Started](/guides/charms-apps/get-started) -3. [Cast a Spell](/guides/charms-apps/cast-spell) diff --git a/src/content/docs/guides/charms-apps/pre-reqs.md b/src/content/docs/guides/charms-apps/pre-reqs.md deleted file mode 100644 index eca3443..0000000 --- a/src/content/docs/guides/charms-apps/pre-reqs.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Pre-Requisites -sidebar: - order: 1 ---- - -### Bitcoin Core - -Bitcoin Core v28.0 or later is required (we're going to use `testnet4`). You can install it with Homebrew: - -```sh -brew install bitcoin -``` - -This guide assumes a bitcoin node running with the following configuration (`bitcoin.conf`): - -``` -server=1 -testnet4=1 -txindex=1 -addresstype=bech32m -changetype=bech32m -``` - -`bitcoin.conf` is usually located at: -- macOS: `~/Library/Application Support/Bitcoin/bitcoin.conf`, -- Linux: `~/.bitcoin/bitcoin.conf`. - -**Important:** we assume `bitcoin-cli` is aliased as `b`: - -```sh -alias b=bitcoin-cli -``` - -Make sure you have a wallet loaded: - -```sh -b createwallet testwallet # create a wallet (you might already have one) -b loadwallet testwallet # load the wallet (bitcoind doesn't do it automatically when it starts) -``` - -### Test BTC - -Get some test BTC: - -```sh -b getnewaddress # prints out a new address associated with your wallet -``` - -Visit https://mempool.space/testnet4/faucet and get some test BTC to the address you just created. Get at least 50000 -sats (0.0005 (test) BTC). Also, get more than one UTXO, so either tap the faucet more than once or send some sats within -your wallet to get some small UTXOs and at least one larger one (>= 10000 sats). - -### jq - -You will also need to have `jq` installed: - -```sh -brew install jq -``` diff --git a/src/content/docs/guides/wallet-integration/introduction.md b/src/content/docs/guides/wallet-integration/introduction.md deleted file mode 100644 index 03abc4c..0000000 --- a/src/content/docs/guides/wallet-integration/introduction.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Introduction -sidebar: - order: 1 ---- - -This guide provides wallet providers with the technical specifications needed to integrate Charms support into their wallets. - -By implementing this protocol, wallet providers can offer their users the ability to view, transfer, and interact with Charms, enabling use cases such as collectibles, tokens, and programmable assets on Bitcoin. - -## End Results - -By implementing this protocol, wallet providers can offer their users the ability to: - -- View and manage Charms assets -- Transfer Charms (both NFTs and fungible tokens) -- Interact with Charms-enabled applications -- Participate in the growing Charms ecosystem - -## Integration Steps - -Charms wallet integration consists of several components: - -1. **Visualization**: Displaying Charms assets in the wallet interface -2. **Transfer NFTs**: Enabling users to send NFT charms -3. **Transfer Fungible Tokens**: Enabling users to send fungible token charms -4. **Wallet features considerations**: Some current operations, like UTXO consolidation, need to be Charms-compliant - -## Guide Sections - -1. Introduction (this page) -2. [Charms Visualization](/guides/wallet-integration/visualization) -3. [Charms Transfer](/guides/wallet-integration/transactions/overview) - - [Transfer NFTs](/guides/wallet-integration/transactions/nft) - - [Transfer Tokens](/guides/wallet-integration/transactions/token) - - [Prover API](/guides/wallet-integration/transactions/prover-api) - - [Signing Transactions](/guides/wallet-integration/transactions/signing) - - [Broadcasting Transactions](/guides/wallet-integration/transactions/broadcasting) - -## References - -- [Spell JSON](/references/spell-json) - diff --git a/src/content/docs/guides/wallet-integration/transactions/broadcasting.md b/src/content/docs/guides/wallet-integration/transactions/broadcasting.md deleted file mode 100644 index 3494cc2..0000000 --- a/src/content/docs/guides/wallet-integration/transactions/broadcasting.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: Broadcasting Transactions -sidebar: - order: 7 ---- - -After signing the spell transaction, it must be broadcast to the Bitcoin network. - -## Broadcasting - -Send the signed transaction using standard Bitcoin APIs: - -```bash -bitcoin-cli sendrawtransaction -``` - -## Important Considerations - -- **Mempool Acceptance**: The transaction must be accepted into the mempool to ensure proper processing. Validate the transaction before submitting it. -- **Fee Rates**: When proving the spell, use an adequate fee rate (defaults to 2.0 sats per vB) to ensure acceptance to the mempool and ultimately, inclusion in the block. The fee rate is specified in the Prover API request. diff --git a/src/content/docs/guides/wallet-integration/transactions/nft.md b/src/content/docs/guides/wallet-integration/transactions/nft.md deleted file mode 100644 index d9290bb..0000000 --- a/src/content/docs/guides/wallet-integration/transactions/nft.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: NFT Transfers -sidebar: - order: 2 ---- - -NFT transfer involves sending an NFT charm to a new UTXO. We will cover how to send one NFT charm to a single destination. - -:::note -A transaction can send multiple NFTs to one or more outputs. To achieve that -1. add apps defining those NFTs, -2. add inputs with those NFTs to the list of inputs and -3. add the NFTs to transaction outputs. -::: - -## Spell JSON for NFT Transfers - -For NFT transfers, the entire charm is sent to a single destination. Here's the Spell JSON structure for an NFT transfer: - -```json -{ - "version": 11, - "tx": { - "ins": [ - ":" - ], - "outs": [ - { - "0": { - - } - } - ], - "coins": [ - { - "amount": 1000, - "dest": "" - } - ] - }, - "app_public_inputs": { - "n//": null - } -} -``` - -:::note -The simplest case is when the transaction does **not involve** anything beside simple transfers. If it does (e.g. new NFTs are minted or any inputs or outputs contain charms that are neither tokens nor NFTs), the transaction must satisfy the app contracts involved. We will describe how to deal with this in the [Prover API](/guides/wallet-integration/transactions/prover-api) section. -::: - -## Key Components - -- **`version`**: Must be `11` for Charms `v11.0.1` -- **`app_public_inputs`**: Lists NFT app(s) involved in the spell (`null` for simple transfers) -- **`tx.ins`**: Source UTXO list (`txid:vout`) -- **`tx.outs`**: Destination charm outputs, keyed by app index (`"0"`, `"1"`, ...) -- **`tx.coins`**: Native coin outputs (`amount`, hex-encoded `dest`) - -## Implementation Steps - -1. **Retrieve Charm Data**: Get the charm's details from the source UTXO -2. **Construct the Spell JSON**: Fill in `tx` and `app_public_inputs` (see [Spell JSON Reference](/references/spell-json)) -3. **Add Coin Outputs**: Build `tx.coins` with destination hex (`charms util dest`) -4. **Proceed to Prover API**: Use this JSON in the Prover API call (see [Prover API](/guides/wallet-integration/transactions/prover-api)) - -## Example - -Here's an example of a completed Spell JSON for an NFT transfer: - -```json -{ - "version": 11, - "tx": { - "ins": [ - "eb711823b50d368c5e0121649e414d78086cad69817b5163e871f7039ac0a4a3:0" - ], - "outs": [ - { - "0": { - "ticker": "CHARMIX", - "name": "Panoramix #1", - "description": "An Ancient magician from the Gallia", - "image": "https://shorturl.at/KfUka", - "image_hash": "eb6e19663b72ab41354462cb2d3e03a97a745d0d2874f5d010c9b5c8f2544e9c", - "url": "https://charms.dev" - } - } - ], - "coins": [ - { - "amount": 1000, - "dest": "2f7e10b8f6e2089b5bb5dcce96e8dd49ca01012f6506af0fe7bf5d2f2f5db531" - } - ] - }, - "app_public_inputs": { - "n/af50d82d1e47e77ef5d03d1f6a1280eb137c91a51d696edcc0d2cc9351659508/a0029d4e7f8ba7361cde6004561c6209d968bd3686c456504cd0005e19ac1a2f": null - } -} -``` - -**Note:** The following fields are (optional) properties of an NFT charm itself (recommended by [CHIP-420](https://github.com/CharmsDev/charms/blob/main/CHIPs/CHIP-0420)): -- **`ticker`**: The ticker or symbol for the charm (e.g., `"ticker": "CHARMIX"`) -- **`name`**: The name of the NFT (e.g., `"name": "Panoramix #1"`) -- `description`: A description of the NFT (e.g., `"description": "An Ancient magician from the Gallia"`) -- **`image`**: A URL to the image of the NFT (e.g., `"image": "https://shorturl.at/KfUka"`) -- **`image_hash`**: A hash of the image for verification (e.g., `"image_hash": "eb6e19663b72ab41354462cb2d3e03a97a745d0d2874f5d010c9b5c8f2544e9c"`) -- **`url`**: A URL for more information about the NFT (e.g., `"url": "https://charms.dev"`) -- (other fields may be added as needed, depending on the app's requirements) - -## UI Considerations - -When implementing NFT transfers in your wallet UI: - -- Clearly display the NFT being transferred -- Show the destination address in a user-friendly format -- Provide transaction fee information -- Include confirmation steps before proceeding -- Display transaction status updates during the process diff --git a/src/content/docs/guides/wallet-integration/transactions/overview.md b/src/content/docs/guides/wallet-integration/transactions/overview.md deleted file mode 100644 index b46844c..0000000 --- a/src/content/docs/guides/wallet-integration/transactions/overview.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Transactions Overview -sidebar: - order: 1 ---- - -Charms, like other digital assets can be transferred from one address to another, while preserving their unique properties. Charms transactions are inscribed with special pieces of data (called _spells_) within regular Bitcoin transactions. - -A correct spell has a succinct zero-knowledge proof that can be verified by anyone using a Charms client (as CLI, API or library). The containing transaction and its previous transactions (producing the inputs being spent) are the public inputs the proof is verified against. - -:::note -If a transaction doesn't have a correct spell (for whatever reason) **and** spends outputs with charms, the transaction may still be a valid Bitcoin transaction, but the charms in its inputs are effectively burned if the transaction is accepted in the blockchain. -::: - -## Asset Preservation Rules - -There are two types of _simple transfers_ in Charms, corresponding to the two special types of charms — NFTs and (fungible) tokens. A _simple transfer_ of assets defined by an app does not require to produce the proof of the app contract being satisfied by the transaction: simple asset preservation rules are sufficient: - -1. **NFT** transfers: The entire charm is transferred to a new output unchanged. For NFT apps involved in the transaction, the transaction is a simple transfer with regard to the app (the asset defined by the app), if and only if the NFTs in the outputs are exactly the same as the NFTs in the inputs. - -2. **Fungible Token** transfers: For (fungible) token apps involved in the transaction, the transaction is a simple transfer with regard to the app (the asset defined by the app), if and only if the total amount of the token in all outputs equals the total amount of the token in the inputs. - -## Spell Transactions - -A spell is embedded in a single Bitcoin transaction as an `OP_RETURN` output containing the spell data and its zero-knowledge proof. The Prover API generates this transaction from a spell definition. - -## The Transfer Process - -The complete transfer process involves several key steps: - -1. **Prepare the Spell JSON**: Specify the charms and transfer details -2. **Call the Prover API**: Generate the spell transaction -3. **Sign the Transaction**: Sign the spell transaction -4. **Broadcast the Transaction**: Send the transaction to the Bitcoin network - -## Next Steps - -The following sections will guide you through each step of the transfer process in detail: - -- [Transfer NFTs](/guides/wallet-integration/transactions/nft): How to transfer an NFT charm -- [Transfer Tokens](/guides/wallet-integration/transactions/token): How to transfer fungible tokens -- [Prover API](/guides/wallet-integration/transactions/prover-api): How to use the Prover API to generate transactions -- [Signing Transactions](/guides/wallet-integration/transactions/signing): How to sign Charms transactions -- [Broadcasting Transactions](/guides/wallet-integration/transactions/broadcasting): How to broadcast transactions to the network - -## References - -- [Spell JSON](/references/spell-json): Detailed explanation of the Spell JSON format diff --git a/src/content/docs/guides/wallet-integration/transactions/prover-api.md b/src/content/docs/guides/wallet-integration/transactions/prover-api.md deleted file mode 100644 index 2ea2fc2..0000000 --- a/src/content/docs/guides/wallet-integration/transactions/prover-api.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -title: Prover API -sidebar: - order: 5 ---- - -The Prover API generates the spell transaction for Charms operations. You can use the hosted service or run your own prover server. - -## API Endpoint - -``` -POST /spells/prove -``` - -### Hosted service - -The Charms CLI (when built without the `prover` feature) calls the hosted proving service by default: - -``` -https://v11.charms.dev/spells/prove -``` - -You can override this URL by setting the `CHARMS_PROVE_API_URL` environment variable. - -### Self-hosted server - -Run your own prover: - -```bash -charms server -``` - -Then use: -``` -http://localhost:17784/spells/prove -``` - -Readiness check: - -``` -GET http://localhost:17784/ready -``` - -The self-hosted server accepts both `application/json` and `application/cbor` request bodies (auto-detected from the `Content-Type` header) and responds in the same format. - -## Request Format - -Send a `POST` request with a JSON body containing the following fields: - -```javascript -const requestBody = { - spell: { - version: 11, - tx: { - ins: [":"], - outs: [{ "0": { ticker: "EXAMPLE", remaining: 100000 } }], - coins: [{ amount: 1000, dest: "" }] - }, - app_public_inputs: { - "n//": null - } - }, - app_private_inputs: {}, - tx_ins_beamed_source_utxos: {}, - binaries: {}, - prev_txs: [ - { bitcoin: "020000000001..." } - ], - change_address: "tb1p...", - fee_rate: 2.0, - chain: "bitcoin" -}; -``` - -### Parameters - -- **`spell`**: The spell object (same structure as [Spell JSON](/references/spell-json)) -- **`app_private_inputs`**: Optional map of app spec (`tag/identity/vk`) to private input data -- **`tx_ins_beamed_source_utxos`**: Optional map for beamed inputs (`input_index -> [source_utxo, nonce]`) -- **`binaries`**: Optional map of app verification key (hex) to app binary bytes -- **`prev_txs`**: Previous transactions needed for validation/proving (chain-tagged, e.g. `{ bitcoin: "hex..." }`) -- **`change_address`**: Required change address for the target chain -- **`fee_rate`**: Optional Bitcoin fee rate in sats/vB (defaults to `2.0`) -- **`chain`**: Target chain (`bitcoin` or `cardano`) -- **`collateral_utxo`**: Optional Cardano collateral UTXO (`txid:vout`), required for Cardano proving flows - -## Making the API Call - -Here's an example of how to call the Prover API: - -```javascript -// API endpoint (self-hosted or use https://v11.charms.dev/spells/prove) -const proveApiUrl = 'http://localhost:17784/spells/prove'; - -// Build the spell object (see Spell JSON reference for full structure) -const spell = { - version: 11, - tx: { - ins: ["eb711823b50d368c5e0121649e414d78086cad69817b5163e871f7039ac0a4a3:0"], - outs: [{ "0": { ticker: "CHARMIX", name: "Panoramix #1" } }], - coins: [{ amount: 1000, dest: "2f7e10b8f6e2089b5bb5dcce96e8dd49ca01012f6506af0fe7bf5d2f2f5db531" }] - }, - app_public_inputs: { - "n/af50d82d1e47e77ef5d03d1f6a1280eb137c91a51d696edcc0d2cc9351659508/a0029d4e7f8ba7361cde6004561c6209d968bd3686c456504cd0005e19ac1a2f": null - } -}; - -// Request body -const requestBody = { - spell, - app_private_inputs: {}, - tx_ins_beamed_source_utxos: {}, - binaries: {}, - prev_txs: [ - { bitcoin: "020000000001..." } - ], - change_address: "tb1putrfz7kq9yh3jymjcumq9heu9s4q7nmm8x7k55462n9rua408y9svaw3uv", - fee_rate: 2.0, - chain: "bitcoin" -}; - -// Make the API call -const response = await fetch(proveApiUrl, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(requestBody) -}); - -// Response contains the spell transaction -const result = await response.json(); -const spellTx = result[0]; -``` - -## Response Format - -The API response is a JSON array containing the chain-tagged spell transaction. - -```json -[ - { "bitcoin": "hex_encoded_spell_tx" } -] -``` - -The transaction includes the spell and its proof in an `OP_RETURN` output. - -For Cardano, entries are tagged as `{ "cardano": ... }`. - -## Error Handling - -The API may return error responses in the following cases: - -- **HTTP 400**: Invalid spell, missing required parameters, invalid UTXO references -- **HTTP 500**: Transient prover failures (retry with backoff) - -Implement proper error handling to catch and process these errors in your application. - -## Implementation Tips - -- Validate the Spell JSON before sending it to the API -- Ensure the funding UTXO has sufficient value to cover the transaction fees -- Use appropriate fee rates based on network conditions -- Implement retry logic for temporary server errors (HTTP 500) -- Store the transaction securely until it is signed and broadcast diff --git a/src/content/docs/guides/wallet-integration/transactions/signing.md b/src/content/docs/guides/wallet-integration/transactions/signing.md deleted file mode 100644 index dfac573..0000000 --- a/src/content/docs/guides/wallet-integration/transactions/signing.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Signing Transactions -sidebar: - order: 6 ---- - -After generating the spell transaction using the Prover API, it must be signed before it can be broadcast. - -## Signing the Spell Transaction - -The Prover API returns a single transaction that spends the input UTXOs and includes the spell in an `OP_RETURN` output. Sign the transaction with the keys for the funding UTXOs: - -```bash -bitcoin-cli signrawtransactionwithwallet -``` - -## Key Points for Wallet Providers - -- **Signature Type**: Charms use Taproot outputs, so the wallet needs to support Taproot (Schnorr signatures). - -## Library Support - -Most modern Bitcoin libraries support Taproot signing, including: - -- Bitcoin Core -- bitcoinjs-lib -- rust-bitcoin -- btcd - -Use your existing wallet infrastructure and signing libraries, just ensure they support Taproot and Schnorr signatures. diff --git a/src/content/docs/guides/wallet-integration/transactions/token.md b/src/content/docs/guides/wallet-integration/transactions/token.md deleted file mode 100644 index 312d7b2..0000000 --- a/src/content/docs/guides/wallet-integration/transactions/token.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Fungible Token Transfers -sidebar: - order: 3 ---- - -Token transfers involve spending one of more outputs with tokens, and creating one or more destination outputs with the same total amount of tokens. - -## Spell JSON for Token Transfers - -Here's the Spell JSON structure for a token transfer: - -```json -{ - "version": 11, - "tx": { - "ins": [ - ":", - ":" - ], - "outs": [ - { - "0": - }, - { - "0": - } - ], - "coins": [ - { - "amount": 1000, - "dest": "" - }, - { - "amount": 1000, - "dest": "" - } - ] - }, - "app_public_inputs": { - "t//": null - } -} -``` - -:::note -The simplest case is when the transaction does **not involve** anything beside simple transfers. If it does (e.g. new tokens are minted or any inputs or outputs contain charms that are neither tokens nor NFTs), the transaction must satisfy the app contracts involved. We will describe how to deal with this in the [Prover API](/guides/wallet-integration/transactions/prover-api) section. -::: - -## Key Components - -- **`version`**: Must be `11` for Charms `v11.0.1` -- **`app_public_inputs`**: Lists apps involved in the spell (for simple token transfers use `null` value) -- **`tx.ins`**: Source UTXO list (`txid:vout`) -- **`tx.outs`**: Destination charm outputs, keyed by app index (`"0"`, `"1"`, ...) -- **`tx.coins`**: Native coin outputs; `dest` is a hex destination (`charms util dest`) - - -## Implementation Steps - -1. **Retrieve Token Data**: Collect source UTXOs and token amounts -2. **Calculate Amounts**: Determine transfer and change token amounts -3. **Construct the Spell JSON**: Fill in `tx` and `app_public_inputs` (see [Spell JSON Reference](/references/spell-json)) -4. **Add Coin Outputs**: Build `tx.coins` entries (`amount`, `dest`) for Bitcoin outputs -5. **Proceed to Prover API**: Use this JSON in the Prover API call (see [Prover API](/guides/wallet-integration/transactions/prover-api)) - -## Example - -Here's an example of a completed Spell JSON for a token transfer: - -```json -{ - "version": 11, - "tx": { - "ins": [ - "55777ba206bf747724a4e96586f2d912a77baa8a15a4c63a0b510531ad5fa65e:0" - ], - "outs": [ - { - "0": 420 - }, - { - "0": 419580 - } - ], - "coins": [ - { - "amount": 1000, - "dest": "2f7e10b8f6e2089b5bb5dcce96e8dd49ca01012f6506af0fe7bf5d2f2f5db531" - }, - { - "amount": 1000, - "dest": "009fb48961bca8ec68f01ec882f7ec0dc7dc5cc6bcf4ad154f129ea2338f6cd1" - } - ] - }, - "app_public_inputs": { - "t/1dc78849dc544b2d2bca6d698bb30c20f4e5894ec8d9042f1dbae5c41e997334/b22a36379c7c0b1e987f680e33b2263d94f86e2a75063d698ccf842ce6592840": null - } -} -``` - -**Note:** The content of a token charm is the token amount. In `tx.outs`, the app index `"0"` refers to the first app in `app_public_inputs`. - -## UI Considerations - -When implementing token transfers in your wallet UI: - -- Allow users to specify the amount to transfer -- Clearly display the transfer amount(s) and the remaining amount(s) -- Show the destination address in a user-friendly format -- Provide transaction fee information -- Include confirmation steps before proceeding -- Display transaction status updates during the process diff --git a/src/content/docs/guides/wallet-integration/visualization.md b/src/content/docs/guides/wallet-integration/visualization.md deleted file mode 100644 index 8dc94d3..0000000 --- a/src/content/docs/guides/wallet-integration/visualization.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Charms Visualization -sidebar: - order: 1.5 ---- - -To display Charms assets in your wallet, you'll need to fetch data from the Charms API. This section explains how to retrieve and display Charms data. - -## Fetching Charms Data - -To get all Charms associated with a specific UTXO, you can use charms_lib.wasm module (available as a Charms [release artifact](https://github.com/CharmsDev/charms/releases), can be built from the source at [Charms GitHub](https://github.com/CharmsDev/charms/tree/v11.0.1/charms-lib)). - - -To create JS bindings for the WASM module: - -```sh -wasm-bindgen --out-dir target/wasm-bindgen-nodejs --target nodejs path/to/charms_lib.wasm -``` - -### Example - -Bitcoin transaction (`bitcoin-tx.json`): -```json -{ - "bitcoin": "020000000001024c24d84d55241594f59337265d8bdae0bbfce8841b2d667d45129a75ea92aa130100000000ffffffffe1562b13c190c62084ee16cbf1feb354dd9029822bbb821010ba70a452c9bfc50000000000ffffffff02e803000000000000225120ec52e2809d78721dc1444ef22749b8e73c0c8f59cad4f70e7af4b13d305a2874580900000000000016001445d77e6d194773f086df5ee258d1803ea5d27b4901405495c9e8f8fca5f20fcf5130e944111d150986b67065a5030167d8f27c893c1304ffdfd8ffdece713882b0a01b4eb91912bd667b0a21cc86b73d11508444cdd80341d6516f4c39207cf3c14986997b57d069bf1e5e60b39ce867ac1a102cf56e71e49964b6ddb256c5070902c42e606af3a538ab156e19706990f7ca39ab27d53b7581fddd020063057370656c6c4d080282a36776657273696f6e07627478a1646f75747381a1001b00000009502f9000716170705f7075626c69635f696e70757473a18361749820183d187f18e718e418ce18a6121819184718af187318d70e1851181918be18bd188a18a518b718ed18fe187418bf18af186e1877189a1818184718bd189b982018c9187518d418e018c2189218fb189518ef18bd18a518c118331218d618ac181d188b185a18ef18f718f018f118e518571886184518a218da187018ff185ff699010418a41859184c1859181e18501884185d18701851187b188518181856189a18d80d1823184018cc182d18e118ed184918f4183f18c718e818e318e5081829184b1859188918a7181e18480e1833186518c518e006182018f318180a1872183f18da1887185e186f0e18ac1879187218740718e21826185b18f618d30a18da18df1820183f18d0186a184a183a10183e18ec18431823188518af18a91888186c184e183618ec189418bf1844183018ee181f186a18e01832188f0f187918ec181f09186318d818ae1849189f186f1318bd18a41877187318591860188b18ae182118b0189818dd18bd18f118ce18ee187b182318a6185a18d2188818aa0f18ab182d185918291218eb189c18e7182618a418e3182e1882189418891829185f18211871189418d9188a185e189118dd18861898187518cd09181d0918701856181c186a181a18a1184118791826184ca533185418a418591883182e1821183a18dc18ab18c318cc18b4181918c9040c0018e0186718581869181818a81898181b1888186318e8185f189c188a1869186818351857185018c31882184818af184618f618ac185e18a418db1898185c18c91879189e181a18d216187b185918f218db18fa1831185818e7187e186318c318ee184b182209188d1831186e1846186b184718d518f01875188718b90718f3188f18b018446820adcd6a7d4ea97319846d90c15b30609bf0174cb0c0f9c032e626009b6185cb17ac21c1adcd6a7d4ea97319846d90c15b30609bf0174cb0c0f9c032e626009b6185cb1700000000" -} -``` - -Simpe JavaScript test demonstrating how to use the API (`extractAndVerifySpell.node.test.js`): - -```js -const assert = require('assert'); -const path = require('path'); -const fs = require('fs'); - -function main() { - const wasmModulePath = path.resolve(__dirname, 'path/to/wasm-bindgen-nodejs/charms_lib.js'); - // Ensure wasm artifacts exist - assert.ok(fs.existsSync(wasmModulePath), `Wasm JS glue not found at ${wasmModulePath}`); - - const wasm = require(wasmModulePath); - assert.ok(typeof wasm.extractAndVerifySpell === 'function', 'extractAndVerifySpell export not found'); - - const txJsonPath = path.resolve(__dirname, './bitcoin-tx.json'); - assert.ok(fs.existsSync(txJsonPath), `Sample tx JSON not found at ${txJsonPath}`); - - const tx = JSON.parse(fs.readFileSync(txJsonPath, 'utf8')); - - // Invoke the wasm function extractAndVerifySpell - const res = wasm.extractAndVerifySpell(tx, false); - console.log('[extractAndVerifySpell.test] OK'); - console.log('%o', res); -} - -if (require.main === module) { - try { - main(); - } catch (err) { - console.error('[extractAndVerifySpell.test] FAILED'); - console.error(err); - process.exit(1); - } -} -``` - -Run the test: - -```sh -node extractAndVerifySpell.node.test.js -``` - -This will print the Charms spell data: - -``` -[extractAndVerifySpell.test] OK -{ - version: 11, - tx: { - ins: [ - '13aa92ea759a12457d662d1b84e8fcbbe0da8b5d263793f5941524554dd8244c:1', - [length]: 1 - ], - outs: [ Map(1) { 0 => 40000000000 }, [length]: 1 ] - }, - app_public_inputs: Map(1) { - 't/3d7fe7e4cea6121947af73d70e5119bebd8aa5b7edfe74bfaf6e779a1847bd9b/c975d4e0c292fb95efbda5c13312d6ac1d8b5aeff7f0f1e5578645a2da70ff5f' => undefined - } -} -``` - -## API Response Structure - -The `extractAndVerifySpell(tx, mock)` function returns the Charms _spell_ object, describing all Charms in the outputs of the specified transaction. The response includes: - -- Charms App Specifications, each containing: - - tag ('n' for NFTs, 't' for fungible tokens) - - identity (a 32-byte identifier) - - verification key (a 32-byte verification key of the app's compiled code) -- Input Specifications, each containing: - - UTXO ID of the input -- Output Specifications with Charms — mappings of App spec (referred by an index) to Charm content, which may be: - - Amounts (for fungible tokens) - - Arbitrary data (for NFTs and other types of charms) - -NFTs are recommended (but not required) to adhere to [CHIP-0420](https://github.com/CharmsDev/charms/tree/v11.0.1/CHIPs/CHIP-0420) for structuring their content. - -## Displaying Charms in Your Wallet - -When implementing Charms visualization in your wallet: - -1. **Scan UTXOs**: For each UTXO in the user's wallet, check if it contains Charms by querying the API -2. **Parse Responses**: Process the API responses to extract Charm data -3. **Render UI Elements**: Display Charms with appropriate visuals and information -4. **Handle Different Types**: Implement different display logic for NFTs vs. fungible tokens - -### UI Considerations - -- For NFTs, prominently display the image and name -- For tokens, show the quantity alongside the token name/symbol + image -- Include options for viewing detailed metadata (review Charms Token Metadata specification [CHIP-0420](https://github.com/CharmsDev/charms/tree/v11.0.1/CHIPs/CHIP-0420)) diff --git a/src/content/docs/how-to/beam-charms.md b/src/content/docs/how-to/beam-charms.md new file mode 100644 index 0000000..3bea776 --- /dev/null +++ b/src/content/docs/how-to/beam-charms.md @@ -0,0 +1,103 @@ +--- +title: Beam charms across chains +description: "Move a charm from Bitcoin to Cardano (and back) using beaming, with eBTC as the example." +--- + +[Beaming](/explanation/beaming) moves a charm from one chain to another by +destroying it at a source UTXO and re-creating it at a destination UTXO, tied +together by a hash commitment and a finality proof. This guide walks the flow +using [eBTC](https://github.com/CharmsDev/ebtc) — a token that can live on both +Bitcoin and Cardano. Read [Beaming](/explanation/beaming) first for the concepts. + +A beam is always a **pair** of spells: a *send* on the source chain and a +*receive* on the destination chain. + +## 1. Send (on the source chain) + +The send spell marks an output as **beamed out**: it carries no token, only a +hash committing to the destination UTXO. In `beamed_outs`, the value is +`SHA-256(destination_utxo_id ‖ nonce)`: + +```yaml +version: 15 +tx: + ins: + - ${in_utxo_0} # the eBTC you're sending + outs: + - 0: ${send_amount} # output 0 nominally holds the token... + beamed_outs: + 0: 7a0fae5c… # ...but it's beamed out: hash of the destination UTXO (+ nonce) + coins: + - amount: 300 # a dust carrier output on the source chain + dest: ${dest_1} +app_public_inputs: + t/${app_id}/${app_vk}: ~ +``` + +Prove it on the source chain. On Bitcoin: + +```sh +cat ./spells/beam-send.yaml | envsubst | charms spell prove \ + --prev-txs=$prev_tx \ + --change-address=$change_address +``` + +On Cardano the send is `--chain=cardano` and needs a collateral UTXO: + +```sh +cat ./spells/beam-send-c2b.yaml | envsubst | charms spell prove \ + --chain=cardano \ + --prev-txs=$prev_tx \ + --collateral-utxo=$collateral +``` + +Sign and broadcast the resulting transaction as usual. Note the destination +UTXO id and the nonce — you need them to receive. + +## 2. Receive (on the destination chain) + +The receive spell spends the **destination (placeholder) UTXO** you committed to, +re-materializing the charm. You authorize the claim with `--beamed-from`, mapping +the input index to `[source_utxo, nonce]`, and you pass the **source +transaction together with its finality proof** in `--prev-txs`. + +```sh +cat ./spells/beam-receive.yaml | envsubst | charms spell prove \ + --prev-txs="$placeholder_tx" \ + --prev-txs="$source_tx_with_finality_proof" \ + --beamed-from '{0: [, ]}' \ + --change-address=$change_address \ + --chain=cardano --collateral-utxo=$collateral # when receiving on Cardano +``` + +The finality-proof form of `--prev-txs` depends on the **source** chain: + +- **Source = Bitcoin** → a proof of work: + + ``` + --prev-txs="!bitcoin {tx: , proof: , headers: [, …]}" + ``` + + (about six block headers of accumulated work). + +- **Source = Cardano** → a [Scrolls](/explanation/scrolls) finality signature: + + ``` + --prev-txs="!cardano {tx: , signature: }" + ``` + +The prover checks that the destination UTXO (plus nonce) hashes to the value the +source committed in `beamed_outs`, and that the source transaction is proven +final — otherwise it refuses to prove. If it succeeds, sign and broadcast the +destination transaction. + +## Notes + +- A pure beam (just moving the token) is a simple transfer and needs no app + binary. If the receive *also* mints/burns — as eBTC does when releasing BTC + from its vault — pass `--app-bins` so the contract runs. +- The hash commitment binds a **specific** destination UTXO, so only its holder + can claim the beamed charm. Keep the nonce. +- See the [eBTC scripts](https://github.com/CharmsDev/ebtc) (`beam-send.sh`, + `beam-receive.sh`, and the `*-c2b` counterparts) for complete, runnable + examples in both directions. diff --git a/src/content/docs/how-to/call-the-prover-api.md b/src/content/docs/how-to/call-the-prover-api.md new file mode 100644 index 0000000..d0aa796 --- /dev/null +++ b/src/content/docs/how-to/call-the-prover-api.md @@ -0,0 +1,81 @@ +--- +title: Call the Prover API +description: "Generate a spell transaction from client code by calling the Prover API." +--- + +The [Prover API](/reference/prover-api) turns a spell into a proven, +ready-to-broadcast transaction. This guide calls it from client code (for example +a wallet). For the full request/response contract, see the +[Prover API reference](/reference/prover-api). + +## Choose an endpoint + +| | URL | +| --- | --- | +| Hosted (default) | `https://v15.charms.dev/spells/prove` | +| Self-hosted | `http://localhost:17784/spells/prove` ([run your own](/how-to/run-a-prover-server)) | + +## Build the spell and call the API + +Construct the [spell](/reference/spell) object, then `POST` it. The response is a +JSON array; for Bitcoin it contains a single unsigned transaction. + +```javascript +const proveApiUrl = 'https://v15.charms.dev/spells/prove'; + +const spell = { + version: 15, + tx: { + ins: ["eb711823b50d368c5e0121649e414d78086cad69817b5163e871f7039ac0a4a3:0"], + outs: [{ "0": { ticker: "CHARMIX", name: "Panoramix #1" } }], + coins: [{ amount: 1000, dest: "5120…" }] // dest from `charms util dest` + }, + app_public_inputs: { + "n/af50d82d…/a0029d4e…": null + } +}; + +const requestBody = { + spell, + prev_txs: [{ bitcoin: "020000000001…" }], // tx(s) that produced the inputs + change_address: "tb1p…", + fee_rate: 2.0, + chain: "bitcoin" +}; + +const response = await fetch(proveApiUrl, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(requestBody), +}); + +if (!response.ok) { + // 400 = bad spell/params; 500 = transient prover failure (retry with backoff) + throw new Error(`prove failed: ${response.status}`); +} + +const [tx] = await response.json(); // e.g. { bitcoin: "" } +const spellTxHex = tx.bitcoin; +``` + +## After proving + +The returned transaction is **unsigned**. Sign it with the keys for its funding +inputs and broadcast it — see +[Sign and broadcast](/how-to/wallet-integration/sign-and-broadcast): + +```sh +bitcoin-cli signrawtransactionwithwallet +bitcoin-cli sendrawtransaction +``` + +## Tips + +- Include every app's binary in `binaries` (or use `--app-bins` from the CLI) for + anything beyond a [simple transfer](/explanation/apps#simple-transfers-need-no-contract). +- Pass app witnesses in `app_private_inputs` (keyed by app `tag/identity/vk`). +- For [versioned apps](/how-to/manage-app-keys), include `app_signatures`. +- Ensure the funding UTXOs cover the outputs plus fees; pick a `fee_rate` + appropriate to network conditions. +- Retry `500` responses with backoff; `400` responses indicate a bad request and + will not succeed on retry. diff --git a/src/content/docs/how-to/index.md b/src/content/docs/how-to/index.md new file mode 100644 index 0000000..6b623f2 --- /dev/null +++ b/src/content/docs/how-to/index.md @@ -0,0 +1,34 @@ +--- +title: How-to guides +description: "Task-oriented recipes for working with Charms." +--- + +Practical, goal-oriented recipes. Each guide assumes you already know the +basics — if you're new, start with the [Tutorials](/tutorials); for the ideas +behind these tasks, see [Explanation](/explanation); for exact formats, see +[Reference](/reference). + +### Set up + +- [Install Charms](/how-to/install-charms) +- [Set up a Bitcoin node](/how-to/set-up-a-bitcoin-node) + +### Build apps + +- [Write an app contract](/how-to/write-an-app-contract) +- [Manage app keys and signatures](/how-to/manage-app-keys) (versioned apps) + +### Prove + +- [Call the Prover API](/how-to/call-the-prover-api) +- [Run a prover server](/how-to/run-a-prover-server) (SP1 Prover Network) + +### Move charms + +- [Beam charms across chains](/how-to/beam-charms) (eBTC example) +- [Spend Scroll outputs](/how-to/spend-scroll-outputs) + +### Integrate + +- [Wallet integration](/how-to/wallet-integration) — add Charms support to a + Bitcoin wallet. diff --git a/src/content/docs/how-to/install-charms.md b/src/content/docs/how-to/install-charms.md new file mode 100644 index 0000000..c20c5f8 --- /dev/null +++ b/src/content/docs/how-to/install-charms.md @@ -0,0 +1,53 @@ +--- +title: Install Charms +description: "Install the charms CLI and its prerequisites." +--- + +This guide installs the `charms` command-line tool. To run your own prover, see +[Run a prover server](/how-to/run-a-prover-server) instead (it builds the +`charms-prover` binary). + +## Prerequisites + +- **[Rust](https://rust-lang.org/)** (stable toolchain, via + [rustup](https://rustup.rs/)). +- The **Protocol Buffers compiler `protoc`** — + [`protobuf`](https://protobuf.dev/downloads/): + + ```sh + brew install protobuf # macOS + # or: apt-get install protobuf-compiler + ``` + +- The **WebAssembly target** used to build apps: + + ```sh + rustup target add wasm32-wasip1 + ``` + +## Install the CLI + +```sh +## important to have this end with `/target` (a dependency issue) +export CARGO_TARGET_DIR=$(mktemp -d)/target +cargo install --locked charms +``` + +## Verify + +```sh +charms spell vk +``` + +This prints the spell verification key as JSON, including the protocol version: + +```json +{ "prover": false, "version": 15, "vk": "00425796f4c4fa050043eee14d801b4f935244e44aad6a28de0cd5cb3de0ae52" } +``` + +## Next steps + +- [Build a Charms app](/tutorials/build-a-charms-app) — the tutorial. +- [Set up a Bitcoin node](/how-to/set-up-a-bitcoin-node) — needed to broadcast + spells on `testnet4`. +- [CLI reference](/reference/cli) — every command and option. diff --git a/src/content/docs/how-to/manage-app-keys.md b/src/content/docs/how-to/manage-app-keys.md new file mode 100644 index 0000000..ae387a0 --- /dev/null +++ b/src/content/docs/how-to/manage-app-keys.md @@ -0,0 +1,85 @@ +--- +title: Manage app keys and signatures +description: "Use versioned apps: generate a key, sign binaries, and verify them." +--- + +By default a Charms app is **immutable**: its verification key is the hash of one +exact Wasm binary, so the code can never change. A **versioned app** instead pins +its verification key to a *signing key*, letting you upgrade the binary over time +by signing each new version. This guide covers the versioned-app workflow. For +the trade-offs, see +[Apps](/explanation/apps#immutable-and-versioned-apps). + +## When to use a versioned app + +- **Immutable app** — maximally trustless; the binary is frozen forever. Good for + assets that must never change rules. `vk = SHA-256(wasm)`. +- **Versioned app** — upgradeable; holders trust the key-holder to authorize + binaries. Good for apps you expect to evolve. `vk = SHA-256(public_key)`. + +## Generate a signing key + +```sh +charms app keygen +``` + +This writes a BIP-340 keypair to `.charms/app-key.json` (mode `0600`; it refuses +to overwrite). The file contains `{ public_key, secret_key, vk }`, where the +app's verification key is `vk = SHA-256(public_key)`. + +:::caution +Keep `secret_key` private — it is the authority to authorize new app binaries. +The `.charms/` directory is git-ignored by the template. +::: + +Get the versioned app's `vk`: + +```sh +charms app vk --pubkey .charms/app-key.json +``` + +## Sign a binary + +`charms app build` **auto-signs**: when `.charms/app-key.json` exists, building +the app also signs the fresh Wasm and writes the signature next to it as +`.sig.yaml`. + +To sign explicitly: + +```sh +charms app sign # uses .charms/app-key.json and the release build +# or +charms app sign --key .charms/app-key.json --bin path/to/app.wasm --out app.sig.yaml +``` + +A `.yaml`/`.yml` output is a `vk -> AppSignature` map; any other extension writes +a single JSON `AppSignature`. Each signature is a Schnorr signature over the +binary's `SHA-256`, declaring its version. + +## Verify a binary + +```sh +charms app verify # verifies .sig.yaml against the build +# or +charms app verify --bin path/to/app.wasm --sig app.sig.yaml +``` + +Verification checks that each signature's `SHA-256(public_key)` equals its `vk` +key and that the Schnorr signature over the binary hash is valid. + +## Use signatures when proving + +A spell that uses a versioned app must carry a signature for it. Pass the +`.sig.yaml` to checking and proving: + +```sh +charms spell prove \ + --app-bins=$app_bin \ + --app-signatures=app.sig.yaml \ + … +``` + +In a [Prover API](/reference/prover-api) request, supply these as the +`app_signatures` field, keyed by app `vk`. The runtime also checks that the +binary's exported `__app_version` matches the version recorded in the spell — so +declare your version in the app with `charms_sdk::app_version!(N)`. diff --git a/src/content/docs/how-to/run-a-prover-server.md b/src/content/docs/how-to/run-a-prover-server.md new file mode 100644 index 0000000..397b690 --- /dev/null +++ b/src/content/docs/how-to/run-a-prover-server.md @@ -0,0 +1,92 @@ +--- +title: Run a prover server +description: "Build and run charms-prover server, proving with the SP1 Prover Network." +--- + +The hosted [Prover API](/reference/prover-api) is convenient, but you can run your +own prover — for development, privacy, or control over proving costs. The prover +is the `charms-prover` binary: the same code as the `charms` CLI, built with the +`prover` feature, which enables real [SP1](https://docs.succinct.xyz/) proving. + +## Build `charms-prover` + +```sh +git clone https://github.com/CharmsDev/charms +cd charms +cargo install --path . --locked --bin charms-prover --features prover +``` + +## Run the server + +```sh +charms-prover server # binds 0.0.0.0:17784 +charms-prover server --ip 127.0.0.1 --port 8080 +``` + +It exposes `POST /spells/prove` and `GET /ready`. Check readiness: + +```sh +curl http://localhost:17784/ready # -> OK +``` + +Point the `charms` CLI (or your client) at it: + +```sh +export CHARMS_PROVE_API_URL=http://localhost:17784/spells/prove +charms spell prove … +``` + +## Proving backends + +The prover proves in two stages — the app/spell-checker proof, then a Groth16 +wrapper — and two environment variables select the backend for each: + +| Variable | Values | Selects | +| --- | --- | --- | +| `APP_SP1_PROVER` | `cpu`, `network` | The app + spell-checker proof. | +| `SPELL_SP1_PROVER` | `app`, `network` | The Groth16 wrapper. `app` reuses the app backend. | + +### Prove with the SP1 Prover Network (recommended) + +Generating real Groth16 proofs on CPU is slow; the +[Succinct Prover Network](https://docs.succinct.xyz/) does it for you. Set both +stages to use the network and provide your network key: + +```sh +export APP_SP1_PROVER=network +export SPELL_SP1_PROVER=app # the wrapper reuses the network app backend +export NETWORK_PRIVATE_KEY=0x… # your Succinct Prover Network private key (required) +# optional — defaults to https://rpc.mainnet.succinct.xyz +# export NETWORK_RPC_URL=https://rpc.mainnet.succinct.xyz + +charms-prover server +``` + +`NETWORK_PRIVATE_KEY` is **required** when a backend is `network` — the server +will fail to start without it. This is the key for your Succinct account, which +pays for proof requests. + +### Prove locally on CPU (no network) + +Slow, but needs no account — useful for development: + +```sh +export APP_SP1_PROVER=cpu +export SPELL_SP1_PROVER=app +charms-prover server +``` + +## Optional configuration + +| Variable | Purpose | +| --- | --- | +| `REDIS_URL` | Cache proofs and deduplicate concurrent identical requests. Omit to disable. | +| `CHARMS_FEE_SETTINGS` | Path to a YAML file configuring the Charms protocol fee (addresses, rate). | +| `SP1_GPU_SERVICE_URL` | URL of a local SP1 GPU (Moongate) service, if proving on GPU. | +| `RUST_LOG` | Log level, e.g. `info`. | + +:::note +For Bitcoin spells with [Scroll](/explanation/scrolls) outputs, a prover *server* +is required (not mock mode): the server calls the Scrolls canister to fill in the +Scroll output addresses while proving. +::: diff --git a/src/content/docs/how-to/set-up-a-bitcoin-node.md b/src/content/docs/how-to/set-up-a-bitcoin-node.md new file mode 100644 index 0000000..fd71818 --- /dev/null +++ b/src/content/docs/how-to/set-up-a-bitcoin-node.md @@ -0,0 +1,73 @@ +--- +title: Set up a Bitcoin node +description: "Run a Bitcoin Core node on testnet4 for casting spells." +--- + +To cast spells on Bitcoin you need a Bitcoin Core node. This guide sets one up on +`testnet4`. + +## Bitcoin Core + +Bitcoin Core **v28.0 or later** is required. Install it with Homebrew: + +```sh +brew install bitcoin +``` + +Use this configuration (`bitcoin.conf`): + +```ini +server=1 +testnet4=1 +txindex=1 +addresstype=bech32m +changetype=bech32m +``` + +`bitcoin.conf` is usually located at: + +- macOS: `~/Library/Application Support/Bitcoin/bitcoin.conf` +- Linux: `~/.bitcoin/bitcoin.conf` + +Start `bitcoind` and let it sync. + +:::tip +Throughout the docs we assume `bitcoin-cli` is aliased as `b`: + +```sh +alias b=bitcoin-cli +``` +::: + +## Load a wallet + +```sh +b createwallet testwallet # create a wallet (you might already have one) +b loadwallet testwallet # bitcoind does not load wallets automatically at startup +``` + +## Get test BTC + +Get a new address and fund it from a faucet: + +```sh +b getnewaddress # prints a new address +``` + +Visit and send test BTC to that address. +Get at least **50,000 sats** (0.0005 test BTC). Aim for **more than one UTXO** — +tap the faucet a few times, or send sats within your own wallet so you have some +small UTXOs and at least one larger one (≥ 10,000 sats). + +## jq + +Several examples use `jq`: + +```sh +brew install jq +``` + +## Next steps + +- [Cast your first spell](/tutorials/cast-your-first-spell) — prove, sign, and + broadcast on `testnet4`. diff --git a/src/content/docs/how-to/spend-scroll-outputs.md b/src/content/docs/how-to/spend-scroll-outputs.md new file mode 100644 index 0000000..b449ed2 --- /dev/null +++ b/src/content/docs/how-to/spend-scroll-outputs.md @@ -0,0 +1,62 @@ +--- +title: Spend Scroll outputs +description: "Spend a Scrolls-controlled Bitcoin output with the canister's sign_and_submit method." +--- + +A Bitcoin output carrying a [Scroll](/explanation/scrolls) charm is locked to an +address controlled by the `scrolls_bitcoin_v15` canister — no single private key +can spend it. To spend it, you build the transaction, sign your *own* inputs, and +ask the canister to sign its inputs and broadcast. This guide uses the canister's +[`sign_and_submit`](/reference/scrolls-canister#sign_and_submit) method. + +## How it works + +The canister will sign a Scroll input only if the transaction: + +1. carries a **valid Charms spell**, and +2. pays the configured Scrolls **protocol fee**. + +So you can't move Scroll-controlled funds arbitrarily — only via a transaction +whose spell is correct. That is the whole point of [Scrolls](/explanation/scrolls): +programmable custody enforced by Charms logic. + +## Steps + +1. **Build the spell transaction.** Prove a spell that spends the Scroll output + and pays the fee output, producing an (unsigned) Bitcoin transaction — for + example with `charms spell prove` (you'll need a [prover + server](/how-to/run-a-prover-server) for Scroll spells). The result is your + `tx_to_sign`. + +2. **Sign your own inputs.** Sign every input that is *not* Scroll-controlled + (e.g. your funding UTXOs). Leave the Scroll inputs unsigned. The canister + requires that your inputs are already signed and its inputs are not. + +3. **Call `sign_and_submit`.** Pass the network, the Scroll input indexes to + sign, the prerequisite transactions, and the partially-signed transaction: + + ```sh + dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \ + '("main", record { + sign_inputs = vec { 0 : nat32 }; # indexes of the Scroll inputs + prev_txs = vec { "0200000000…" }; # txs that created the spent outputs + tx_to_sign = "0200000000…"; # your partially-signed tx + v14_sign_inputs = null; + })' + ``` + + Use `"main"` or `"testnet4"` for the network. + +4. **Get the txid.** On success the canister verifies the spell, checks the fee, + signs its inputs, **broadcasts** the transaction, and returns + `{ txid, wtxid }`. Re-broadcasting an already-confirmed transaction is + idempotent. + +## Calling without dfx + +You can call the canister with any Internet Computer agent +(`ic-agent`/agent-rs), or over HTTP via the `scrolls-api` service, which exposes +`POST /{network}/sign` and returns `{ txid, wtxid }` as JSON. + +See the [Scrolls canister reference](/reference/scrolls-canister) for the full +method signatures and the `SignRequest` shape. diff --git a/src/content/docs/how-to/wallet-integration/display-charms.md b/src/content/docs/how-to/wallet-integration/display-charms.md new file mode 100644 index 0000000..d649395 --- /dev/null +++ b/src/content/docs/how-to/wallet-integration/display-charms.md @@ -0,0 +1,69 @@ +--- +title: Display charms +description: "Read and render the charms held by a transaction's outputs." +--- + +To show charms in a wallet, extract them from the transaction that produced the +UTXO. The `charms-lib` WebAssembly module exposes `extractAndVerifySpell`, which +parses a transaction, verifies its spell proof, and returns the charms. + +## Get the WASM module + +Use the `charms_lib.wasm` module — available as a +[release artifact](https://github.com/CharmsDev/charms/releases) or built from +[`charms-lib`](https://github.com/CharmsDev/charms/tree/main/charms-lib). + +Create JS bindings: + +```sh +wasm-bindgen --out-dir target/wasm-bindgen-nodejs --target nodejs path/to/charms_lib.wasm +``` + +## Extract and verify + +Pass a chain-tagged transaction to `extractAndVerifySpell(tx, mock)`: + +```js +const wasm = require('./target/wasm-bindgen-nodejs/charms_lib.js'); + +const tx = { bitcoin: "020000000001…" }; // the raw transaction hex +const spell = wasm.extractAndVerifySpell(tx, false); +console.log(spell); +``` + +The returned spell describes the charms in the transaction's outputs: + +``` +{ + version: 15, + tx: { + ins: [ '13aa92ea…:1' ], + outs: [ Map(1) { 0 => 40000000000 } ] + }, + app_public_inputs: Map(1) { + 't/3d7fe7e4…/c975d4e0…' => undefined + } +} +``` + +## What you get + +`extractAndVerifySpell(tx, mock)` returns the spell object for the transaction: + +- **App specifications** — each app's `tag` (`n` NFT, `t` token, `s` Scroll, or + custom), 32-byte `identity`, and 32-byte verification key `vk`. +- **Inputs** — the UTXO ids spent. +- **Outputs with charms** — each output maps an app (by index) to its charm + content: an amount for fungible tokens, or arbitrary data for NFTs and other + apps. + +## Render in the wallet + +1. **Scan UTXOs.** For each UTXO, extract charms from the transaction that + created it. +2. **Parse** the returned spell to get each output's charms. +3. **Render** by type: show an NFT's image and name prominently; show a token's + amount alongside its name/symbol and image. +4. **Show metadata.** NFTs are recommended (not required) to follow + [CHIP-0420](https://github.com/CharmsDev/charms/tree/main/CHIPs/CHIP-0420) for + their content structure (`ticker`, `name`, `image`, …). diff --git a/src/content/docs/how-to/wallet-integration/index.md b/src/content/docs/how-to/wallet-integration/index.md new file mode 100644 index 0000000..8a313f7 --- /dev/null +++ b/src/content/docs/how-to/wallet-integration/index.md @@ -0,0 +1,37 @@ +--- +title: Wallet integration +description: "Add Charms support to a Bitcoin wallet." +--- + +This set of guides gives wallet providers what they need to add Charms support: +displaying charms, transferring them, and signing and broadcasting the resulting +transactions. With it, a wallet can let users view, transfer, and interact with +charms — collectibles, tokens, and other programmable assets on Bitcoin. + +## What it involves + +1. **[Display charms](/how-to/wallet-integration/display-charms)** — read the + charms held by a UTXO and render them. +2. **[Transfer NFTs](/how-to/wallet-integration/transfer-nfts)** — build a spell + that sends an NFT charm. +3. **[Transfer tokens](/how-to/wallet-integration/transfer-tokens)** — build a + spell that sends fungible-token charms. +4. **[Sign and broadcast](/how-to/wallet-integration/sign-and-broadcast)** — + finalize the spell transaction on the Bitcoin network. + +The transfer flow always follows the same shape: build the +[spell](/reference/spell), [call the Prover API](/how-to/call-the-prover-api) to +get the spell transaction, then sign and broadcast it. + +:::caution[Charms-aware coin selection] +A wallet that supports Charms must avoid spending charmed UTXOs by accident. +Ordinary operations like fee bumping or UTXO consolidation will **burn** any +charms in the inputs unless the transaction carries a correct spell preserving +them. Treat charmed UTXOs as special and exclude them from generic coin +selection. +::: + +## Reference + +- [Spell structure](/reference/spell) +- [Prover API](/reference/prover-api) diff --git a/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md b/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md new file mode 100644 index 0000000..8a86a03 --- /dev/null +++ b/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md @@ -0,0 +1,41 @@ +--- +title: Sign and broadcast +description: "Finalize a spell transaction: sign it and send it to the Bitcoin network." +--- + +The [Prover API](/reference/prover-api) returns an **unsigned** Bitcoin +transaction — a single transaction that spends the inputs and carries the spell +and its proof in an `OP_RETURN` output. Sign it and broadcast it to complete the +transfer. + +## Sign + +Sign the transaction with the keys for its funding inputs: + +```sh +bitcoin-cli signrawtransactionwithwallet +``` + +The wallet must be able to sign whatever input types it owns. The Charms tooling +and node setup [recommend `bech32m` (Taproot)](/how-to/set-up-a-bitcoin-node) +addresses, so ensure your signing stack supports Taproot / Schnorr signatures. +Most modern libraries do — Bitcoin Core, `bitcoinjs-lib`, `rust-bitcoin`, +`btcd`, and others. + +## Broadcast + +Send the signed transaction: + +```sh +bitcoin-cli sendrawtransaction +``` + +## Considerations + +- **Fee rate.** The fee is set when you prove (the Prover API `fee_rate`, default + `2.0` sats/vB). Choose a rate appropriate to network conditions so the + transaction is accepted into the mempool and confirmed. +- **Validate before sending.** Confirm the transaction is well-formed and the + inputs are still unspent before broadcasting. +- **One transaction.** There is no commit/reveal step — signing and broadcasting + the single returned transaction is all that's needed. diff --git a/src/content/docs/how-to/wallet-integration/transfer-nfts.md b/src/content/docs/how-to/wallet-integration/transfer-nfts.md new file mode 100644 index 0000000..15a82da --- /dev/null +++ b/src/content/docs/how-to/wallet-integration/transfer-nfts.md @@ -0,0 +1,54 @@ +--- +title: Transfer NFTs +description: "Build a spell that sends an NFT charm to a new UTXO." +--- + +Transferring an NFT sends the entire charm, unchanged, to a new output. This is a +[simple transfer](/explanation/apps#simple-transfers-need-no-contract), so it +needs no app binary or contract proof — just asset preservation. + +## The spell + +```json +{ + "version": 15, + "tx": { + "ins": [":"], + "outs": [{ "0": { "ticker": "CHARMIX", "name": "Panoramix #1" } }], + "coins": [{ "amount": 1000, "dest": "" }] + }, + "app_public_inputs": { "n//": null } +} +``` + +| Field | Meaning | +| --- | --- | +| `version` | `15`. | +| `app_public_inputs` | The NFT app(s) involved; `null` for a simple transfer. | +| `tx.ins` | Source UTXO(s) (`txid:vout`). | +| `tx.outs` | Destination charms, keyed by app index (`"0"`, `"1"`, …). | +| `tx.coins` | Native outputs (`amount`, hex `dest` from [`charms util dest`](/reference/cli#charms-util-dest)). | + +The NFT content fields (`ticker`, `name`, `description`, `image`, `image_hash`, +`url`, …) follow +[CHIP-0420](https://github.com/CharmsDev/charms/tree/main/CHIPs/CHIP-0420). To +send multiple NFTs, add their apps to `app_public_inputs`, their inputs to +`tx.ins`, and the NFTs to `tx.outs`. + +:::note +If the transaction does more than a simple transfer (mints a new NFT, or involves +charms that are neither tokens nor NFTs), the relevant app contracts must run — +pass the app binaries when proving. +::: + +## Steps + +1. **Read** the NFT's content from the source UTXO + ([Display charms](/how-to/wallet-integration/display-charms)). +2. **Build** the spell `tx` and `app_public_inputs` + ([Spell structure](/reference/spell)). +3. **Derive** `coins[].dest` from the destination address with + `charms util dest --addr
`. +4. **Prove** by [calling the Prover API](/how-to/call-the-prover-api). +5. **[Sign and broadcast](/how-to/wallet-integration/sign-and-broadcast)** the + returned transaction. diff --git a/src/content/docs/how-to/wallet-integration/transfer-tokens.md b/src/content/docs/how-to/wallet-integration/transfer-tokens.md new file mode 100644 index 0000000..f68d25a --- /dev/null +++ b/src/content/docs/how-to/wallet-integration/transfer-tokens.md @@ -0,0 +1,56 @@ +--- +title: Transfer tokens +description: "Build a spell that sends fungible-token charms." +--- + +A token transfer spends one or more outputs holding a token and creates +destination outputs whose total token amount equals the input total. Like NFT +transfers, this is a +[simple transfer](/explanation/apps#simple-transfers-need-no-contract) — no app +binary or contract proof required. + +## The spell + +```json +{ + "version": 15, + "tx": { + "ins": [":"], + "outs": [{ "0": 420 }, { "0": 419580 }], + "coins": [ + { "amount": 1000, "dest": "" }, + { "amount": 1000, "dest": "" } + ] + }, + "app_public_inputs": { "t//": null } +} +``` + +Here the token (app index `"0"`) is split into `420` (sent) and `419580` +(change). The total out must equal the total in. Each `tx.outs` entry pairs with +the `tx.coins` entry at the same position (the native output that will carry the +charm). + +| Field | Meaning | +| --- | --- | +| `version` | `15`. | +| `app_public_inputs` | The token app(s); `null` for a simple transfer. | +| `tx.ins` | Source UTXO(s). | +| `tx.outs` | Per output, the app index → token amount. | +| `tx.coins` | Native outputs (`amount`, hex `dest` from [`charms util dest`](/reference/cli#charms-util-dest)). | + +:::note +Minting or burning tokens is **not** a simple transfer: it must satisfy the +token app's contract, so pass the app binary when proving. +::: + +## Steps + +1. **Collect** source UTXOs and their token amounts + ([Display charms](/how-to/wallet-integration/display-charms)). +2. **Compute** the transfer and change amounts (they must sum to the input + total). +3. **Build** the spell `tx` and `app_public_inputs`. +4. **Derive** each `coins[].dest` with `charms util dest --addr
`. +5. **Prove** by [calling the Prover API](/how-to/call-the-prover-api), then + **[sign and broadcast](/how-to/wallet-integration/sign-and-broadcast)**. diff --git a/src/content/docs/how-to/write-an-app-contract.md b/src/content/docs/how-to/write-an-app-contract.md new file mode 100644 index 0000000..5817516 --- /dev/null +++ b/src/content/docs/how-to/write-an-app-contract.md @@ -0,0 +1,140 @@ +--- +title: Write an app contract +description: "Implement the app_contract predicate that governs your charms." +--- + +An app's logic is a single Rust function, the **app contract**. This guide shows +how to implement one, starting from the generated template. For the concepts, see +[Apps](/explanation/apps); for the exact API, see the [SDK reference](/reference/sdk). + +## Scaffold a project + +```sh +charms app new my-token +cd ./my-token +cargo update +``` + +The template is a working **fungible token managed by a reference NFT**: the +NFT's state records the `remaining` supply, and whoever controls the NFT can mint +tokens by decreasing it. + +## The contract + +`src/lib.rs` exposes `app_contract`, the predicate that must hold for the +transaction's spell to be correct: + +```rust +use charms_sdk::data::{ + charm_values, check, sum_token_amount, App, Data, Transaction, UtxoId, B32, NFT, TOKEN, +}; + +pub fn app_contract(app: &App, tx: &Transaction, x: &Data, w: &Data) -> bool { + let empty = Data::empty(); + assert_eq!(x, &empty); // this app takes no public input + match app.tag { + NFT => check!(nft_contract_satisfied(app, tx, w)), + TOKEN => check!(token_contract_satisfied(app, tx)), + _ => unreachable!(), + } + true +} +``` + +The arguments are `app` (the app being evaluated), `tx` (the transaction with its +charms), `x` (public input), and `w` (private input/witness). Return `true` to +allow the transaction. + +### Minting the NFT + +The NFT can be minted only by the party spending a specific UTXO. The contract +takes that UTXO id as its **private input** `w`, and requires that its hash equals +the NFT's `identity` — which is exactly how the `identity` is chosen when minting: + +```rust +fn can_mint_nft(nft_app: &App, tx: &Transaction, w: &Data) -> bool { + let w_str: String = w.value().expect("witness should be a UTXO id string"); + + // the NFT's identity is the hash of the UTXO being spent... + check!(hash(&w_str) == nft_app.identity); + // ...and that UTXO must actually be an input of this transaction. + let w_utxo_id = UtxoId::from_str(&w_str).unwrap(); + check!(tx.ins.iter().any(|(utxo_id, _)| utxo_id == &w_utxo_id)); + + // exactly one NFT charm out, with the expected structure. + let nft_charms = charm_values(nft_app, tx.outs.iter()).collect::>(); + check!(nft_charms.len() == 1); + check!(nft_charms[0].value::().is_ok()); + true +} +``` + +### Minting tokens against the NFT's supply + +Tokens may be minted only by the amount the managing NFT's `remaining` supply +decreases — a conservation rule: + +```rust +fn can_mint_token(token_app: &App, tx: &Transaction) -> bool { + let nft_app = App { tag: NFT, identity: token_app.identity.clone(), vk: token_app.vk.clone() }; + + let incoming = nft_remaining(&nft_app, tx.ins.iter().map(|(_, v)| v)); + let outgoing = nft_remaining(&nft_app, tx.outs.iter()); + check!(incoming >= outgoing); + + let input_amount = sum_token_amount(token_app, tx.ins.iter().map(|(_, v)| v)).unwrap(); + let output_amount = sum_token_amount(token_app, tx.outs.iter()).unwrap(); + + // minted tokens == reduction in remaining supply + output_amount - input_amount == incoming - outgoing +} +``` + +(See the generated `src/lib.rs` for the full, compiling version.) + +## Patterns + +- **Dispatch on `app.tag`.** One binary can implement several related apps (here, + the NFT `n` and its token `t`). +- **`check!(cond)`** returns `false` from the contract early if `cond` fails (and + logs the failing expression). Prefer it over manual `if/return`. +- **`charm_values(app, charms)`** iterates the `Data` for `app` across inputs, + outputs, or references. **`sum_token_amount(app, charms)`** sums a token's + amounts. +- **Public vs private input.** `x` is visible in the spell; `w` is a witness that + is never published. The template requires `x` to be empty and uses `w` for the + minting UTXO. +- **Allow simple transfers cheaply.** Moving an NFT or tokens without minting is a + [simple transfer](/explanation/apps#simple-transfers-need-no-contract) and does + not run your contract at all — only mint/burn/custom operations do. You can use + `is_simple_transfer`, `token_amounts_balanced`, and `nft_state_preserved` from + the SDK when you want to special-case them. + +## Build and check + +Build the WebAssembly binary: + +```sh +app_bin=$(charms app build) +charms app vk $app_bin # the app's verification key +``` + +The example spells under `spells/` use environment variables. Test the NFT mint +locally (no proof, no network) — the `app_id` is the SHA-256 of the UTXO you +spend: + +```sh +export app_vk=$(charms app vk $app_bin) +export in_utxo_0="d8fa4cdade7ac3dff64047dc73b58591ebe638579881b200d4fea68fc84521f0:0" +export app_id=$(echo -n "${in_utxo_0}" | sha256sum | cut -d' ' -f1) +export dest_0=$(charms util dest --addr tb1p3w06fgh64axkj3uphn4t258ehweccm367vkdhkvz8qzdagjctm8qaw2xyv) +export amount_0=20000 + +cat ./spells/mint-nft.yaml | envsubst | charms spell check \ + --prev-txs=$prev_txs \ + --app-bins=$app_bin \ + --private-inputs=<(cat ./spells/mint-nft-private.yaml | envsubst) +``` + +If the contract is satisfied, `charms spell check` reports success and the cycles +used. Next, [cast it onto a real transaction](/tutorials/cast-your-first-spell). diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index 6c33e32..4d4f653 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -9,10 +9,10 @@ hero: file: ../../assets/charms.svg actions: - text: Get started - link: /guides/charms-apps/get-started + link: /tutorials/build-a-charms-app icon: rocket - - text: Why? - link: /concepts/why + - text: Why Charms? + link: /explanation/why-charms icon: right-arrow variant: minimal - text: Whitepaper @@ -43,12 +43,35 @@ import { Card, CardGrid } from '@astrojs/starlight/components'; ```sh - ## edit the spell at ./spells/mint-tokens.yaml - ## then run - charms spell check --spell=./spells/mint-tokens.yaml + ## edit the spell at ./spells/mint-nft.yaml, then run + charms spell check --spell=./spells/mint-nft.yaml ``` - - Learn more in [the Charms Docs](./concepts/why). + + Mint an NFT on Bitcoin in the + [Cast your first spell](/tutorials/cast-your-first-spell) tutorial. + + + +## Find your way around + +These docs follow the [Diátaxis](https://diataxis.fr) framework. + + + + Learn by building, from install to a charm on Bitcoin. + [Start here →](/tutorials) + + + Task-focused recipes: prove, beam, integrate a wallet, and more. + [Browse →](/how-to) + + + Understand apps, spells, beaming, and Scrolls. + [Read →](/explanation) + + + The CLI, spell structure, SDK, Prover API, and Scrolls canister. + [Look up →](/reference) diff --git a/src/content/docs/reference/cli.md b/src/content/docs/reference/cli.md new file mode 100644 index 0000000..109f048 --- /dev/null +++ b/src/content/docs/reference/cli.md @@ -0,0 +1,196 @@ +--- +title: CLI +description: "The charms command-line interface, command by command." +sidebar: + order: 1 +--- + +The `charms` command-line tool creates and verifies spells, manages apps, and +runs a prover server. This page documents every command in v15. + +## Binaries + +The workspace builds two binaries from the same code: + +| Binary | Built with | Role | +| --- | --- | --- | +| `charms` | default features | The CLI. `charms spell prove` forwards proving to a hosted [Prover API](/reference/prover-api). | +| `charms-prover` | `--features prover` | The proving **server** with real SP1 proving built in. Run it with `charms-prover server`. | + +Both expose the same subcommands; only `charms-prover` can generate real proofs +locally. Install the CLI with: + +```sh +cargo install --locked charms +``` + +See [Install Charms](/how-to/install-charms) for prerequisites and +[Run a prover server](/how-to/run-a-prover-server) to build `charms-prover`. + +## `charms app` + +Manage Charms apps. See [Write an app contract](/how-to/write-an-app-contract) +and [Manage app keys](/how-to/manage-app-keys). + +### `charms app new ` + +Scaffold a new app project from the +[`charms-app`](https://github.com/CharmsDev/charms-app) template (via +`cargo generate`; installs `cargo-generate` if missing). Creates a Git-initialized +directory with `src/lib.rs` (your `app_contract`), example spells under +`spells/`, and a `Cargo.toml` depending on `charms-sdk`. + +### `charms app build` + +Compile the app to WebAssembly: + +```sh +cargo build --locked --release --target=wasm32-wasip1 +``` + +Prints the path to the resulting `.wasm` binary. If `.charms/app-key.json` +exists, the freshly built binary is automatically signed and a +`.sig.yaml` is written (see `app sign`). + +### `charms app vk [PATH] [--pubkey ]` + +Print an app verification key (`vk`), a 32-byte hex value. + +- `PATH` given → `SHA-256` of that Wasm binary (an **immutable** app's vk). +- `--pubkey ` given → `SHA-256` of the x-only public key (a **versioned** + app's vk). Accepts a hex file or an `app-key.json`. +- neither → uses `.charms/app-key.json` if present, otherwise builds the app and + hashes the Wasm. + +### `charms app keygen [--out ]` + +Generate a BIP-340 (Schnorr/secp256k1) keypair for a **versioned** app and write +it as JSON `{ public_key, secret_key, vk }` (where `vk = SHA-256(public_key)`). +Default path: `.charms/app-key.json` (written `0600`; refuses to overwrite). Keep +the secret key private — it is the authority to authorize new app binaries. + +### `charms app sign [--key ] [--bin ] [--out ]` + +Produce a Schnorr signature over the app binary's `SHA-256`, authorizing it for a +versioned app. + +- `--key` default `.charms/app-key.json`. +- `--bin` default: the release build output. +- `--out` default `.sig.yaml`. A `.yaml`/`.yml` path writes a + `vk -> AppSignature` map; any other extension writes a single JSON + `AppSignature`. + +### `charms app verify [--bin ] [--sig ]` + +Verify that the signature(s) match the binary. `--sig` default +`.sig.yaml`. Checks that each entry's `SHA-256(public_key)` equals its +`vk` key and that the Schnorr signature is valid. + +## `charms spell` + +### `charms spell check` + +Validate a spell and run its app contracts **locally** (in WebAssembly, no +proof). Prints the resolved spell and the cycles each app used. + +```sh +charms spell check \ + --spell ./spells/mint-nft.yaml \ + --app-bins ./target/wasm32-wasip1/release/my_token.wasm \ + --private-inputs ./spells/mint-nft-private.yaml \ + --prev-txs +``` + +| Option | Description | +| --- | --- | +| `--spell ` | Spell YAML/JSON. Default: `/dev/stdin`. | +| `--private-inputs ` | YAML/JSON map of app → private input (`w`). | +| `--beamed-from ` | YAML/JSON map `input_index -> [source_utxo, nonce]` for [beamed](/explanation/beaming) inputs. | +| `--app-bins ...` | App `.wasm` binaries (repeatable). | +| `--app-signatures ` | YAML/JSON map `vk -> {public_key, signature}` for versioned apps. | +| `--prev-txs ...` | Prerequisite transactions (repeatable). Plain hex, `!bitcoin …`/`!cardano …` tagged forms, or JSON `{"bitcoin":"…"}`. | +| `--chain ` | `bitcoin` (default) or `cardano`. | +| `--mock` | Relax proof-related strictness (mock mode). | + +### `charms spell prove` + +Prove a spell and emit ready-to-broadcast transaction(s). Accepts every +`spell check` option, plus: + +| Option | Description | +| --- | --- | +| `--change-address ` | **Required.** Change address for the target chain. | +| `--fee-rate ` | Bitcoin fee rate. Default `2.0` (must be ≥ `1.0`). | +| `--collateral-utxo ` | **Required for `--chain cardano`.** Collateral UTXO. | +| `--payload` | Print the [Prover API](/reference/prover-api) request instead of proving. | +| `-o, --output ` | Payload format (with `--payload`). Default `json`. | + +On Bitcoin, prints a JSON array with the single unsigned spell transaction: +`[{"bitcoin":""}]`. On Cardano, prints a Ledger CDDL transaction envelope. +By default the `charms` binary forwards the proving request to the hosted +[Prover API](/reference/prover-api); build with `--features prover` (the +`charms-prover` binary) to prove locally. + +### `charms spell vk` + +Print the spell verification key as JSON (pass `--mock` for the mock key), e.g.: + +```json +{ "prover": false, "version": 15, "vk": "00425796f4c4fa050043eee14d801b4f935244e44aad6a28de0cd5cb3de0ae52" } +``` + +## `charms tx show-spell` + +Extract and verify the spell embedded in a transaction. + +```sh +charms tx show-spell --tx [--chain bitcoin|cardano] [--json] [--mock] +``` + +Prints the spell as YAML (default) or JSON (`--json`). Returns nothing if the +transaction carries no valid spell. + +## `charms wallet list` + +```sh +charms wallet list [--json] [--mock] +``` + +List the UTXOs in your local `bitcoin-cli` wallet that carry charms (Bitcoin +only). Shells out to `bitcoin-cli listunspent` and `getrawtransaction`. + +## `charms util` + +### `charms util dest` + +Compute the hex destination (`dest`) used inside `tx.coins[].dest` of a spell. + +```sh +charms util dest --addr
[--chain bitcoin|cardano] +charms util dest --apps ... --chain cardano +``` + +Exactly one of `--addr` (any address) or `--apps` (Cardano proxy-script address) +is required. The chain is auto-detected from the address when `--chain` is +omitted. + +### `charms util install-circuit-files` + +(Hidden.) Install the SP1 Groth16 circuit artifacts used for proving. + +## `charms server` + +```sh +charms server [--ip ] [--port ] +``` + +Start the REST API server exposing `POST /spells/prove` and `GET /ready`. +Defaults: `--ip 0.0.0.0`, `--port 17784`. Real proving requires the `prover` +feature — in practice you run the `charms-prover` binary +(`charms-prover server`). See [Run a prover server](/how-to/run-a-prover-server) +and the [Prover API reference](/reference/prover-api). + +## `charms completions ` + +Print shell completions for the given shell (`bash`, `zsh`, `fish`, …). Dynamic +completions are also available via `source <(COMPLETE=zsh charms)`. diff --git a/src/content/docs/reference/index.md b/src/content/docs/reference/index.md new file mode 100644 index 0000000..a56cbd5 --- /dev/null +++ b/src/content/docs/reference/index.md @@ -0,0 +1,26 @@ +--- +title: Reference +description: "Exact formats, commands, and APIs for Charms v15." +sidebar: + order: 0 +--- + +Precise, information-oriented descriptions of the Charms v15 interfaces. Use this +section to look things up; for guided learning see the +[Tutorials](/tutorials), and for task recipes see the [How-to guides](/how-to). + +- **[CLI](/reference/cli)** — every `charms` command and its options. +- **[Spell structure](/reference/spell)** — the spell as you author it + (logical), as it is serialized (on-chain), and how it is embedded in Bitcoin + and Cardano transactions. +- **[SDK](/reference/sdk)** — the `charms-sdk` / `charms-data` types, helpers, + and macros used to write app contracts. +- **[Prover API](/reference/prover-api)** — the `POST /spells/prove` HTTP + endpoint: request and response. +- **[Scrolls canister](/reference/scrolls-canister)** — the `scrolls_bitcoin_v15` + Internet Computer canister API. + +:::note[Version] +This documentation describes **Charms v15** (protocol version `15`). The current +source is at [github.com/CharmsDev/charms](https://github.com/CharmsDev/charms). +::: diff --git a/src/content/docs/reference/prover-api.md b/src/content/docs/reference/prover-api.md new file mode 100644 index 0000000..1d5a1d3 --- /dev/null +++ b/src/content/docs/reference/prover-api.md @@ -0,0 +1,114 @@ +--- +title: Prover API +description: "The POST /spells/prove HTTP endpoint: request and response." +sidebar: + order: 4 +--- + +The Prover API turns a spell into a proven, ready-to-broadcast transaction. It +runs the app contracts, generates the [proof](/explanation/spells#the-proof), and +builds the chain transaction(s). Use the hosted service or +[run your own](/how-to/run-a-prover-server). + +## Endpoints + +| Method | Path | Description | +| --- | --- | --- | +| `POST` | `/spells/prove` | Prove a spell; returns the spell transaction(s). | +| `GET` | `/ready` | Readiness check; returns `OK`. | + +### Base URL + +The `charms` CLI calls the hosted service by default: + +``` +https://v15.charms.dev/spells/prove +``` + +Override it with the `CHARMS_PROVE_API_URL` environment variable. A self-hosted +server listens on port `17784` by default +(`http://localhost:17784/spells/prove`). See +[Call the Prover API](/how-to/call-the-prover-api) and +[Run a prover server](/how-to/run-a-prover-server). + +### Content types + +The request and response bodies may be **JSON** or **CBOR**. The server picks +CBOR when the request `Content-Type` contains `application/cbor`, and JSON +otherwise; the response uses the same format. The maximum request body is +32 MiB. (The `charms` CLI sends CBOR; the examples below use JSON for +readability.) + +## Request + +`POST /spells/prove` with this body: + +| Field | Type | Description | +| --- | --- | --- | +| `spell` | object | The spell ([Spell structure](/reference/spell)). In JSON it may be the spell object or its hex-encoded CBOR. | +| `app_private_inputs` | map | (Optional) app `tag/identity/vk` → private input (`w`). Omit when empty. | +| `tx_ins_beamed_source_utxos` | map | (Optional) input index → `[source_utxo, nonce]` for [beamed](/explanation/beaming) inputs. Omit when empty. | +| `binaries` | map | (Optional) app `vk` (hex) → app `.wasm` bytes (base64 in JSON). Omit when empty. | +| `app_signatures` | map | (Optional) app `vk` (hex) → `{ public_key, signature }` for [versioned apps](/explanation/apps#immutable-and-versioned-apps). Omit when empty. | +| `prev_txs` | array | Prerequisite transactions, chain-tagged: `{"bitcoin":""}` / `{"cardano":""}` (and finality-proof forms for beaming). | +| `change_address` | string | **Required.** Change address for the target chain. | +| `fee_rate` | number | Bitcoin fee rate (sats/vB). | +| `chain` | string | `bitcoin` or `cardano`. | +| `collateral_utxo` | string | (Optional) `txid:vout` collateral. **Required for Cardano.** | + +### Example + +```javascript +const requestBody = { + spell: { + version: 15, + tx: { + ins: ["eb711823b50d368c5e0121649e414d78086cad69817b5163e871f7039ac0a4a3:0"], + outs: [{ "0": { ticker: "CHARMIX", name: "Panoramix #1" } }], + coins: [{ amount: 1000, dest: "5120…" }] + }, + app_public_inputs: { + "n/af50d82d…/a0029d4e…": null + } + }, + prev_txs: [{ bitcoin: "020000000001…" }], + change_address: "tb1putrfz7kq9yh3jymjcumq9heu9s4q7nmm8x7k55462n9rua408y9svaw3uv", + fee_rate: 2.0, + chain: "bitcoin" +}; +``` + +## Response + +A JSON (or CBOR) array of chain-tagged transactions. For a Bitcoin spell this is +a **single** unsigned transaction with the spell and proof in its `OP_RETURN` +output: + +```json +[ + { "bitcoin": "" } +] +``` + +Cardano entries are tagged `{ "cardano": "" }`. The transaction is **not +signed** — sign it (e.g. with `bitcoin-cli signrawtransactionwithwallet`) and +broadcast it. See +[Sign and broadcast](/how-to/wallet-integration/sign-and-broadcast). + +## Errors + +| Status | Meaning | +| --- | --- | +| `400` | Invalid spell, missing/invalid parameters, malformed body. | +| `500` | Transient prover failure — retry with backoff. | + +## Notes + +- Proving runs the app contracts, so include every app's binary in `binaries` + (or `--app-bins`) for any operation beyond a simple transfer. +- For [Scroll](/explanation/scrolls) outputs on Bitcoin, the prover fills the + `dest` script automatically by calling the Scrolls canister — only a prover + *server* (not mock mode) can do this. +- The `spell.tx.ins` and `spell.tx.coins` you send are used to build the + transaction; in the *serialized* on-chain spell they are stripped and + recovered from the transaction itself. diff --git a/src/content/docs/reference/scrolls-canister.md b/src/content/docs/reference/scrolls-canister.md new file mode 100644 index 0000000..9438d1e --- /dev/null +++ b/src/content/docs/reference/scrolls-canister.md @@ -0,0 +1,137 @@ +--- +title: Scrolls canister +description: "The scrolls_bitcoin_v15 Internet Computer canister API." +sidebar: + order: 5 +--- + +The `scrolls_bitcoin_v15` canister is the Bitcoin signer for Charms v15. It +derives the addresses that [Scroll](/explanation/scrolls) outputs are locked to, +and it signs and broadcasts transactions that spend those outputs — but only when +the transaction carries a valid Charms spell and pays the protocol fee. + +| | | +| --- | --- | +| Canister (IC mainnet) | `rpgc6-oqaaa-aaaak-qy3uq-cai` | +| Networks (the `network` arg) | `"main"`, `"testnet4"` | +| Access control | None at the caller level — policy-based (valid spell + fee). | + +In normal use you call only two methods: [`addresses`](#addresses) (the prover +does this for you) and [`sign_and_submit`](#sign_and_submit) (to spend a +Scroll-controlled output). See [Spend Scroll outputs](/how-to/spend-scroll-outputs). + +## Candid interface + +```candid +type Addresses = record { + script_pubkeys : vec record { nat32; text }; // out_index -> hex(scriptPubKey) + signature : text; // hex BIP-340 Schnorr signature +}; + +type SignRequest = record { + prev_txs : vec text; // hex prev txs that created the spent outputs + sign_inputs : vec nat32; // input indexes the canister must sign + tx_to_sign : text; // hex unsigned/partially-signed Bitcoin tx + v14_sign_inputs : opt vec record { nonce : nat64; index : nat64 }; +}; + +type SignAndSubmitResult = record { txid : text; wtxid : text }; + +service : { + addresses : (text, vec nat32) -> (variant { Ok : Addresses; Err : text }); + sign_and_submit : (text, SignRequest) -> (variant { Ok : SignAndSubmitResult; Err : text }); + verify_spell : (text, bool) -> (variant { Ok : text; Err : text }); + verify_spell_delegated : (text, bool, nat32, vec text) -> (variant { Ok : text; Err : text }); + config : () -> (Config) query; + cycles_balance : () -> (nat) query; + deposit_cycles : () -> (variant { Ok : nat; Err : text }); +} +``` + +## `sign_and_submit` + +```candid +sign_and_submit : (network : text, SignRequest) -> (variant { Ok : SignAndSubmitResult; Err : text }); +``` + +Signs the Scroll-controlled inputs of a transaction, enforces policy, broadcasts +it, and returns the transaction id. **This is the only method a wallet normally +needs to call.** + +Given a `network` (`"main"` or `"testnet4"`) and a `SignRequest`, the canister: + +1. parses `tx_to_sign` and validates the `sign_inputs` indexes; +2. (optional) delegates any `v14_sign_inputs` to the older v14 canister, so one + transaction can spend mixed v14/v15 Scroll UTXOs; +3. checks that every input **not** in `sign_inputs` is already signed, and every + input **in** `sign_inputs` is still unsigned (you sign your own inputs; the + canister signs only the Scroll inputs); +4. **verifies the spell** carried by `tx_to_sign` — failing if there is none; +5. **checks the fee** — the transaction must pay the configured Scrolls fee + address at least the required amount; +6. signs each requested input with the threshold key derived for that + Scroll-controlled output; +7. **broadcasts** the fully-signed transaction (via the mempool.space API); +8. returns `{ txid, wtxid }`. + +Re-broadcasting an already-confirmed transaction is idempotent (it succeeds +rather than erroring). + +```sh +dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \ + '("main", record { + sign_inputs = vec { 0 : nat32 }; + prev_txs = vec { "0200000000…" }; + tx_to_sign = "0200000000…"; + v14_sign_inputs = null; + })' +``` + +## `addresses` + +```candid +addresses : (tx_in_0 : text, out_is : vec nat32) -> (variant { Ok : Addresses; Err : text }); +``` + +Returns the canister-controlled `scriptPubKey` for each requested output index, +plus a BIP-340 Schnorr **signature** over the map. **The prover calls this +automatically** while building a spell that has Scroll outputs — you rarely call +it yourself. + +- `tx_in_0` — the first input (`txid:vout`) of the transaction that will *create* + the outputs; outputs are derived deterministically from it. (For coinbase + outputs, use the all-zeros txid with the block height in place of the vout.) +- `out_is` — the output indexes to derive (max 256 per call). +- The returned `script_pubkeys` are raw P2WPKH scripts (`OP_0 <20-byte hash>`) + that go straight into a Bitcoin output's `dest`. They are **network-independent** + (identical on `main` and `testnet4`), which is why this method takes no + `network` argument. + +The signature lets the spell proof verify, in-circuit, that these are genuinely +the canister's addresses for the given transaction. This is how a Scroll output +is provably pinned to programmable custody — see +[`fill_scroll_outputs`](/explanation/scrolls#scroll-charms). + +## Other methods + +| Method | Description | +| --- | --- | +| `verify_spell(tx, mock)` | Extract and verify the spell from a raw Bitcoin tx; returns the normalized spell as hex CBOR. | +| `verify_spell_delegated(tx, mock, spell_version, seen)` | Forward-compatible verification: delegates newer-version spells to the next canister, with cycle detection. | +| `config()` | (query) The canister's configuration (fee addresses, fee parameters). | +| `cycles_balance()` | (query) The canister's cycles balance. | +| `deposit_cycles()` | Top up the canister's cycles (it is designed to be blackholed). | + +## Calling the canister + +- **`ic-agent` / agent-rs (Rust)** — what the prover uses: build an `Agent` + against `https://ic0.app`, `Encode!` the args, and `update`/`query` the + canister, decoding the reply with `Decode!`. +- **`dfx`** — `dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai '()'`. +- **HTTP** — a Cloudflare Worker (`scrolls-api`) wraps the canister and exposes + `POST /{network}/sign`, returning `{ txid, wtxid }` as JSON. + +There is no per-caller access control: the canister signs for anyone, but only a +transaction that carries a valid spell and pays the fee. Address-derivation +integrity is protected by a canister-private secret prefix and the signed +`addresses` attestation. diff --git a/src/content/docs/reference/sdk.md b/src/content/docs/reference/sdk.md new file mode 100644 index 0000000..f4f5826 --- /dev/null +++ b/src/content/docs/reference/sdk.md @@ -0,0 +1,177 @@ +--- +title: SDK +description: "The charms-sdk / charms-data API for writing app contracts." +sidebar: + order: 3 +--- + +App contracts are written in Rust against the `charms-sdk` crate, which +re-exports the core data types as `charms_sdk::data` and provides the two macros +that wire your contract into a runnable WebAssembly module. A generated app +depends on it as: + +```toml +[dependencies] +charms-sdk = { version = "15.0.0" } +``` + +For the patterns you'll use, see +[Write an app contract](/how-to/write-an-app-contract). + +## Entry point + +```rust +use charms_sdk::data::{check, App, Data, Transaction, NFT, TOKEN}; + +pub fn app_contract(app: &App, tx: &Transaction, x: &Data, w: &Data) -> bool { + // return true iff `tx` is allowed by `app` + true +} + +// in src/main.rs: +charms_sdk::main!(my_app::app_contract); +``` + +### `charms_sdk::main!($path)` + +Generates the module's `main`: it reads the `(App, Transaction, Data, Data)` +tuple (CBOR) from stdin and asserts that `$path(&app, &tx, &x, &w)` returns +`true`. This is the convention every app uses to expose its contract. + +### `charms_sdk::app_version!($version)` + +For [versioned apps](/explanation/apps#immutable-and-versioned-apps). Expands to +`pub const VERSION: u32 = $version;` and exports an `__app_version()` function so +the runtime can confirm the running binary matches the version pinned in the +spell. Requires Rust edition 2024. + +## Core types + +All under `charms_sdk::data` (re-exported from `charms_data`). + +### `App` + +```rust +pub struct App { + pub tag: char, // 'n' NFT, 't' token, 's' Scroll, or any custom tag + pub identity: B32, // 32-byte asset identity + pub vk: B32, // app verification key +} +``` + +Displays / parses as the string `tag/identity_hex/vk_hex`. + +### `Transaction` + +```rust +pub struct Transaction { + pub ins: Vec<(UtxoId, Charms)>, // inputs and their charms + pub refs: Vec<(UtxoId, Charms)>, // reference inputs and their charms + pub outs: Vec, // outputs and their charms + pub coin_ins: Option>, + pub coin_outs: Option>, + pub prev_txs: BTreeMap, + pub app_public_inputs: BTreeMap, +} +``` + +### `Charms` + +```rust +pub type Charms = BTreeMap; // the app -> data map carried by a UTXO +``` + +### `Data` + +An opaque CBOR value. Construct it from any `Serialize` type, and read it back +with `value::()`: + +```rust +let n: u64 = x.value()?; // deserialize the public input +let d: Data = Data::from(&my_struct); // serialize anything +Data::empty(); // the empty value +data.is_empty(); +``` + +### `UtxoId`, `TxId`, `B32` + +```rust +pub struct UtxoId(pub TxId, pub u32); // "txid:index"; 36 bytes via to_bytes() +pub struct TxId(pub [u8; 32]); // hex (Bitcoin-style reversed) +pub struct B32(pub [u8; 32]); // 32-byte value, hex Display/FromStr +``` + +### `NativeOutput` + +```rust +pub struct NativeOutput { + pub amount: u64, + pub dest: Vec, + pub content: Option, +} +``` + +## Constants + +```rust +pub const TOKEN: char = 't'; +pub const NFT: char = 'n'; +pub const SCROLL: char = 's'; +``` + +## Helpers + +### `check!` + +```rust +check!(condition); // early-return false from a -> bool fn if false +check!(cond, "message"); // with a message printed to stderr +``` + +The idiomatic way to assert inside a contract: if the condition fails, the +contract returns `false` (and the failing expression is logged). + +### `charm_values` + +```rust +pub fn charm_values<'a>( + app: &'a App, + charms: impl Iterator, +) -> impl Iterator; +``` + +Yields the `Data` values for `app` across the given charms (e.g. all outputs). +(Replaces the deprecated `app_datas`.) + +### `sum_token_amount` + +```rust +pub fn sum_token_amount<'a>( + app: &App, + charms: impl Iterator, +) -> anyhow::Result; +``` + +Sum a fungible token's amounts across charms. Requires `app.tag == TOKEN`. + +### Simple-transfer predicates + +```rust +pub fn is_simple_transfer(app: &App, tx: &Transaction) -> bool; +pub fn token_amounts_balanced(app: &App, tx: &Transaction) -> bool; +pub fn nft_state_preserved(app: &App, tx: &Transaction) -> bool; +``` + +Useful when a contract wants to allow plain transfers and only enforce extra +rules on mint/burn. + +## Versioned-app types + +Used by the proving/verification layer (rarely by a simple contract): + +```rust +pub struct VersionedApp { pub version: u32, pub wasm_hash: B32 } +pub struct AppSignature { pub public_key: B32, pub signature: [u8; 64] } // BIP-340 +``` + +See [Manage app keys](/how-to/manage-app-keys). diff --git a/src/content/docs/reference/spell.md b/src/content/docs/reference/spell.md new file mode 100644 index 0000000..17d1fb7 --- /dev/null +++ b/src/content/docs/reference/spell.md @@ -0,0 +1,210 @@ +--- +title: Spell structure +description: "The spell as you author it, as it is serialized on-chain, and how it rides inside Bitcoin and Cardano transactions." +sidebar: + order: 2 +--- + +A **spell** is the metadata added to a blockchain transaction to make it also a +Charms transaction: spells create and transform charms. This page is the +authoritative reference for the spell's three faces: + +1. the **logical** spell you author (YAML/JSON); +2. the **serialized** spell that lives on-chain (CBOR + proof); +3. the **on-chain transaction structure** that carries it, on Bitcoin and on + Cardano. + +For the concepts behind it, see [Spells](/explanation/spells) and +[Transactions](/explanation/transactions). + +## Logical structure + +You author a spell as YAML (or JSON). It deserializes directly into the +`NormalizedSpell` structure, using ergonomic human-readable forms (apps as +`tag/identity/vk` strings, UTXOs as `txid:vout`, byte arrays as hex). + +```yaml +version: 15 +tx: + ins: + - 33027a870a0f8c7b3d3114d970b6e67d11b32316ad5b6c58bdc7e0d8e77f7e6a:1 + refs: + - 92077a14998b31367efeec5203a00f1080facdb270cbf055f09b66ae0a273c7d:0 + outs: + - 0: + ticker: TOAD + remaining: 30160 + 1: 42 + - 2: 69420 + beamed_outs: + 1: 009fb48961bca8ec68f01ec882f7ec0dc7dc5cc6bcf4ad154f129ea2338f6cd1 + coins: + - amount: 1000 + dest: 51207c4bb238ab772a2000906f3958ca5f15d3a80d563f17eb4123c5b7c135b128dc + scrolls: [0] +app_public_inputs: + n/f54f6d40…/7df79205…: + t/7e7e5623…/b25ddd68…: +``` + +### Top-level fields + +| Field | Type | Description | +| --- | --- | --- | +| `version` | integer | Protocol version. Use `15` for the current prover. | +| `tx` | object | The normalized transaction payload (below). | +| `app_public_inputs` | map | All apps in the spell → each app's public input (`x`). | +| `versioned_apps` | map | (Optional) `vk -> { version, wasm_hash }` for [versioned apps](/explanation/apps#immutable-and-versioned-apps). Omit when empty. | +| `mock` | bool | (Optional) `true` only for mock-proving workflows. Omit otherwise. | + +:::note +Spells with lower versions exist on-chain and are recognized by clients for +backward compatibility, but only the current `version` is accepted by the +prover. +::: + +### `tx` + +| Field | Type | Description | +| --- | --- | --- | +| `ins` | list | Input UTXOs spent (`txid:vout`). Omitted in the serialized form (recovered from the hosting transaction). | +| `refs` | list | (Optional) reference UTXOs — read, not spent. | +| `outs` | list | Output *strings of charms*. Each entry maps an **app index** (`0`, `1`, …) to that app's charm data. | +| `beamed_outs` | map | (Optional) output index → `SHA-256` hash of the destination UTXO id, for [beaming](/explanation/beaming) out. | +| `coins` | list | Native coin outputs (below). One per transaction output. | +| `scrolls` | list | (Optional) output indexes that carry [Scroll](/explanation/scrolls) charms and must be sent to Scrolls-controlled addresses. | + +**App indexes.** In `outs` (and `scrolls`, `beamed_outs`), outputs reference apps +by their **index** into `app_public_inputs`, taken in sorted key order: `0` is +the first app, `1` the second, and so on. + +**`coins` entries:** + +| Field | Type | Description | +| --- | --- | --- | +| `amount` | integer | Native amount (sats on Bitcoin, lovelace on Cardano). | +| `dest` | hex | Destination: a Bitcoin `scriptPubKey` or Cardano address bytes. Derive it with [`charms util dest`](/reference/cli#charms-util-dest). | +| `content` | object | (Optional, Cardano) extra output content — `multiasset`, `datum`, `script_ref`. | + +### `app_public_inputs` + +Maps each app in the spell to its public input data (`x`): + +```yaml +app_public_inputs: + n//: # NFT app — null value (no public input) + t//: # fungible-token app + c/0000…0000/: # a general "contract" app with public input: + param: value + s//: # Scroll app +``` + +App keys are `tag/identity/vk`: + +- `n/…` — NFT app +- `t/…` — fungible-token app +- `s/…` — [Scroll](/explanation/scrolls) app +- any other tag (e.g. `c/…`) — a general app whose logic is fully defined by its + contract + +Values may be empty (`null`) for simple transfers. + +### Private inputs are *not* part of the spell + +An app's **private input** (`w`, the witness) is never published, so it is not in +the spell. Pass it separately: + +```sh +charms spell prove --private-inputs ./private-inputs.yaml … +``` + +```yaml +# private-inputs.yaml — app -> private input data +n//: "" +``` + +In a [Prover API](/reference/prover-api) request, private inputs go in the +`app_private_inputs` field. + +## Serialized (on-chain) form + +On-chain, a spell is stored together with its proof as a single CBOR-encoded +pair: + +``` +cbor( (NormalizedSpell, Proof) ) +``` + +- **`NormalizedSpell`** is the structure above, with two fields stripped because + they can be recovered from the hosting transaction: `tx.ins` and `tx.coins` + are both cleared (set to absent). On extraction, the input list is taken from + the hosting transaction's inputs. +- **`Proof`** is a byte string: the **Groth16** SNARK (BN254) attesting that the + spell is [correct](/explanation/spells#what-makes-a-spell-correct). It is + produced by an [SP1](https://docs.succinct.xyz/) zkVM pipeline — a + `charms-spell-checker` proof wrapped into Groth16 — and is recursive, so it + also covers every prerequisite transaction's spell. + +The values committed by the proof are the CBOR of `(spell_vk, NormalizedSpell)`, +where `spell_vk` is the 32-byte spell verification key +(`00425796f4c4fa050043eee14d801b4f935244e44aad6a28de0cd5cb3de0ae52` for v15; see +[`charms spell vk`](/reference/cli#charms-spell-vk)). + +## On-chain transaction structure + +### On Bitcoin + +A Bitcoin spell is a **single transaction** that carries the serialized +`(spell, proof)` pair in an `OP_RETURN` output: + +``` +OP_RETURN + OP_PUSH "spell" # the marker b"spell" + OP_PUSH +``` + +That transaction: + +- spends the spell's input UTXOs; +- creates one output per `tx.coins` entry (value `amount`, script `dest`), + carrying the resulting charms; +- includes the `OP_RETURN` spell output (value `0`); +- optionally adds a Charms protocol fee output; +- sends the remainder to the `--change-address`. + +There is **no commit/reveal**: everything is in one transaction. The +[Prover API](/reference/prover-api) returns it as an unsigned hex transaction in +a one-element array `[{"bitcoin":""}]`; you sign and broadcast it yourself. + +### On Cardano + +A Cardano spell is also a single transaction, but the spell is attached +differently: + +- **Spell location.** The `(spell, proof)` pair is wrapped as a Plutus + `BoundedBytes` value and attached as the **inline datum** of a dedicated + small-ADA output (sent to the Charms fee address). +- **Charms as native assets.** Token and NFT charms are Cardano **native + assets**, minted/burned by per-app PlutusV3 minting policies parameterized by + the app `vk`. Non-token apps are spent from a shared proxy script address. +- **Collateral.** Because the transaction runs Plutus scripts, a **collateral + UTXO** is required — pass it as `charms spell prove --collateral-utxo + `. +- **Co-signing.** Cardano spell transactions are signed by the Cardano + [Scrolls](/explanation/scrolls) canister as part of proving. + +The Prover API returns Cardano transactions tagged `{"cardano":""}` (a +Ledger CDDL envelope). + +## Beamed inputs + +When a spell *receives* a [beamed](/explanation/beaming) charm, the source UTXO +on the other chain is supplied out of band (it is not a field of the spell +itself): + +- CLI: `charms spell prove --beamed-from '{: [, ]}'` +- Prover API: the `tx_ins_beamed_source_utxos` field. + +The corresponding source transaction — carrying its finality proof — is passed +in `--prev-txs` (CLI) / `prev_txs` (API). See +[Beam charms across chains](/how-to/beam-charms). diff --git a/src/content/docs/references/spell-json.md b/src/content/docs/references/spell-json.md deleted file mode 100644 index c406892..0000000 --- a/src/content/docs/references/spell-json.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: Spell JSON Reference -sidebar: - order: 1 ---- - -_Spell_ is the metadata added to a Bitcoin transaction to make it also a Charms transaction: spells create charms. This reference provides an explanation of each parameter in the Spell JSON format. - -## Structure Overview - -The Spell JSON has the following top-level fields: - -1. **`version`**: Protocol version identifier -2. **`tx`**: Normalized transaction payload (`ins`, `refs`, `outs`, optional `beamed_outs`, optional `coins`) -3. **`app_public_inputs`**: App definitions and public input data -4. **`mock`**: Optional boolean used for mock proving - -## Parameter Details - -### `version` - -Protocol version number. - -```json -"version": 11 -``` - -**Required Value**: Must be `11` for Charms CLI `v11.0.1`. - -Spells exist on-chain with lower versions, and they are recognized by the client, but are not supported by the prover. - -### `tx` - -Normalized transaction payload. - -```json -"tx": { - "ins": [ - ":", - ":" - ], - "refs": [ - ":" - ], - "outs": [ - { - "0": { - "ticker": "TOAD", - "remaining": 30160 - }, - "1": 42 - }, - { - "2": 69420 - } - ], - "beamed_outs": { - "1": "009fb48961bca8ec68f01ec882f7ec0dc7dc5cc6bcf4ad154f129ea2338f6cd1" - }, - "coins": [ - { - "amount": 1000, - "dest": "2f7e10b8f6e2089b5bb5dcce96e8dd49ca01012f6506af0fe7bf5d2f2f5db531" - } - ] -} -``` - -- **`ins`**: Input UTXOs spent by the transaction (`txid:vout`). Optional in serialized spells. -- **`refs`**: Optional reference UTXOs. -- **`outs`**: Output charms. Each output is a map of **app index** to charm data. -- **`beamed_outs`**: Optional map of output index to destination UTXO hash for beaming. -- **`coins`**: Optional native coin outputs (`amount` and hex-encoded `dest`). - -Use `charms util dest` to derive output `dest` from an address when constructing `coins` entries. - -### `app_public_inputs` - -Maps each app in the spell to that app's public input data. - -```json -"app_public_inputs": { - "n//": { - "ticker": "TOAD", - "remaining": 30580 - }, - "t//": null, - "c/0000000000000000000000000000000000000000000000000000000000000000/": { - "param": "value" - } -} -``` - -- App keys are in `tag/identity/vk` format: - - `n/...` for NFT apps - - `t/...` for fungible token apps - - `c/...` for contract apps -- Public input values can be `null` for simple transfers. - -App indexes used in `tx.outs` (`0`, `1`, `2`, ...) refer to this map in sorted key order. - -### `mock` - -```json -"mock": false -``` - -Optional. Use `true` only for mock-mode workflows. - -## About Private Inputs - -Private app inputs are **not part of Spell JSON** in v11.0.1. Pass them separately to proving/checking interfaces: - -```sh -charms spell prove --private-inputs=./private-inputs.yaml ... -``` - -- For API requests, use `app_private_inputs` in the prover payload. - -## Implementation Tips - -- Keep `version` at `11`. -- Ensure all app indexes in `tx.outs` are valid indexes into `app_public_inputs`. -- Include all prerequisite transactions in `prev_txs` when checking/proving. -- Validate spell shape with `charms spell check` before proving. diff --git a/src/content/docs/tutorials/build-a-charms-app.md b/src/content/docs/tutorials/build-a-charms-app.md new file mode 100644 index 0000000..633b177 --- /dev/null +++ b/src/content/docs/tutorials/build-a-charms-app.md @@ -0,0 +1,108 @@ +--- +title: Build a Charms app +description: "Create a Charms app and check a spell locally — no blockchain required." +--- + +In this tutorial you'll install the Charms tools, scaffold an app, build it, and +check a spell against it — entirely on your machine. By the end you'll have a +working app and you'll have seen its contract accept a mint. + +## Before you begin + +Install the prerequisites and the CLI (details in +[Install Charms](/how-to/install-charms)): + +```sh +rustup target add wasm32-wasip1 # WebAssembly target +brew install protobuf # Protocol Buffers compiler (macOS) + +export CARGO_TARGET_DIR=$(mktemp -d)/target # note: must end with /target +cargo install --locked charms +``` + +Check it works: + +```sh +charms spell vk +# { "prover": false, "version": 15, "vk": "0042…ae52" } +``` + +## 1. Create the app + +```sh +charms app new my-token +cd ./my-token +cargo update +``` + +This scaffolds a Git-initialized project. The interesting file is `src/lib.rs` — +your **app contract**. The template implements a fungible token managed by a +reference NFT: the NFT's state holds the `remaining` supply, and whoever controls +the NFT can mint tokens by reducing it. Read +[Write an app contract](/how-to/write-an-app-contract) for a walkthrough of the +code. + +## 2. Build it and get its verification key + +```sh +app_bin=$(charms app build) +charms app vk $app_bin +``` + +`charms app build` compiles the app to WebAssembly and prints the path to the +`.wasm` file. `charms app vk` prints the app's **verification key** — a 32-byte +hex value that identifies your app's code, something like: + +``` +8e877d70518a5b28f5221e70bd7ff7692a603f3a26d7076a5253e21c304a354f +``` + +## 3. Check an NFT-mint spell + +The project ships example spells under `spells/`. Let's check the NFT mint +locally — no network, no proving, just running the contract. Set the environment +variables the spell template uses. The app's `identity` (`app_id`) is the +SHA-256 of the UTXO you're "spending": + +```sh +export app_vk=$(charms app vk $app_bin) + +# the UTXO whose id seeds this NFT (any value works for a local check) +export in_utxo_0="d8fa4cdade7ac3dff64047dc73b58591ebe638579881b200d4fea68fc84521f0:0" +export app_id=$(echo -n "${in_utxo_0}" | sha256sum | cut -d' ' -f1) + +export dest_0=$(charms util dest --addr tb1p3w06fgh64axkj3uphn4t258ehweccm367vkdhkvz8qzdagjctm8qaw2xyv) +export amount_0=20000 + +# the raw transaction that produced in_utxo_0 (a prerequisite for checking) +prev_txs=02000000000101a3a4c09a03f771e863517b8169ad6c08784d419e6421015e8c360db5231871eb0200000000fdffffff024331070000000000160014555a971f96c15bd5ef181a140138e3d3c960d6e1204e0000000000002251207c4bb238ab772a2000906f3958ca5f15d3a80d563f17eb4123c5b7c135b128dc0140e3d5a2a8c658ea8a47de425f1d45e429fbd84e68d9f3c7ff9cd36f1968260fa558fe15c39ac2c0096fe076b707625e1ae129e642a53081b177294251b002ddf600000000 +``` + +Now run the check, passing the app binary, the prerequisite transaction, and the +private inputs (the witness — here, the minting UTXO): + +```sh +cat ./spells/mint-nft.yaml | envsubst | charms spell check \ + --prev-txs=${prev_txs} \ + --app-bins=${app_bin} \ + --private-inputs=<(cat ./spells/mint-nft-private.yaml | envsubst) +``` + +If all is well, you'll see that the NFT-mint contract is satisfied, along with +the cycles the contract used. 🎉 + +:::note[What just happened] +`charms spell check` ran your app's `app_contract` in WebAssembly against the +spell, with no proof generated. The `mint-nft.yaml` spell mints one NFT; the +`mint-nft-private.yaml` file passes the minting UTXO to the contract as its +private witness. +::: + +Keep the same `app_id` as you explore the other example spells (`mint-token.yaml`, +`send.yaml`): you create an `app_id` when you mint the NFT, then reuse it for the +lifetime of that NFT and its associated tokens. + +## Next + +You've built an app and checked a spell locally. Next, put a spell on a real +blockchain: [Cast your first spell](/tutorials/cast-your-first-spell). diff --git a/src/content/docs/tutorials/cast-your-first-spell.md b/src/content/docs/tutorials/cast-your-first-spell.md new file mode 100644 index 0000000..6aa3c80 --- /dev/null +++ b/src/content/docs/tutorials/cast-your-first-spell.md @@ -0,0 +1,104 @@ +--- +title: Cast your first spell +description: "Mint an NFT on Bitcoin testnet4: prove a spell, sign it, and broadcast it." +--- + +In [Build a Charms app](/tutorials/build-a-charms-app) you checked a spell +locally. Now you'll cast one for real: mint an NFT on Bitcoin `testnet4` by +proving the spell, signing the transaction, and broadcasting it. + +## Before you begin + +- Finish [Build a Charms app](/tutorials/build-a-charms-app) — you'll reuse that + project. +- Set up a [Bitcoin node on `testnet4`](/how-to/set-up-a-bitcoin-node) with a + funded wallet. We assume `alias b=bitcoin-cli` and `jq` is installed. + +Move into your app directory and rebuild it: + +```sh +cd ./my-token +app_bin=$(charms app build) +export app_vk=$(charms app vk $app_bin) +export RUST_LOG=info +``` + +## 1. Pick a UTXO to spend + +The NFT's identity is derived from a UTXO you spend when minting. Pick one you +control and record the transaction that created it (the prover needs it): + +```sh +# choose a UTXO from your wallet +export in_utxo_0=$(b listunspent | jq -r '.[0] | "\(.txid):\(.vout)"') + +# the NFT's identity = SHA-256 of that UTXO id +export app_id=$(echo -n "${in_utxo_0}" | sha256sum | cut -d' ' -f1) + +# the raw transaction that produced the UTXO (a prerequisite for proving) +export prev_txs=$(b getrawtransaction $(echo $in_utxo_0 | cut -d: -f1)) +``` + +## 2. Fill in the spell's outputs + +The `mint-nft.yaml` template puts the new NFT on a fresh output. Derive the +destination from a new wallet address, and set the output amount and a change +address: + +```sh +export dest_0=$(charms util dest --addr $(b getnewaddress)) +export amount_0=20000 # sats carried by the NFT output +change_address=$(b getrawchangeaddress) +``` + +## 3. Prove the spell + +Proving runs the app contract and generates the zero-knowledge proof. By default +the CLI sends the request to the hosted prover at `https://v15.charms.dev` — this +takes a little while. + +```sh +out=$(cat ./spells/mint-nft.yaml | envsubst | charms spell prove \ + --app-bins=$app_bin \ + --prev-txs=$prev_txs \ + --private-inputs=<(cat ./spells/mint-nft-private.yaml | envsubst) \ + --change-address=$change_address) +``` + +`charms spell prove` prints a JSON array containing one unsigned Bitcoin +transaction — the spell transaction, with the spell and its proof in an +`OP_RETURN` output. Extract its hex: + +```sh +tx=$(echo "$out" | jq -r '.[0].bitcoin') +``` + +## 4. Sign and broadcast + +Sign with your wallet, then send it to the network: + +```sh +signed=$(b signrawtransactionwithwallet "$tx" | jq -r '.hex') +b sendrawtransaction "$signed" +``` + +`sendrawtransaction` prints the txid. Your NFT is now minted on `testnet4`! 🎉 + +## 5. Verify + +Inspect the spell carried by your transaction: + +```sh +charms tx show-spell --tx "$signed" +``` + +You can also look the txid up on +[mempool.space/testnet4](https://mempool.space/testnet4). + +## What's next + +- Mint tokens against your NFT, or transfer charms — see the + [How-to guides](/how-to). +- Understand what just happened: [Spells](/explanation/spells) and + [Transactions](/explanation/transactions). +- Run proving yourself: [Run a prover server](/how-to/run-a-prover-server). diff --git a/src/content/docs/tutorials/index.md b/src/content/docs/tutorials/index.md new file mode 100644 index 0000000..7a47554 --- /dev/null +++ b/src/content/docs/tutorials/index.md @@ -0,0 +1,17 @@ +--- +title: Tutorials +description: "Learn Charms by building: from an empty directory to a charm on Bitcoin." +--- + +New to Charms? These tutorials take you, step by step, from nothing to a real +charm on Bitcoin. Follow them in order — each one builds on the last. You don't +need to understand everything as you go; the goal is to *do* it and see it work. +Once you have, the [Explanation](/explanation) section fills in the why, and the +[Reference](/reference) section has the details. + +1. **[Build a Charms app](/tutorials/build-a-charms-app)** — install the tools, + create an app, and check a spell locally. No blockchain required. +2. **[Cast your first spell](/tutorials/cast-your-first-spell)** — mint an NFT on + Bitcoin `testnet4`: prove the spell, sign it, and broadcast it. + +When you're done, see the [How-to guides](/how-to) for specific tasks. From 2ea2283e64f6ad7d89b6d3c4ab63c5b3443903a4 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 13:56:57 -0700 Subject: [PATCH 05/16] Update Bitcoin Core version requirement to v30 in node setup guide --- src/content/docs/how-to/set-up-a-bitcoin-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/how-to/set-up-a-bitcoin-node.md b/src/content/docs/how-to/set-up-a-bitcoin-node.md index fd71818..b649891 100644 --- a/src/content/docs/how-to/set-up-a-bitcoin-node.md +++ b/src/content/docs/how-to/set-up-a-bitcoin-node.md @@ -8,7 +8,7 @@ To cast spells on Bitcoin you need a Bitcoin Core node. This guide sets one up o ## Bitcoin Core -Bitcoin Core **v28.0 or later** is required. Install it with Homebrew: +Bitcoin Core **v30 or later** is required. Install it with Homebrew: ```sh brew install bitcoin From a6a18a23e0784b4514e542c91d379b3453f33918 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 14:19:30 -0700 Subject: [PATCH 06/16] Clarify NETWORK_PRIVATE_KEY failure mode in run-a-prover-server The SP1 SDK reads NETWORK_PRIVATE_KEY lazily when it builds the network prover (on the first proof request, via a Shared once-cell), not at server startup. Correct "the server will fail to start" to reflect that the process starts and the first prove fails. The env var name itself is confirmed correct against sp1-sdk network/builder.rs. Surfaced by an independent grok audit. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/content/docs/how-to/run-a-prover-server.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/content/docs/how-to/run-a-prover-server.md b/src/content/docs/how-to/run-a-prover-server.md index 397b690..08ba113 100644 --- a/src/content/docs/how-to/run-a-prover-server.md +++ b/src/content/docs/how-to/run-a-prover-server.md @@ -62,9 +62,10 @@ export NETWORK_PRIVATE_KEY=0x… # your Succinct Prover Network private ke charms-prover server ``` -`NETWORK_PRIVATE_KEY` is **required** when a backend is `network` — the server -will fail to start without it. This is the key for your Succinct account, which -pays for proof requests. +`NETWORK_PRIVATE_KEY` is **required** for network proving: the SP1 SDK looks it +up when it builds the network prover, which happens on the **first proof +request**. The server process starts without it, but the first prove will fail. +It is the key for your Succinct account, which pays for proof requests. ### Prove locally on CPU (no network) From 6743715a294429142ef70b2f81395c28c3e48fa1 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 14:52:15 -0700 Subject: [PATCH 07/16] Fix v15 doc inaccuracies and fill content gaps Correct Bitcoin Core minimum (v28.0+ for testnet4), add missing prev_txs in the app-contract guide, document Cardano Scrolls canister and clarify that scrolls-api HTTP targets v14 only, fix broken scrolls anchor link, and align fee_rate defaults and install prerequisites with the source. --- astro.config.mjs | 2 +- src/content/docs/how-to/install-charms.md | 5 +- .../docs/how-to/set-up-a-bitcoin-node.md | 5 +- .../docs/how-to/spend-scroll-outputs.md | 7 ++- .../wallet-integration/sign-and-broadcast.md | 7 ++- .../docs/how-to/write-an-app-contract.md | 3 + src/content/docs/index.mdx | 2 +- src/content/docs/reference/index.md | 4 +- src/content/docs/reference/prover-api.md | 2 +- .../docs/reference/scrolls-canister.md | 61 +++++++++++++++++-- .../docs/tutorials/cast-your-first-spell.md | 5 +- 11 files changed, 81 insertions(+), 22 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index e5c5014..6ee6e8b 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -116,7 +116,7 @@ export default defineConfig({ { label: 'Spell structure', link: '/reference/spell' }, { label: 'SDK', link: '/reference/sdk' }, { label: 'Prover API', link: '/reference/prover-api' }, - { label: 'Scrolls canister', link: '/reference/scrolls-canister' }, + { label: 'Scrolls canisters', link: '/reference/scrolls-canister' }, ], }, { diff --git a/src/content/docs/how-to/install-charms.md b/src/content/docs/how-to/install-charms.md index c20c5f8..d424c6d 100644 --- a/src/content/docs/how-to/install-charms.md +++ b/src/content/docs/how-to/install-charms.md @@ -9,8 +9,9 @@ This guide installs the `charms` command-line tool. To run your own prover, see ## Prerequisites -- **[Rust](https://rust-lang.org/)** (stable toolchain, via - [rustup](https://rustup.rs/)). +- **[Rust](https://rust-lang.org/)** 1.94 or later (stable toolchain, via + [rustup](https://rustup.rs/)). Charms v15 and its app template use Rust edition + 2024. - The **Protocol Buffers compiler `protoc`** — [`protobuf`](https://protobuf.dev/downloads/): diff --git a/src/content/docs/how-to/set-up-a-bitcoin-node.md b/src/content/docs/how-to/set-up-a-bitcoin-node.md index b649891..c8cfef6 100644 --- a/src/content/docs/how-to/set-up-a-bitcoin-node.md +++ b/src/content/docs/how-to/set-up-a-bitcoin-node.md @@ -8,7 +8,10 @@ To cast spells on Bitcoin you need a Bitcoin Core node. This guide sets one up o ## Bitcoin Core -Bitcoin Core **v30 or later** is required. Install it with Homebrew: +Bitcoin Core **v28.0 or later** is required (`testnet4` was added in v28.0). A +recent release is recommended — spell transactions carry a larger `OP_RETURN` than +the historical 80-byte standardness limit, and current Bitcoin Core versions +relay them. Install with Homebrew: ```sh brew install bitcoin diff --git a/src/content/docs/how-to/spend-scroll-outputs.md b/src/content/docs/how-to/spend-scroll-outputs.md index b449ed2..e68f31e 100644 --- a/src/content/docs/how-to/spend-scroll-outputs.md +++ b/src/content/docs/how-to/spend-scroll-outputs.md @@ -54,9 +54,10 @@ programmable custody enforced by Charms logic. ## Calling without dfx -You can call the canister with any Internet Computer agent -(`ic-agent`/agent-rs), or over HTTP via the `scrolls-api` service, which exposes -`POST /{network}/sign` and returns `{ txid, wtxid }` as JSON. +Call the v15 canister with any Internet Computer agent (`ic-agent`/agent-rs). +The `scrolls-api` HTTP wrapper (`POST /{network}/sign`) targets the older **v14** +canister and its nonce-based addresses — use it only for legacy v14 Scroll UTXOs, +not for v15. See the [Scrolls canister reference](/reference/scrolls-canister) for the full method signatures and the `SignRequest` shape. diff --git a/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md b/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md index 8a86a03..9a7c672 100644 --- a/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md +++ b/src/content/docs/how-to/wallet-integration/sign-and-broadcast.md @@ -32,9 +32,10 @@ bitcoin-cli sendrawtransaction ## Considerations -- **Fee rate.** The fee is set when you prove (the Prover API `fee_rate`, default - `2.0` sats/vB). Choose a rate appropriate to network conditions so the - transaction is accepted into the mempool and confirmed. +- **Fee rate.** The fee is set when you prove (`fee_rate` in the Prover API + request, or `--fee-rate` on the CLI — default `2.0` sats/vB). Choose a rate + appropriate to network conditions so the transaction is accepted into the + mempool and confirmed. - **Validate before sending.** Confirm the transaction is well-formed and the inputs are still unspent before broadcasting. - **One transaction.** There is no commit/reveal step — signing and broadcasting diff --git a/src/content/docs/how-to/write-an-app-contract.md b/src/content/docs/how-to/write-an-app-contract.md index 5817516..351857a 100644 --- a/src/content/docs/how-to/write-an-app-contract.md +++ b/src/content/docs/how-to/write-an-app-contract.md @@ -130,6 +130,9 @@ export app_id=$(echo -n "${in_utxo_0}" | sha256sum | cut -d' ' -f1) export dest_0=$(charms util dest --addr tb1p3w06fgh64axkj3uphn4t258ehweccm367vkdhkvz8qzdagjctm8qaw2xyv) export amount_0=20000 +# the raw transaction that produced in_utxo_0 (a prerequisite for checking) +prev_txs=02000000000101a3a4c09a03f771e863517b8169ad6c08784d419e6421015e8c360db5231871eb0200000000fdffffff024331070000000000160014555a971f96c15bd5ef181a140138e3d3c960d6e1204e0000000000002251207c4bb238ab772a2000906f3958ca5f15d3a80d563f17eb4123c5b7c135b128dc0140e3d5a2a8c658ea8a47de425f1d45e429fbd84e68d9f3c7ff9cd36f1968260fa558fe15c39ac2c0096fe076b707625e1ae129e642a53081b177294251b002ddf600000000 + cat ./spells/mint-nft.yaml | envsubst | charms spell check \ --prev-txs=$prev_txs \ --app-bins=$app_bin \ diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index 4d4f653..e508f7c 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -44,7 +44,7 @@ import { Card, CardGrid } from '@astrojs/starlight/components'; ```sh ## edit the spell at ./spells/mint-nft.yaml, then run - charms spell check --spell=./spells/mint-nft.yaml + charms spell check --spell=./spells/mint-nft.yaml --app-bins=… ``` diff --git a/src/content/docs/reference/index.md b/src/content/docs/reference/index.md index a56cbd5..13eca47 100644 --- a/src/content/docs/reference/index.md +++ b/src/content/docs/reference/index.md @@ -17,8 +17,8 @@ section to look things up; for guided learning see the and macros used to write app contracts. - **[Prover API](/reference/prover-api)** — the `POST /spells/prove` HTTP endpoint: request and response. -- **[Scrolls canister](/reference/scrolls-canister)** — the `scrolls_bitcoin_v15` - Internet Computer canister API. +- **[Scrolls canisters](/reference/scrolls-canister)** — the + `scrolls_bitcoin_v15` and `scrolls_cardano` Internet Computer canister APIs. :::note[Version] This documentation describes **Charms v15** (protocol version `15`). The current diff --git a/src/content/docs/reference/prover-api.md b/src/content/docs/reference/prover-api.md index 1d5a1d3..5ff009b 100644 --- a/src/content/docs/reference/prover-api.md +++ b/src/content/docs/reference/prover-api.md @@ -52,7 +52,7 @@ readability.) | `app_signatures` | map | (Optional) app `vk` (hex) → `{ public_key, signature }` for [versioned apps](/explanation/apps#immutable-and-versioned-apps). Omit when empty. | | `prev_txs` | array | Prerequisite transactions, chain-tagged: `{"bitcoin":""}` / `{"cardano":""}` (and finality-proof forms for beaming). | | `change_address` | string | **Required.** Change address for the target chain. | -| `fee_rate` | number | Bitcoin fee rate (sats/vB). | +| `fee_rate` | number | Bitcoin fee rate (sats/vB). Defaults to `0.0` if omitted (the CLI defaults to `2.0`). | | `chain` | string | `bitcoin` or `cardano`. | | `collateral_utxo` | string | (Optional) `txid:vout` collateral. **Required for Cardano.** | diff --git a/src/content/docs/reference/scrolls-canister.md b/src/content/docs/reference/scrolls-canister.md index 9438d1e..45dafbf 100644 --- a/src/content/docs/reference/scrolls-canister.md +++ b/src/content/docs/reference/scrolls-canister.md @@ -1,10 +1,12 @@ --- -title: Scrolls canister -description: "The scrolls_bitcoin_v15 Internet Computer canister API." +title: Scrolls canisters +description: "The scrolls_bitcoin_v15 and scrolls_cardano Internet Computer canister APIs." sidebar: order: 5 --- +## `scrolls_bitcoin_v15` + The `scrolls_bitcoin_v15` canister is the Bitcoin signer for Charms v15. It derives the addresses that [Scroll](/explanation/scrolls) outputs are locked to, and it signs and broadcasts transactions that spend those outputs — but only when @@ -110,7 +112,7 @@ it yourself. The signature lets the spell proof verify, in-circuit, that these are genuinely the canister's addresses for the given transaction. This is how a Scroll output is provably pinned to programmable custody — see -[`fill_scroll_outputs`](/explanation/scrolls#scroll-charms). +[Scroll charms](/explanation/scrolls#scroll-charms). ## Other methods @@ -122,16 +124,63 @@ is provably pinned to programmable custody — see | `cycles_balance()` | (query) The canister's cycles balance. | | `deposit_cycles()` | Top up the canister's cycles (it is designed to be blackholed). | -## Calling the canister +## Calling the Bitcoin canister - **`ic-agent` / agent-rs (Rust)** — what the prover uses: build an `Agent` against `https://ic0.app`, `Encode!` the args, and `update`/`query` the canister, decoding the reply with `Decode!`. - **`dfx`** — `dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai '()'`. -- **HTTP** — a Cloudflare Worker (`scrolls-api`) wraps the canister and exposes - `POST /{network}/sign`, returning `{ txid, wtxid }` as JSON. + +:::note[scrolls-api HTTP wrapper] +The Cloudflare Worker (`scrolls-api`) exposes `POST /{network}/sign` over HTTP, +but it wraps the older **v14** canister (`lmbwh-3qaaa-aaaak-qunha-cai`) and its +nonce-based address model. For v15 Scroll outputs, call the v15 canister +directly (as above) or let the prover fill addresses via `addresses`. +::: There is no per-caller access control: the canister signs for anyone, but only a transaction that carries a valid spell and pays the fee. Address-derivation integrity is protected by a canister-private secret prefix and the signed `addresses` attestation. + +## `scrolls_cardano` + +The `scrolls_cardano` canister co-signs Cardano spell transactions and issues +finality attestations used when [beaming](/explanation/beaming) out of Cardano. + +| | | +| --- | --- | +| Canister (IC mainnet) | `tty7k-waaaa-aaaak-qvngq-cai` | +| Networks | `"mainnet"`, `"preprod"` | + +The Charms prover calls `sign` automatically while proving Cardano spells. Wallets +and integrators rarely call this canister directly. + +### Candid interface + +```candid +type Config = record { + fee_address : vec record { text; text }; + fixed_cost : nat64; +}; + +service : () -> { + sign : (text) -> (variant { Ok : text; Err : text }); // tx hex in/out + certify_final : (text) -> (variant { Ok : text; Err : text }); + finality_vkey : () -> (variant { Ok : text; Err : text }); + vkey : () -> (variant { Ok : text; Err : text }); + config : () -> (Config) query; + cycles_balance : () -> (nat) query; + deposit_cycles : () -> (variant { Ok : nat; Err : text }); +} +``` + +| Method | Description | +| --- | --- | +| `sign(tx_to_sign)` | Co-sign a Cardano spell transaction (hex in, signed hex out). Called by the prover. | +| `certify_final(tx)` | Produce a finality-certified transaction. | +| `finality_vkey()` | Return the Ed25519 public key used for finality attestations (beaming). | +| `vkey()` | Return the canister's signing verification key. | +| `config()` | (query) Fee address and fixed cost. | +| `cycles_balance()` | (query) Cycles balance. | +| `deposit_cycles()` | Top up cycles (canister is designed to be blackholed). | diff --git a/src/content/docs/tutorials/cast-your-first-spell.md b/src/content/docs/tutorials/cast-your-first-spell.md index 6aa3c80..05875c1 100644 --- a/src/content/docs/tutorials/cast-your-first-spell.md +++ b/src/content/docs/tutorials/cast-your-first-spell.md @@ -48,13 +48,14 @@ address: ```sh export dest_0=$(charms util dest --addr $(b getnewaddress)) export amount_0=20000 # sats carried by the NFT output -change_address=$(b getrawchangeaddress) +export change_address=$(b getrawchangeaddress) ``` ## 3. Prove the spell Proving runs the app contract and generates the zero-knowledge proof. By default -the CLI sends the request to the hosted prover at `https://v15.charms.dev` — this +the CLI sends the request to the hosted prover at +`https://v15.charms.dev/spells/prove` — this takes a little while. ```sh From d1b7d397283290d706c6d37bf4dd9c12755e114c Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 15:12:12 -0700 Subject: [PATCH 08/16] Update Bitcoin Core requirement to v30 in node setup guide --- src/content/docs/how-to/set-up-a-bitcoin-node.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/content/docs/how-to/set-up-a-bitcoin-node.md b/src/content/docs/how-to/set-up-a-bitcoin-node.md index c8cfef6..5a85eab 100644 --- a/src/content/docs/how-to/set-up-a-bitcoin-node.md +++ b/src/content/docs/how-to/set-up-a-bitcoin-node.md @@ -8,8 +8,7 @@ To cast spells on Bitcoin you need a Bitcoin Core node. This guide sets one up o ## Bitcoin Core -Bitcoin Core **v28.0 or later** is required (`testnet4` was added in v28.0). A -recent release is recommended — spell transactions carry a larger `OP_RETURN` than +Bitcoin Core **v30.0 or later** is recommended (`testnet4` was added in v28.0). Spell transactions carry a larger `OP_RETURN` than the historical 80-byte standardness limit, and current Bitcoin Core versions relay them. Install with Homebrew: From 86fb204bf2edaee234f2fcdc43bb80798818c6c2 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Mon, 15 Jun 2026 15:19:19 -0700 Subject: [PATCH 09/16] Replace dfx CLI examples with icp CLI in Scrolls docs Update spend-scroll-outputs and scrolls-canister reference to use the recommended `icp canister call` syntax, verified against a live query to the v15 canister on IC mainnet. --- src/content/docs/how-to/spend-scroll-outputs.md | 7 ++++--- src/content/docs/reference/scrolls-canister.md | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/content/docs/how-to/spend-scroll-outputs.md b/src/content/docs/how-to/spend-scroll-outputs.md index e68f31e..f60a083 100644 --- a/src/content/docs/how-to/spend-scroll-outputs.md +++ b/src/content/docs/how-to/spend-scroll-outputs.md @@ -36,7 +36,7 @@ programmable custody enforced by Charms logic. sign, the prerequisite transactions, and the partially-signed transaction: ```sh - dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \ + icp canister call --network ic rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \ '("main", record { sign_inputs = vec { 0 : nat32 }; # indexes of the Scroll inputs prev_txs = vec { "0200000000…" }; # txs that created the spent outputs @@ -52,9 +52,10 @@ programmable custody enforced by Charms logic. `{ txid, wtxid }`. Re-broadcasting an already-confirmed transaction is idempotent. -## Calling without dfx +## Calling programmatically -Call the v15 canister with any Internet Computer agent (`ic-agent`/agent-rs). +Call the v15 canister with any Internet Computer agent (`ic-agent`/agent-rs) from +your application code instead of the [`icp` CLI](https://internetcomputer.org/docs/building-apps/developer-tools/icp-cli). The `scrolls-api` HTTP wrapper (`POST /{network}/sign`) targets the older **v14** canister and its nonce-based addresses — use it only for legacy v14 Scroll UTXOs, not for v15. diff --git a/src/content/docs/reference/scrolls-canister.md b/src/content/docs/reference/scrolls-canister.md index 45dafbf..c09c23e 100644 --- a/src/content/docs/reference/scrolls-canister.md +++ b/src/content/docs/reference/scrolls-canister.md @@ -80,7 +80,7 @@ Re-broadcasting an already-confirmed transaction is idempotent (it succeeds rather than erroring). ```sh -dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \ +icp canister call --network ic rpgc6-oqaaa-aaaak-qy3uq-cai sign_and_submit \ '("main", record { sign_inputs = vec { 0 : nat32 }; prev_txs = vec { "0200000000…" }; @@ -129,7 +129,8 @@ is provably pinned to programmable custody — see - **`ic-agent` / agent-rs (Rust)** — what the prover uses: build an `Agent` against `https://ic0.app`, `Encode!` the args, and `update`/`query` the canister, decoding the reply with `Decode!`. -- **`dfx`** — `dfx canister --network ic call rpgc6-oqaaa-aaaak-qy3uq-cai '()'`. +- **`icp` CLI** — `icp canister call --network ic rpgc6-oqaaa-aaaak-qy3uq-cai '()'`. + Add `--query` for query methods (e.g. `config`, `cycles_balance`). :::note[scrolls-api HTTP wrapper] The Cloudflare Worker (`scrolls-api`) exposes `POST /{network}/sign` over HTTP, From 94aebb80956d5ff6cf27123f0c38342c751a3132 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Tue, 16 Jun 2026 15:20:56 -0700 Subject: [PATCH 10/16] Simplify installation and server instructions for Charms CLI and prover --- src/content/docs/how-to/install-charms.md | 9 +++++---- src/content/docs/how-to/run-a-prover-server.md | 6 ++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/content/docs/how-to/install-charms.md b/src/content/docs/how-to/install-charms.md index d424c6d..86a2718 100644 --- a/src/content/docs/how-to/install-charms.md +++ b/src/content/docs/how-to/install-charms.md @@ -20,7 +20,7 @@ This guide installs the `charms` command-line tool. To run your own prover, see # or: apt-get install protobuf-compiler ``` -- The **WebAssembly target** used to build apps: +- The **WebAssembly target** to build Charms apps: ```sh rustup target add wasm32-wasip1 @@ -29,11 +29,12 @@ This guide installs the `charms` command-line tool. To run your own prover, see ## Install the CLI ```sh -## important to have this end with `/target` (a dependency issue) -export CARGO_TARGET_DIR=$(mktemp -d)/target -cargo install --locked charms +cargo install charms --locked ``` +If you want to run your own prover, see +[Run a prover server](/how-to/run-a-prover-server) instead (it builds the `charms-prover` binary). + ## Verify ```sh diff --git a/src/content/docs/how-to/run-a-prover-server.md b/src/content/docs/how-to/run-a-prover-server.md index 08ba113..01c9308 100644 --- a/src/content/docs/how-to/run-a-prover-server.md +++ b/src/content/docs/how-to/run-a-prover-server.md @@ -11,16 +11,14 @@ is the `charms-prover` binary: the same code as the `charms` CLI, built with the ## Build `charms-prover` ```sh -git clone https://github.com/CharmsDev/charms -cd charms -cargo install --path . --locked --bin charms-prover --features prover +cargo install charms --locked --bin charms-prover --features prover ``` ## Run the server ```sh charms-prover server # binds 0.0.0.0:17784 -charms-prover server --ip 127.0.0.1 --port 8080 +charms-prover server --ip 127.0.0.1 --port 17784 ``` It exposes `POST /spells/prove` and `GET /ready`. Check readiness: From 23b1abc427d4acbab9928b75b6f36f8772f09f48 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Thu, 18 Jun 2026 14:32:30 -0700 Subject: [PATCH 11/16] Rename Explanation section to Concepts and move it to top of nav Move content from explanation/ to concepts/, update sidebar links and internal references, and add redirects from old /explanation URLs. --- README.md | 6 +-- astro.config.mjs | 39 +++++++++++-------- .../docs/{explanation => concepts}/apps.md | 2 +- .../docs/{explanation => concepts}/beaming.md | 4 +- .../docs/{explanation => concepts}/index.md | 14 +++---- .../docs/{explanation => concepts}/scrolls.md | 4 +- .../docs/{explanation => concepts}/spells.md | 4 +- .../{explanation => concepts}/transactions.md | 6 +-- .../{explanation => concepts}/why-charms.md | 8 ++-- src/content/docs/how-to/beam-charms.md | 6 +-- .../docs/how-to/call-the-prover-api.md | 2 +- src/content/docs/how-to/index.md | 2 +- src/content/docs/how-to/manage-app-keys.md | 2 +- .../docs/how-to/run-a-prover-server.md | 2 +- .../docs/how-to/spend-scroll-outputs.md | 4 +- .../wallet-integration/transfer-nfts.md | 2 +- .../wallet-integration/transfer-tokens.md | 2 +- .../docs/how-to/write-an-app-contract.md | 4 +- src/content/docs/index.mdx | 6 +-- src/content/docs/reference/cli.md | 2 +- src/content/docs/reference/prover-api.md | 8 ++-- .../docs/reference/scrolls-canister.md | 6 +-- src/content/docs/reference/sdk.md | 2 +- src/content/docs/reference/spell.md | 18 ++++----- .../docs/tutorials/cast-your-first-spell.md | 4 +- src/content/docs/tutorials/index.md | 2 +- 26 files changed, 83 insertions(+), 78 deletions(-) rename src/content/docs/{explanation => concepts}/apps.md (98%) rename src/content/docs/{explanation => concepts}/beaming.md (96%) rename src/content/docs/{explanation => concepts}/index.md (57%) rename src/content/docs/{explanation => concepts}/scrolls.md (96%) rename src/content/docs/{explanation => concepts}/spells.md (97%) rename src/content/docs/{explanation => concepts}/transactions.md (94%) rename src/content/docs/{explanation => concepts}/why-charms.md (92%) diff --git a/README.md b/README.md index abcdd87..8dfbb99 100644 --- a/README.md +++ b/README.md @@ -16,9 +16,9 @@ distinct need: | Section | Directory | For | | --- | --- | --- | +| **Concepts** | `concepts/` | Understanding the ideas behind Charms. | | **Tutorials** | `tutorials/` | Learning by doing (start here). | | **How-to guides** | `how-to/` | Accomplishing specific tasks. | -| **Explanation** | `explanation/` | Understanding the concepts. | | **Reference** | `reference/` | Looking up exact formats and APIs. | The sidebar and redirects from old URLs are configured in `astro.config.mjs`. @@ -43,9 +43,9 @@ npm run dev # local dev server at http://localhost:4321 - Put each page in the section that matches its *purpose*, not its topic — a single topic (e.g. spells) legitimately appears across tutorials, how-to, - explanation, and reference. + concepts, and reference. - Keep the types distinct: tutorials don't dwell on options, how-to guides don't - explain theory, reference stays factual, explanation avoids step-by-step + explain theory, reference stays factual, concepts avoid step-by-step instructions. - Internal links are root-relative and omit the trailing slash (`/reference/spell`), matching `trailingSlash: 'never'`. diff --git a/astro.config.mjs b/astro.config.mjs index 6ee6e8b..bc3c7e0 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -8,9 +8,14 @@ export default defineConfig({ trailingSlash: 'never', // Redirects from the pre-Diátaxis URLs to their new homes. redirects: { - '/concepts/why': '/explanation/why-charms', - '/concepts/apps': '/explanation/apps', - '/concepts/spells': '/explanation/spells', + '/explanation': '/concepts', + '/explanation/why-charms': '/concepts/why-charms', + '/explanation/apps': '/concepts/apps', + '/explanation/spells': '/concepts/spells', + '/explanation/transactions': '/concepts/transactions', + '/explanation/beaming': '/concepts/beaming', + '/explanation/scrolls': '/concepts/scrolls', + '/concepts/why': '/concepts/why-charms', '/guides/charms-apps/introduction': '/tutorials', '/guides/charms-apps/pre-reqs': '/how-to/set-up-a-bitcoin-node', '/guides/charms-apps/get-started': '/tutorials/build-a-charms-app', @@ -61,9 +66,21 @@ export default defineConfig({ }, ], // The sidebar follows the Diátaxis framework (https://diataxis.fr): - // Tutorials (learning), How-to guides (tasks), Explanation - // (understanding), and Reference (information). + // Concepts (understanding), Tutorials (learning), How-to guides + // (tasks), and Reference (information). sidebar: [ + { + label: 'Concepts', + items: [ + { label: 'Overview', link: '/concepts' }, + { label: 'Why Charms?', link: '/concepts/why-charms' }, + { label: 'Apps', link: '/concepts/apps' }, + { label: 'Spells', link: '/concepts/spells' }, + { label: 'Transactions', link: '/concepts/transactions' }, + { label: 'Beaming', link: '/concepts/beaming' }, + { label: 'Scrolls', link: '/concepts/scrolls' }, + ], + }, { label: 'Tutorials', items: [ @@ -96,18 +113,6 @@ export default defineConfig({ }, ], }, - { - label: 'Explanation', - items: [ - { label: 'Overview', link: '/explanation' }, - { label: 'Why Charms?', link: '/explanation/why-charms' }, - { label: 'Apps', link: '/explanation/apps' }, - { label: 'Spells', link: '/explanation/spells' }, - { label: 'Transactions', link: '/explanation/transactions' }, - { label: 'Beaming', link: '/explanation/beaming' }, - { label: 'Scrolls', link: '/explanation/scrolls' }, - ], - }, { label: 'Reference', items: [ diff --git a/src/content/docs/explanation/apps.md b/src/content/docs/concepts/apps.md similarity index 98% rename from src/content/docs/explanation/apps.md rename to src/content/docs/concepts/apps.md index bfb60f6..9489a95 100644 --- a/src/content/docs/explanation/apps.md +++ b/src/content/docs/concepts/apps.md @@ -14,7 +14,7 @@ An app is identified by a triple `tag/identity/vk`: - **`tag`** — a single character describing the kind of app. Three tags have special meaning: `t` for fungible **tokens**, `n` for **NFTs**, and `s` for - [**Scrolls**](/explanation/scrolls). Any other character denotes a general + [**Scrolls**](/concepts/scrolls). Any other character denotes a general app whose logic is defined entirely by its contract. - **`identity`** — a 32-byte value identifying a particular asset *within* the app (for example, one NFT collection, or one token). diff --git a/src/content/docs/explanation/beaming.md b/src/content/docs/concepts/beaming.md similarity index 96% rename from src/content/docs/explanation/beaming.md rename to src/content/docs/concepts/beaming.md index 9a0b064..f741fbd 100644 --- a/src/content/docs/explanation/beaming.md +++ b/src/content/docs/concepts/beaming.md @@ -63,7 +63,7 @@ origin chain: roughly six blocks' worth of accumulated work. No third party is trusted; only Bitcoin's own proof-of-work. - **From Cardano** — a finality *attestation*: an Ed25519 signature from a - [Scrolls](/explanation/scrolls) canister certifying that the Cardano + [Scrolls](/concepts/scrolls) canister certifying that the Cardano transaction is settled. (Cardano has no compact proof-of-work analogue, so finality is attested by the Scrolls signer.) @@ -74,7 +74,7 @@ proof. ## Beaming and Scrolls -Beaming and [Scrolls](/explanation/scrolls) are distinct mechanisms that share a +Beaming and [Scrolls](/concepts/scrolls) are distinct mechanisms that share a trust anchor. Beaming moves charms between UTXOs and is verified by the commitment and finality proof above. Scrolls are the Internet Computer canisters that custody and sign Bitcoin/Cardano UTXOs and that attest Cardano finality. diff --git a/src/content/docs/explanation/index.md b/src/content/docs/concepts/index.md similarity index 57% rename from src/content/docs/explanation/index.md rename to src/content/docs/concepts/index.md index 5196acc..071b355 100644 --- a/src/content/docs/explanation/index.md +++ b/src/content/docs/concepts/index.md @@ -1,5 +1,5 @@ --- -title: Explanation +title: Concepts description: "Understand the ideas behind Charms: programmable assets on Bitcoin and beyond." sidebar: order: 0 @@ -10,15 +10,15 @@ for understanding rather than for getting a specific task done — if you are looking for steps to follow, see the [How-to guides](/how-to), and if you are looking up exact formats and APIs, see the [Reference](/reference). -- **[Why Charms?](/explanation/why-charms)** — the problem Charms solves and how +- **[Why Charms?](/concepts/why-charms)** — the problem Charms solves and how it compares to other Bitcoin token protocols. -- **[Apps](/explanation/apps)** — everything in Charms is an app; what an app +- **[Apps](/concepts/apps)** — everything in Charms is an app; what an app contract is and how it governs assets. -- **[Spells](/explanation/spells)** — the metadata that creates and transforms +- **[Spells](/concepts/spells)** — the metadata that creates and transforms charms, and what makes a spell *correct*. -- **[Transactions](/explanation/transactions)** — how spells and their proofs +- **[Transactions](/concepts/transactions)** — how spells and their proofs are embedded in Bitcoin and Cardano transactions. -- **[Beaming](/explanation/beaming)** — moving charms across chains without a +- **[Beaming](/concepts/beaming)** — moving charms across chains without a custodial bridge. -- **[Scrolls](/explanation/scrolls)** — Internet Computer canisters that act as +- **[Scrolls](/concepts/scrolls)** — Internet Computer canisters that act as programmable, keyless signers for Charms. diff --git a/src/content/docs/explanation/scrolls.md b/src/content/docs/concepts/scrolls.md similarity index 96% rename from src/content/docs/explanation/scrolls.md rename to src/content/docs/concepts/scrolls.md index 37d9e65..41c382c 100644 --- a/src/content/docs/explanation/scrolls.md +++ b/src/content/docs/concepts/scrolls.md @@ -54,14 +54,14 @@ enforces it. - **Vaults and programmable custody** — e.g. the eBTC vault, where BTC is locked at a Scrolls address and released only by a spell that mints/burns eBTC - one-to-one. See [Beaming](/explanation/beaming). + one-to-one. See [Beaming](/concepts/beaming). - **Automated signing and broadcasting** — a client can build a transaction, sign its own inputs, and hand the rest to the canister's [`sign_and_submit`](/reference/scrolls-canister#sign_and_submit) method, which signs the Scroll inputs, enforces the spell-and-fee policy, broadcasts the transaction, and returns its txid. - **Cross-chain finality attestation** — the Cardano Scrolls canister signs - certifications used as finality proofs when [beaming](/explanation/beaming) + certifications used as finality proofs when [beaming](/concepts/beaming) out of Cardano. ## The Bitcoin canister at a glance diff --git a/src/content/docs/explanation/spells.md b/src/content/docs/concepts/spells.md similarity index 97% rename from src/content/docs/explanation/spells.md rename to src/content/docs/concepts/spells.md index 1adeb38..d5d75df 100644 --- a/src/content/docs/explanation/spells.md +++ b/src/content/docs/concepts/spells.md @@ -77,7 +77,7 @@ app_public_inputs: In this example: - **`app_public_inputs`** is the map of all apps involved in the spell. Each key - is an app `tag/identity/vk` (see [Apps](/explanation/apps)), and each value is + is an app `tag/identity/vk` (see [Apps](/concepts/apps)), and each value is that app's public input data (empty here, as it is for simple transfers). - **`tx.ins`** lists the input UTXOs (`txid:vout`) the transaction spends. - **`tx.outs`** lists the output *strings of charms*. In each output, the keys @@ -110,4 +110,4 @@ is correct in milliseconds — without re-running any app code. This proof is produced by the [Prover API](/reference/prover-api). For *how* the proof and spell are attached to a real transaction, see -[Transactions](/explanation/transactions). +[Transactions](/concepts/transactions). diff --git a/src/content/docs/explanation/transactions.md b/src/content/docs/concepts/transactions.md similarity index 94% rename from src/content/docs/explanation/transactions.md rename to src/content/docs/concepts/transactions.md index c2f47a2..10cf0f2 100644 --- a/src/content/docs/explanation/transactions.md +++ b/src/content/docs/concepts/transactions.md @@ -6,7 +6,7 @@ sidebar: --- A spell never travels alone — it rides inside an ordinary blockchain -transaction, alongside a [proof](/explanation/spells#the-proof) of its +transaction, alongside a [proof](/concepts/spells#the-proof) of its correctness. This page explains, conceptually, how a spell becomes part of a real transaction on each supported chain. For the byte-level layout, see the [Spell structure reference](/reference/spell). @@ -74,7 +74,7 @@ mechanics differ in three ways: ledger requires a **collateral UTXO** — a normal ADA input that is forfeited only if script validation fails. You supply it when proving a Cardano spell (`charms spell prove --collateral-utxo …`). Cardano spell transactions are - also co-signed by a [Scrolls](/explanation/scrolls) canister. + also co-signed by a [Scrolls](/concepts/scrolls) canister. ## Prerequisite transactions @@ -82,5 +82,5 @@ Verifying a spell requires the transactions that produced its inputs — the **prerequisite transactions** (`prev_txs`). They let the verifier recover the charms being spent and confirm that each input's own spell was correct. When you prove or check a spell, you pass these transactions explicitly. In cross-chain -[beaming](/explanation/beaming), a prerequisite transaction also carries a +[beaming](/concepts/beaming), a prerequisite transaction also carries a *finality proof* showing it is irreversibly confirmed on its origin chain. diff --git a/src/content/docs/explanation/why-charms.md b/src/content/docs/concepts/why-charms.md similarity index 92% rename from src/content/docs/explanation/why-charms.md rename to src/content/docs/concepts/why-charms.md index 09dad65..fdc59b0 100644 --- a/src/content/docs/explanation/why-charms.md +++ b/src/content/docs/concepts/why-charms.md @@ -63,18 +63,18 @@ A *string of charms* is created or spent as one unit, just like a Bitcoin UTXO. *charmed*). Because of this, whoever owns a Bitcoin UTXO can do whatever they want with the *charms* in it (even destroy them). -To learn how apps define and govern charms, read [Apps](/explanation/apps). +To learn how apps define and govern charms, read [Apps](/concepts/apps). ## How are charms created -*Charms* come into existence by the magic of *[spells](/explanation/spells)* +*Charms* come into existence by the magic of *[spells](/concepts/spells)* added to blockchain transactions. ## Bitcoin and beyond Charms started on Bitcoin and the protocol is designed around Bitcoin's UTXO model. As of v15, the same charms can also live on **Cardano** (an eUTXO chain), -and they can move between chains through [beaming](/explanation/beaming) — a +and they can move between chains through [beaming](/concepts/beaming) — a trust-minimized teleport that needs no custodial bridge. ## Difference from Runes @@ -85,7 +85,7 @@ for Charms (among other things). Runes are tokens on top of Bitcoin, managed by *runestones* — metadata messages (in `OP_RETURN` outputs) directing the minting and transferring of *runes* (the Runes tokens). Runestones can be viewed as a kind of -[spells](/explanation/spells). +[spells](/concepts/spells). Runes lean towards [digital artifacts](https://docs.ordinals.com/digital-artifacts.html) and collectibles diff --git a/src/content/docs/how-to/beam-charms.md b/src/content/docs/how-to/beam-charms.md index 3bea776..e53db9d 100644 --- a/src/content/docs/how-to/beam-charms.md +++ b/src/content/docs/how-to/beam-charms.md @@ -3,11 +3,11 @@ title: Beam charms across chains description: "Move a charm from Bitcoin to Cardano (and back) using beaming, with eBTC as the example." --- -[Beaming](/explanation/beaming) moves a charm from one chain to another by +[Beaming](/concepts/beaming) moves a charm from one chain to another by destroying it at a source UTXO and re-creating it at a destination UTXO, tied together by a hash commitment and a finality proof. This guide walks the flow using [eBTC](https://github.com/CharmsDev/ebtc) — a token that can live on both -Bitcoin and Cardano. Read [Beaming](/explanation/beaming) first for the concepts. +Bitcoin and Cardano. Read [Beaming](/concepts/beaming) first for the concepts. A beam is always a **pair** of spells: a *send* on the source chain and a *receive* on the destination chain. @@ -80,7 +80,7 @@ The finality-proof form of `--prev-txs` depends on the **source** chain: (about six block headers of accumulated work). -- **Source = Cardano** → a [Scrolls](/explanation/scrolls) finality signature: +- **Source = Cardano** → a [Scrolls](/concepts/scrolls) finality signature: ``` --prev-txs="!cardano {tx: , signature: }" diff --git a/src/content/docs/how-to/call-the-prover-api.md b/src/content/docs/how-to/call-the-prover-api.md index d0aa796..666df4f 100644 --- a/src/content/docs/how-to/call-the-prover-api.md +++ b/src/content/docs/how-to/call-the-prover-api.md @@ -72,7 +72,7 @@ bitcoin-cli sendrawtransaction ## Tips - Include every app's binary in `binaries` (or use `--app-bins` from the CLI) for - anything beyond a [simple transfer](/explanation/apps#simple-transfers-need-no-contract). + anything beyond a [simple transfer](/concepts/apps#simple-transfers-need-no-contract). - Pass app witnesses in `app_private_inputs` (keyed by app `tag/identity/vk`). - For [versioned apps](/how-to/manage-app-keys), include `app_signatures`. - Ensure the funding UTXOs cover the outputs plus fees; pick a `fee_rate` diff --git a/src/content/docs/how-to/index.md b/src/content/docs/how-to/index.md index 6b623f2..92562ae 100644 --- a/src/content/docs/how-to/index.md +++ b/src/content/docs/how-to/index.md @@ -5,7 +5,7 @@ description: "Task-oriented recipes for working with Charms." Practical, goal-oriented recipes. Each guide assumes you already know the basics — if you're new, start with the [Tutorials](/tutorials); for the ideas -behind these tasks, see [Explanation](/explanation); for exact formats, see +behind these tasks, see [Concepts](/concepts); for exact formats, see [Reference](/reference). ### Set up diff --git a/src/content/docs/how-to/manage-app-keys.md b/src/content/docs/how-to/manage-app-keys.md index ae387a0..9e869f8 100644 --- a/src/content/docs/how-to/manage-app-keys.md +++ b/src/content/docs/how-to/manage-app-keys.md @@ -8,7 +8,7 @@ exact Wasm binary, so the code can never change. A **versioned app** instead pin its verification key to a *signing key*, letting you upgrade the binary over time by signing each new version. This guide covers the versioned-app workflow. For the trade-offs, see -[Apps](/explanation/apps#immutable-and-versioned-apps). +[Apps](/concepts/apps#immutable-and-versioned-apps). ## When to use a versioned app diff --git a/src/content/docs/how-to/run-a-prover-server.md b/src/content/docs/how-to/run-a-prover-server.md index 01c9308..6efb2d7 100644 --- a/src/content/docs/how-to/run-a-prover-server.md +++ b/src/content/docs/how-to/run-a-prover-server.md @@ -85,7 +85,7 @@ charms-prover server | `RUST_LOG` | Log level, e.g. `info`. | :::note -For Bitcoin spells with [Scroll](/explanation/scrolls) outputs, a prover *server* +For Bitcoin spells with [Scroll](/concepts/scrolls) outputs, a prover *server* is required (not mock mode): the server calls the Scrolls canister to fill in the Scroll output addresses while proving. ::: diff --git a/src/content/docs/how-to/spend-scroll-outputs.md b/src/content/docs/how-to/spend-scroll-outputs.md index f60a083..de27274 100644 --- a/src/content/docs/how-to/spend-scroll-outputs.md +++ b/src/content/docs/how-to/spend-scroll-outputs.md @@ -3,7 +3,7 @@ title: Spend Scroll outputs description: "Spend a Scrolls-controlled Bitcoin output with the canister's sign_and_submit method." --- -A Bitcoin output carrying a [Scroll](/explanation/scrolls) charm is locked to an +A Bitcoin output carrying a [Scroll](/concepts/scrolls) charm is locked to an address controlled by the `scrolls_bitcoin_v15` canister — no single private key can spend it. To spend it, you build the transaction, sign your *own* inputs, and ask the canister to sign its inputs and broadcast. This guide uses the canister's @@ -17,7 +17,7 @@ The canister will sign a Scroll input only if the transaction: 2. pays the configured Scrolls **protocol fee**. So you can't move Scroll-controlled funds arbitrarily — only via a transaction -whose spell is correct. That is the whole point of [Scrolls](/explanation/scrolls): +whose spell is correct. That is the whole point of [Scrolls](/concepts/scrolls): programmable custody enforced by Charms logic. ## Steps diff --git a/src/content/docs/how-to/wallet-integration/transfer-nfts.md b/src/content/docs/how-to/wallet-integration/transfer-nfts.md index 15a82da..cf2a70f 100644 --- a/src/content/docs/how-to/wallet-integration/transfer-nfts.md +++ b/src/content/docs/how-to/wallet-integration/transfer-nfts.md @@ -4,7 +4,7 @@ description: "Build a spell that sends an NFT charm to a new UTXO." --- Transferring an NFT sends the entire charm, unchanged, to a new output. This is a -[simple transfer](/explanation/apps#simple-transfers-need-no-contract), so it +[simple transfer](/concepts/apps#simple-transfers-need-no-contract), so it needs no app binary or contract proof — just asset preservation. ## The spell diff --git a/src/content/docs/how-to/wallet-integration/transfer-tokens.md b/src/content/docs/how-to/wallet-integration/transfer-tokens.md index f68d25a..5e5ce89 100644 --- a/src/content/docs/how-to/wallet-integration/transfer-tokens.md +++ b/src/content/docs/how-to/wallet-integration/transfer-tokens.md @@ -6,7 +6,7 @@ description: "Build a spell that sends fungible-token charms." A token transfer spends one or more outputs holding a token and creates destination outputs whose total token amount equals the input total. Like NFT transfers, this is a -[simple transfer](/explanation/apps#simple-transfers-need-no-contract) — no app +[simple transfer](/concepts/apps#simple-transfers-need-no-contract) — no app binary or contract proof required. ## The spell diff --git a/src/content/docs/how-to/write-an-app-contract.md b/src/content/docs/how-to/write-an-app-contract.md index 351857a..1c43cd2 100644 --- a/src/content/docs/how-to/write-an-app-contract.md +++ b/src/content/docs/how-to/write-an-app-contract.md @@ -5,7 +5,7 @@ description: "Implement the app_contract predicate that governs your charms." An app's logic is a single Rust function, the **app contract**. This guide shows how to implement one, starting from the generated template. For the concepts, see -[Apps](/explanation/apps); for the exact API, see the [SDK reference](/reference/sdk). +[Apps](/concepts/apps); for the exact API, see the [SDK reference](/reference/sdk). ## Scaffold a project @@ -105,7 +105,7 @@ fn can_mint_token(token_app: &App, tx: &Transaction) -> bool { is never published. The template requires `x` to be empty and uses `w` for the minting UTXO. - **Allow simple transfers cheaply.** Moving an NFT or tokens without minting is a - [simple transfer](/explanation/apps#simple-transfers-need-no-contract) and does + [simple transfer](/concepts/apps#simple-transfers-need-no-contract) and does not run your contract at all — only mint/burn/custom operations do. You can use `is_simple_transfer`, `token_amounts_balanced`, and `nft_state_preserved` from the SDK when you want to special-case them. diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index e508f7c..b5d1ce4 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -12,7 +12,7 @@ hero: link: /tutorials/build-a-charms-app icon: rocket - text: Why Charms? - link: /explanation/why-charms + link: /concepts/why-charms icon: right-arrow variant: minimal - text: Whitepaper @@ -66,9 +66,9 @@ These docs follow the [Diátaxis](https://diataxis.fr) framework. Task-focused recipes: prove, beam, integrate a wallet, and more. [Browse →](/how-to) - + Understand apps, spells, beaming, and Scrolls. - [Read →](/explanation) + [Read →](/concepts) The CLI, spell structure, SDK, Prover API, and Scrolls canister. diff --git a/src/content/docs/reference/cli.md b/src/content/docs/reference/cli.md index 109f048..f1f4f9b 100644 --- a/src/content/docs/reference/cli.md +++ b/src/content/docs/reference/cli.md @@ -105,7 +105,7 @@ charms spell check \ | --- | --- | | `--spell ` | Spell YAML/JSON. Default: `/dev/stdin`. | | `--private-inputs ` | YAML/JSON map of app → private input (`w`). | -| `--beamed-from ` | YAML/JSON map `input_index -> [source_utxo, nonce]` for [beamed](/explanation/beaming) inputs. | +| `--beamed-from ` | YAML/JSON map `input_index -> [source_utxo, nonce]` for [beamed](/concepts/beaming) inputs. | | `--app-bins ...` | App `.wasm` binaries (repeatable). | | `--app-signatures ` | YAML/JSON map `vk -> {public_key, signature}` for versioned apps. | | `--prev-txs ...` | Prerequisite transactions (repeatable). Plain hex, `!bitcoin …`/`!cardano …` tagged forms, or JSON `{"bitcoin":"…"}`. | diff --git a/src/content/docs/reference/prover-api.md b/src/content/docs/reference/prover-api.md index 5ff009b..64de985 100644 --- a/src/content/docs/reference/prover-api.md +++ b/src/content/docs/reference/prover-api.md @@ -6,7 +6,7 @@ sidebar: --- The Prover API turns a spell into a proven, ready-to-broadcast transaction. It -runs the app contracts, generates the [proof](/explanation/spells#the-proof), and +runs the app contracts, generates the [proof](/concepts/spells#the-proof), and builds the chain transaction(s). Use the hosted service or [run your own](/how-to/run-a-prover-server). @@ -47,9 +47,9 @@ readability.) | --- | --- | --- | | `spell` | object | The spell ([Spell structure](/reference/spell)). In JSON it may be the spell object or its hex-encoded CBOR. | | `app_private_inputs` | map | (Optional) app `tag/identity/vk` → private input (`w`). Omit when empty. | -| `tx_ins_beamed_source_utxos` | map | (Optional) input index → `[source_utxo, nonce]` for [beamed](/explanation/beaming) inputs. Omit when empty. | +| `tx_ins_beamed_source_utxos` | map | (Optional) input index → `[source_utxo, nonce]` for [beamed](/concepts/beaming) inputs. Omit when empty. | | `binaries` | map | (Optional) app `vk` (hex) → app `.wasm` bytes (base64 in JSON). Omit when empty. | -| `app_signatures` | map | (Optional) app `vk` (hex) → `{ public_key, signature }` for [versioned apps](/explanation/apps#immutable-and-versioned-apps). Omit when empty. | +| `app_signatures` | map | (Optional) app `vk` (hex) → `{ public_key, signature }` for [versioned apps](/concepts/apps#immutable-and-versioned-apps). Omit when empty. | | `prev_txs` | array | Prerequisite transactions, chain-tagged: `{"bitcoin":""}` / `{"cardano":""}` (and finality-proof forms for beaming). | | `change_address` | string | **Required.** Change address for the target chain. | | `fee_rate` | number | Bitcoin fee rate (sats/vB). Defaults to `0.0` if omitted (the CLI defaults to `2.0`). | @@ -106,7 +106,7 @@ broadcast it. See - Proving runs the app contracts, so include every app's binary in `binaries` (or `--app-bins`) for any operation beyond a simple transfer. -- For [Scroll](/explanation/scrolls) outputs on Bitcoin, the prover fills the +- For [Scroll](/concepts/scrolls) outputs on Bitcoin, the prover fills the `dest` script automatically by calling the Scrolls canister — only a prover *server* (not mock mode) can do this. - The `spell.tx.ins` and `spell.tx.coins` you send are used to build the diff --git a/src/content/docs/reference/scrolls-canister.md b/src/content/docs/reference/scrolls-canister.md index c09c23e..387a743 100644 --- a/src/content/docs/reference/scrolls-canister.md +++ b/src/content/docs/reference/scrolls-canister.md @@ -8,7 +8,7 @@ sidebar: ## `scrolls_bitcoin_v15` The `scrolls_bitcoin_v15` canister is the Bitcoin signer for Charms v15. It -derives the addresses that [Scroll](/explanation/scrolls) outputs are locked to, +derives the addresses that [Scroll](/concepts/scrolls) outputs are locked to, and it signs and broadcasts transactions that spend those outputs — but only when the transaction carries a valid Charms spell and pays the protocol fee. @@ -112,7 +112,7 @@ it yourself. The signature lets the spell proof verify, in-circuit, that these are genuinely the canister's addresses for the given transaction. This is how a Scroll output is provably pinned to programmable custody — see -[Scroll charms](/explanation/scrolls#scroll-charms). +[Scroll charms](/concepts/scrolls#scroll-charms). ## Other methods @@ -147,7 +147,7 @@ integrity is protected by a canister-private secret prefix and the signed ## `scrolls_cardano` The `scrolls_cardano` canister co-signs Cardano spell transactions and issues -finality attestations used when [beaming](/explanation/beaming) out of Cardano. +finality attestations used when [beaming](/concepts/beaming) out of Cardano. | | | | --- | --- | diff --git a/src/content/docs/reference/sdk.md b/src/content/docs/reference/sdk.md index f4f5826..cabd03f 100644 --- a/src/content/docs/reference/sdk.md +++ b/src/content/docs/reference/sdk.md @@ -40,7 +40,7 @@ tuple (CBOR) from stdin and asserts that `$path(&app, &tx, &x, &w)` returns ### `charms_sdk::app_version!($version)` -For [versioned apps](/explanation/apps#immutable-and-versioned-apps). Expands to +For [versioned apps](/concepts/apps#immutable-and-versioned-apps). Expands to `pub const VERSION: u32 = $version;` and exports an `__app_version()` function so the runtime can confirm the running binary matches the version pinned in the spell. Requires Rust edition 2024. diff --git a/src/content/docs/reference/spell.md b/src/content/docs/reference/spell.md index 17d1fb7..5e0c05c 100644 --- a/src/content/docs/reference/spell.md +++ b/src/content/docs/reference/spell.md @@ -14,8 +14,8 @@ authoritative reference for the spell's three faces: 3. the **on-chain transaction structure** that carries it, on Bitcoin and on Cardano. -For the concepts behind it, see [Spells](/explanation/spells) and -[Transactions](/explanation/transactions). +For the concepts behind it, see [Spells](/concepts/spells) and +[Transactions](/concepts/transactions). ## Logical structure @@ -54,7 +54,7 @@ app_public_inputs: | `version` | integer | Protocol version. Use `15` for the current prover. | | `tx` | object | The normalized transaction payload (below). | | `app_public_inputs` | map | All apps in the spell → each app's public input (`x`). | -| `versioned_apps` | map | (Optional) `vk -> { version, wasm_hash }` for [versioned apps](/explanation/apps#immutable-and-versioned-apps). Omit when empty. | +| `versioned_apps` | map | (Optional) `vk -> { version, wasm_hash }` for [versioned apps](/concepts/apps#immutable-and-versioned-apps). Omit when empty. | | `mock` | bool | (Optional) `true` only for mock-proving workflows. Omit otherwise. | :::note @@ -70,9 +70,9 @@ prover. | `ins` | list | Input UTXOs spent (`txid:vout`). Omitted in the serialized form (recovered from the hosting transaction). | | `refs` | list | (Optional) reference UTXOs — read, not spent. | | `outs` | list | Output *strings of charms*. Each entry maps an **app index** (`0`, `1`, …) to that app's charm data. | -| `beamed_outs` | map | (Optional) output index → `SHA-256` hash of the destination UTXO id, for [beaming](/explanation/beaming) out. | +| `beamed_outs` | map | (Optional) output index → `SHA-256` hash of the destination UTXO id, for [beaming](/concepts/beaming) out. | | `coins` | list | Native coin outputs (below). One per transaction output. | -| `scrolls` | list | (Optional) output indexes that carry [Scroll](/explanation/scrolls) charms and must be sent to Scrolls-controlled addresses. | +| `scrolls` | list | (Optional) output indexes that carry [Scroll](/concepts/scrolls) charms and must be sent to Scrolls-controlled addresses. | **App indexes.** In `outs` (and `scrolls`, `beamed_outs`), outputs reference apps by their **index** into `app_public_inputs`, taken in sorted key order: `0` is @@ -103,7 +103,7 @@ App keys are `tag/identity/vk`: - `n/…` — NFT app - `t/…` — fungible-token app -- `s/…` — [Scroll](/explanation/scrolls) app +- `s/…` — [Scroll](/concepts/scrolls) app - any other tag (e.g. `c/…`) — a general app whose logic is fully defined by its contract @@ -140,7 +140,7 @@ cbor( (NormalizedSpell, Proof) ) are both cleared (set to absent). On extraction, the input list is taken from the hosting transaction's inputs. - **`Proof`** is a byte string: the **Groth16** SNARK (BN254) attesting that the - spell is [correct](/explanation/spells#what-makes-a-spell-correct). It is + spell is [correct](/concepts/spells#what-makes-a-spell-correct). It is produced by an [SP1](https://docs.succinct.xyz/) zkVM pipeline — a `charms-spell-checker` proof wrapped into Groth16 — and is recursive, so it also covers every prerequisite transaction's spell. @@ -191,14 +191,14 @@ differently: UTXO** is required — pass it as `charms spell prove --collateral-utxo `. - **Co-signing.** Cardano spell transactions are signed by the Cardano - [Scrolls](/explanation/scrolls) canister as part of proving. + [Scrolls](/concepts/scrolls) canister as part of proving. The Prover API returns Cardano transactions tagged `{"cardano":""}` (a Ledger CDDL envelope). ## Beamed inputs -When a spell *receives* a [beamed](/explanation/beaming) charm, the source UTXO +When a spell *receives* a [beamed](/concepts/beaming) charm, the source UTXO on the other chain is supplied out of band (it is not a field of the spell itself): diff --git a/src/content/docs/tutorials/cast-your-first-spell.md b/src/content/docs/tutorials/cast-your-first-spell.md index 05875c1..e831a0b 100644 --- a/src/content/docs/tutorials/cast-your-first-spell.md +++ b/src/content/docs/tutorials/cast-your-first-spell.md @@ -100,6 +100,6 @@ You can also look the txid up on - Mint tokens against your NFT, or transfer charms — see the [How-to guides](/how-to). -- Understand what just happened: [Spells](/explanation/spells) and - [Transactions](/explanation/transactions). +- Understand what just happened: [Spells](/concepts/spells) and + [Transactions](/concepts/transactions). - Run proving yourself: [Run a prover server](/how-to/run-a-prover-server). diff --git a/src/content/docs/tutorials/index.md b/src/content/docs/tutorials/index.md index 7a47554..fd8dd07 100644 --- a/src/content/docs/tutorials/index.md +++ b/src/content/docs/tutorials/index.md @@ -6,7 +6,7 @@ description: "Learn Charms by building: from an empty directory to a charm on Bi New to Charms? These tutorials take you, step by step, from nothing to a real charm on Bitcoin. Follow them in order — each one builds on the last. You don't need to understand everything as you go; the goal is to *do* it and see it work. -Once you have, the [Explanation](/explanation) section fills in the why, and the +Once you have, the [Concepts](/concepts) section fills in the why, and the [Reference](/reference) section has the details. 1. **[Build a Charms app](/tutorials/build-a-charms-app)** — install the tools, From 3d7b0d0c892b9d3a8ddf96be2722c32c6ec1ffb8 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Thu, 18 Jun 2026 14:39:09 -0700 Subject: [PATCH 12/16] Clarify the goal of the Concepts overview page State that the section explains what the Charms protocol is and why it exists, and tighten the pointers to How-to and Reference. --- src/content/docs/concepts/index.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/content/docs/concepts/index.md b/src/content/docs/concepts/index.md index 071b355..bb376f4 100644 --- a/src/content/docs/concepts/index.md +++ b/src/content/docs/concepts/index.md @@ -1,14 +1,15 @@ --- title: Concepts -description: "Understand the ideas behind Charms: programmable assets on Bitcoin and beyond." +description: "What the Charms protocol is, why it exists, and how its core ideas fit together." sidebar: order: 0 --- -This section explains how Charms works and why it is built the way it is. It is -for understanding rather than for getting a specific task done — if you are -looking for steps to follow, see the [How-to guides](/how-to), and if you are -looking up exact formats and APIs, see the [Reference](/reference). +The goal of this section is to explain **what the Charms protocol is** and +**why it exists** — programmable assets on Bitcoin (and beyond), the problems +it was built to solve, and how the pieces fit together. + +If you want steps to follow to complete a task, see the [How-to guides](/how-to); if you need exact formats and APIs, see the [Reference](/reference). - **[Why Charms?](/concepts/why-charms)** — the problem Charms solves and how it compares to other Bitcoin token protocols. From 558943eaf4d2a215c3e5d40d1f2f00add226e92d Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Thu, 18 Jun 2026 14:57:03 -0700 Subject: [PATCH 13/16] Update the Concepts section --- src/content/docs/concepts/scrolls.md | 13 +++++++------ src/content/docs/concepts/transactions.md | 6 +++--- src/content/docs/concepts/why-charms.md | 18 ++++++++---------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/content/docs/concepts/scrolls.md b/src/content/docs/concepts/scrolls.md index 41c382c..bbe8175 100644 --- a/src/content/docs/concepts/scrolls.md +++ b/src/content/docs/concepts/scrolls.md @@ -26,8 +26,9 @@ transaction that created it. The decisive property is the canister's **signing policy**. It will sign a spend only if the spending transaction: -1. carries a **valid Charms spell**, and -2. pays the configured protocol **fee**. +1. carries a **valid Charms spell**, +2. pays the configured protocol **fee**, +3. only spends a Scrolls output **once** per unique Scrolls address. That is what makes the custody *programmable*: funds are released not by presenting a key, but by satisfying on-chain Charms logic — a verified @@ -37,16 +38,16 @@ controllers), so no human can override the policy. ## Scroll charms The charm tag `s` denotes a **Scroll**. A Bitcoin output carrying a Scroll charm -can only be created at a Scrolls-canister-controlled address. The link is +can only be created at a Scrolls canister controlled address. The link is enforced inside the proof: when a spell creates a Scroll output, the prover asks the canister for the controlling `scriptPubKey` (via its [`addresses`](/reference/scrolls-canister#addresses) method, signed by the canister), pins that address into the output, and the spell proof verifies the canister's signature. Later, spending that output requires the canister to -co-sign — which it does only for a valid spell. (On Cardano, a Scroll app behaves -like any other non-token app.) +co-sign — which it does only for a valid spell. On Cardano, a Scroll app behaves +like any other non-token app: Cardano itself enforces the Scroll's smart contract. -The result is an output that is provably locked to programmable custody: its +The result is an output provably locked to programmable custody: its fate is decided by Charms logic, with the Scrolls canister as the agent that enforces it. diff --git a/src/content/docs/concepts/transactions.md b/src/content/docs/concepts/transactions.md index 10cf0f2..e580b4c 100644 --- a/src/content/docs/concepts/transactions.md +++ b/src/content/docs/concepts/transactions.md @@ -76,11 +76,11 @@ mechanics differ in three ways: (`charms spell prove --collateral-utxo …`). Cardano spell transactions are also co-signed by a [Scrolls](/concepts/scrolls) canister. -## Prerequisite transactions +## Prerequisite (previous) transactions Verifying a spell requires the transactions that produced its inputs — the -**prerequisite transactions** (`prev_txs`). They let the verifier recover the +**previous transactions** (`prev_txs`). They let the verifier recover the charms being spent and confirm that each input's own spell was correct. When you prove or check a spell, you pass these transactions explicitly. In cross-chain -[beaming](/concepts/beaming), a prerequisite transaction also carries a +[beaming](/concepts/beaming), a previous transaction also carries a *finality proof* showing it is irreversibly confirmed on its origin chain. diff --git a/src/content/docs/concepts/why-charms.md b/src/content/docs/concepts/why-charms.md index fdc59b0..17308c8 100644 --- a/src/content/docs/concepts/why-charms.md +++ b/src/content/docs/concepts/why-charms.md @@ -5,17 +5,16 @@ sidebar: order: 1 --- -Charms is a **programmable assets** protocol and toolkit for Bitcoin (and, as of -v15, Cardano too), designed to be **developer-friendly**. +Charms is a **programmable assets** protocol and toolkit for Bitcoin (and, recently, Cardano too), designed to be **developer-friendly**. -Q: There are already several token standards out there, even on Bitcoin. Why +There are already several token standards for Bitcoin. Why create another one? In short, because none of them are **programmable**, or particularly -developer-friendly. And we are fixing this. +developer-friendly. We are fixing this. We believe in the magic of programmability. We also believe in the -decentralization and security of Bitcoin. An under-appreciated aspect of +decentralization and security of Bitcoin. An underappreciated aspect of Bitcoin's security is its UTXO model. It's widely believed that the UTXO model is "hard" to make programmable. But, with Charms, not impossible 😼 @@ -24,7 +23,7 @@ directly **on Bitcoin**. Because this is kind of magical, we call such tokens *charms*. -## What are charms +## What are Charms Put simply, _charms_ are programmable tokens on top of Bitcoin UTXOs. @@ -65,14 +64,14 @@ want with the *charms* in it (even destroy them). To learn how apps define and govern charms, read [Apps](/concepts/apps). -## How are charms created +## How are charms created? *Charms* come into existence by the magic of *[spells](/concepts/spells)* added to blockchain transactions. ## Bitcoin and beyond -Charms started on Bitcoin and the protocol is designed around Bitcoin's UTXO +Charms started on Bitcoin, and the protocol is designed around Bitcoin's UTXO model. As of v15, the same charms can also live on **Cardano** (an eUTXO chain), and they can move between chains through [beaming](/concepts/beaming) — a trust-minimized teleport that needs no custodial bridge. @@ -92,5 +91,4 @@ artifacts](https://docs.ordinals.com/digital-artifacts.html) and collectibles (with concepts like rarity of a name). Charms aim to address **programmability** and **composability**: you can have -multiple apps interacting with each other. Charms could (perhaps in a not too -distant future) even work with Runes. +multiple apps interacting with each other. Charms could even work with Runes. From 8ea02cbdbe5196f0e07221d3257148498385a245 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Thu, 18 Jun 2026 15:11:24 -0700 Subject: [PATCH 14/16] Update the Tutorials section --- src/content/docs/tutorials/build-a-charms-app.md | 3 +-- src/content/docs/tutorials/index.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/content/docs/tutorials/build-a-charms-app.md b/src/content/docs/tutorials/build-a-charms-app.md index 633b177..9050e64 100644 --- a/src/content/docs/tutorials/build-a-charms-app.md +++ b/src/content/docs/tutorials/build-a-charms-app.md @@ -16,8 +16,7 @@ Install the prerequisites and the CLI (details in rustup target add wasm32-wasip1 # WebAssembly target brew install protobuf # Protocol Buffers compiler (macOS) -export CARGO_TARGET_DIR=$(mktemp -d)/target # note: must end with /target -cargo install --locked charms +cargo install charms --locked ``` Check it works: diff --git a/src/content/docs/tutorials/index.md b/src/content/docs/tutorials/index.md index fd8dd07..ef4c959 100644 --- a/src/content/docs/tutorials/index.md +++ b/src/content/docs/tutorials/index.md @@ -6,7 +6,7 @@ description: "Learn Charms by building: from an empty directory to a charm on Bi New to Charms? These tutorials take you, step by step, from nothing to a real charm on Bitcoin. Follow them in order — each one builds on the last. You don't need to understand everything as you go; the goal is to *do* it and see it work. -Once you have, the [Concepts](/concepts) section fills in the why, and the +The [Concepts](/concepts) section fills in the what and the why, and the [Reference](/reference) section has the details. 1. **[Build a Charms app](/tutorials/build-a-charms-app)** — install the tools, From 60d50273d729adf870a0cefedea6d51c51556e79 Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Thu, 18 Jun 2026 15:36:36 -0700 Subject: [PATCH 15/16] Clarify `ProveRequest` field descriptions in prover API reference --- src/content/docs/reference/prover-api.md | 29 ++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/content/docs/reference/prover-api.md b/src/content/docs/reference/prover-api.md index 64de985..77c1eb2 100644 --- a/src/content/docs/reference/prover-api.md +++ b/src/content/docs/reference/prover-api.md @@ -41,20 +41,21 @@ readability.) ## Request -`POST /spells/prove` with this body: - -| Field | Type | Description | -| --- | --- | --- | -| `spell` | object | The spell ([Spell structure](/reference/spell)). In JSON it may be the spell object or its hex-encoded CBOR. | -| `app_private_inputs` | map | (Optional) app `tag/identity/vk` → private input (`w`). Omit when empty. | -| `tx_ins_beamed_source_utxos` | map | (Optional) input index → `[source_utxo, nonce]` for [beamed](/concepts/beaming) inputs. Omit when empty. | -| `binaries` | map | (Optional) app `vk` (hex) → app `.wasm` bytes (base64 in JSON). Omit when empty. | -| `app_signatures` | map | (Optional) app `vk` (hex) → `{ public_key, signature }` for [versioned apps](/concepts/apps#immutable-and-versioned-apps). Omit when empty. | -| `prev_txs` | array | Prerequisite transactions, chain-tagged: `{"bitcoin":""}` / `{"cardano":""}` (and finality-proof forms for beaming). | -| `change_address` | string | **Required.** Change address for the target chain. | -| `fee_rate` | number | Bitcoin fee rate (sats/vB). Defaults to `0.0` if omitted (the CLI defaults to `2.0`). | -| `chain` | string | `bitcoin` or `cardano`. | -| `collateral_utxo` | string | (Optional) `txid:vout` collateral. **Required for Cardano.** | +`POST /spells/prove` with a [`ProveRequest`](https://github.com/CharmsDev/charms/blob/main/charms-client/src/request.rs) +body: + +| Field | Type | Description | +| --- | --- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `spell` | object or string | **Required.** The spell ([Spell structure](/reference/spell), a `NormalizedSpell`). In JSON, the spell object's hex-encoded CBOR. | +| `app_private_inputs` | map | (Optional) App key `tag/identity_hex/vk_hex` → private input as hex-encoded CBOR. Omit when empty. | +| `tx_ins_beamed_source_utxos` | map | (Optional) Input index → `["txid:vout"]` or `["txid:vout", nonce]` for [beamed](/concepts/beaming) inputs (`nonce` is an optional `u64`). Omit when empty. | +| `binaries` | map | (Optional) App `vk` (64-char hex) → app `.wasm` bytes (base64 in JSON). Omit when empty. | +| `app_signatures` | map | (Optional) App `vk` (64-char hex) → `{ "public_key": "<64-char hex>", "signature": "<128-char hex>" }` for [versioned apps](/concepts/apps#immutable-and-versioned-apps). Omit when empty. | +| `prev_txs` | array | (Optional) Prerequisite transactions. Each entry is chain-tagged: `{"bitcoin":""}` or `{"cardano":""}`; for [beamed](/concepts/beaming) sources, use finality-proof forms — `{"bitcoin":{"tx":"","proof":"","headers":["",…]}}` or `{"cardano":{"tx":"","signature":""}}`. Omit when empty. | +| `change_address` | string | **Required.** Change address for the target chain. | +| `fee_rate` | number | (Optional) Bitcoin fee rate in sats/vB. Defaults to `0.0` if omitted (the CLI defaults to `2.0`). Ignored for Cardano. | +| `chain` | string | **Required.** `bitcoin` or `cardano`. | +| `collateral_utxo` | string | (Optional) Collateral UTXO as `txid:vout`. **Required for Cardano.** | ### Example From 0216fcfce1d44969fe9422abdbca07f455e3728e Mon Sep 17 00:00:00 2001 From: Ivan Mikushin Date: Thu, 18 Jun 2026 15:42:45 -0700 Subject: [PATCH 16/16] Align CLI reference with charms v15 command implementations Correct spell check output behavior, option formats, prove/prover flow, and wallet, tx, and util command details against the Rust CLI source. --- src/content/docs/reference/cli.md | 57 +++++++++++++++++++------------ 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/src/content/docs/reference/cli.md b/src/content/docs/reference/cli.md index f1f4f9b..6cafe67 100644 --- a/src/content/docs/reference/cli.md +++ b/src/content/docs/reference/cli.md @@ -21,7 +21,7 @@ Both expose the same subcommands; only `charms-prover` can generate real proofs locally. Install the CLI with: ```sh -cargo install --locked charms +cargo install charms --locked ``` See [Install Charms](/how-to/install-charms) for prerequisites and @@ -91,7 +91,9 @@ Verify that the signature(s) match the binary. `--sig` default ### `charms spell check` Validate a spell and run its app contracts **locally** (in WebAssembly, no -proof). Prints the resolved spell and the cycles each app used. +proof). On success, prints per-app cycle counts to **stderr** (for example +`cycles spent: [0, 42]`). May also print simple-transfer notices and warnings +about unbound Scrolls outputs (binding happens on the prover server). ```sh charms spell check \ @@ -104,13 +106,13 @@ charms spell check \ | Option | Description | | --- | --- | | `--spell ` | Spell YAML/JSON. Default: `/dev/stdin`. | -| `--private-inputs ` | YAML/JSON map of app → private input (`w`). | -| `--beamed-from ` | YAML/JSON map `input_index -> [source_utxo, nonce]` for [beamed](/concepts/beaming) inputs. | +| `--private-inputs ` | YAML/JSON map `tag/identity_hex/vk_hex` → app-specific private input data. | +| `--beamed-from ` | YAML/JSON map `input_index -> ["txid:vout"]` or `["txid:vout", nonce]` for [beamed](/concepts/beaming) inputs (`nonce` optional). | | `--app-bins ...` | App `.wasm` binaries (repeatable). | -| `--app-signatures ` | YAML/JSON map `vk -> {public_key, signature}` for versioned apps. | -| `--prev-txs ...` | Prerequisite transactions (repeatable). Plain hex, `!bitcoin …`/`!cardano …` tagged forms, or JSON `{"bitcoin":"…"}`. | +| `--app-signatures ` | YAML/JSON map `vk_hex -> {public_key, signature}` for versioned apps. | +| `--prev-txs ...` | Prerequisite transactions (repeatable, optional). Each value may be plain hex (auto-detected), YAML-tagged (`!bitcoin …` / `!cardano …`), JSON `{"bitcoin":"…"}` / `{"cardano":"…"}`, or a finality-proof object for [beamed](/concepts/beaming) sources. | | `--chain ` | `bitcoin` (default) or `cardano`. | -| `--mock` | Relax proof-related strictness (mock mode). | +| `--mock` | Accept mock proofs when resolving prerequisite spells. | ### `charms spell prove` @@ -120,20 +122,27 @@ Prove a spell and emit ready-to-broadcast transaction(s). Accepts every | Option | Description | | --- | --- | | `--change-address ` | **Required.** Change address for the target chain. | -| `--fee-rate ` | Bitcoin fee rate. Default `2.0` (must be ≥ `1.0`). | -| `--collateral-utxo ` | **Required for `--chain cardano`.** Collateral UTXO. | -| `--payload` | Print the [Prover API](/reference/prover-api) request instead of proving. | +| `--fee-rate ` | Bitcoin fee rate in sats/vB. Default `2.0` (must be ≥ `1.0`). Ignored for Cardano. | +| `--collateral-utxo ` | **Required for `--chain cardano`.** Collateral UTXO (alias: `--collateral`). | +| `--payload` | Print the [Prover API](/reference/prover-api) `ProveRequest` instead of proving. | | `-o, --output ` | Payload format (with `--payload`). Default `json`. | +| `--mock` | Prove locally in mock mode instead of calling the hosted API (requires a local prover for Bitcoin Scrolls spells). | On Bitcoin, prints a JSON array with the single unsigned spell transaction: -`[{"bitcoin":""}]`. On Cardano, prints a Ledger CDDL transaction envelope. -By default the `charms` binary forwards the proving request to the hosted -[Prover API](/reference/prover-api); build with `--features prover` (the -`charms-prover` binary) to prove locally. +`[{"bitcoin":""}]`. On Cardano, prints a Ledger CDDL JSON envelope: + +```json +{ "type": "Witnessed Tx ConwayEra", "description": "Ledger Cddl Format", "cborHex": "…" } +``` + +By default the `charms` binary forwards the proving request (CBOR) to the hosted +[Prover API](/reference/prover-api) (`CHARMS_PROVE_API_URL` overrides the URL). +Build with `--features prover` (the `charms-prover` binary) to prove locally. ### `charms spell vk` -Print the spell verification key as JSON (pass `--mock` for the mock key), e.g.: +Print the spell verification key as JSON. `prover` is `true` when built as +`charms-prover`. With `--mock`, adds `"mock": true` and uses the mock spell vk: ```json { "prover": false, "version": 15, "vk": "00425796f4c4fa050043eee14d801b4f935244e44aad6a28de0cd5cb3de0ae52" } @@ -147,8 +156,9 @@ Extract and verify the spell embedded in a transaction. charms tx show-spell --tx [--chain bitcoin|cardano] [--json] [--mock] ``` -Prints the spell as YAML (default) or JSON (`--json`). Returns nothing if the -transaction carries no valid spell. +Prints the spell as YAML (default) or JSON (`--json`). If the transaction +carries no valid spell, prints `No spell found in the transaction` to stderr. +`--chain` defaults to `bitcoin`. ## `charms wallet list` @@ -156,8 +166,10 @@ transaction carries no valid spell. charms wallet list [--json] [--mock] ``` -List the UTXOs in your local `bitcoin-cli` wallet that carry charms (Bitcoin -only). Shells out to `bitcoin-cli listunspent` and `getrawtransaction`. +List wallet UTXOs that carry charms (Bitcoin only). Shells out to +`bitcoin-cli listunspent 0` and `getrawtransaction`. Prints one YAML document +per match (with `---` separators) or pretty-printed JSON per match (`--json`). +Progress messages go to stderr. ## `charms util` @@ -170,9 +182,10 @@ charms util dest --addr
[--chain bitcoin|cardano] charms util dest --apps ... --chain cardano ``` -Exactly one of `--addr` (any address) or `--apps` (Cardano proxy-script address) -is required. The chain is auto-detected from the address when `--chain` is -omitted. +Exactly one of `--addr` (Bitcoin or Cardano address) or `--apps` (Cardano +proxy-script address from app ids) is required. When `--chain` is omitted, +`--addr` is auto-detected (Cardano first, then Bitcoin). `--apps` requires +Cardano and fails if `--chain bitcoin` is set. ### `charms util install-circuit-files`