From a4f71a2a130df08f5a0d6fec5f4042077fee3d6e Mon Sep 17 00:00:00 2001 From: Diego Carpenter Date: Tue, 14 Apr 2026 13:43:53 -0700 Subject: [PATCH 1/6] docs: The initial stub for vitepress tutorial page --- .github/workflows/build-docs.yml | 22 + .github/workflows/deploy.yml | 51 + .github/workflows/quick-lint.yml | 20 + .github/workflows/semantic-pr.yml | 18 + Makefile | 31 + cfg/lychee.toml | 17 + docs/.gitignore | 3 + docs/.vitepress/config.js | 110 + docs/.vitepress/theme/index.js | 2 + docs/package-lock.json | 2535 ++++++++++++++++++++ docs/package.json | 16 + docs/src/architecture/accounts.md | 77 + docs/src/architecture/overview.md | 96 + docs/src/architecture/program-structure.md | 105 + docs/src/index.md | 25 + docs/src/introduction/core-concepts.md | 61 + docs/src/introduction/what-is-dropset.md | 31 + docs/src/public/CNAME | 1 + docs/src/quickstart/getting-started.md | 99 + docs/src/sdk/overview.md | 84 + docs/src/services/overview.md | 33 + dropset-alpha | 1 + 22 files changed, 3438 insertions(+) create mode 100644 .github/workflows/build-docs.yml create mode 100644 .github/workflows/deploy.yml create mode 100644 .github/workflows/quick-lint.yml create mode 100644 .github/workflows/semantic-pr.yml create mode 100644 Makefile create mode 100644 cfg/lychee.toml create mode 100644 docs/.gitignore create mode 100644 docs/.vitepress/config.js create mode 100644 docs/.vitepress/theme/index.js create mode 100644 docs/package-lock.json create mode 100644 docs/package.json create mode 100644 docs/src/architecture/accounts.md create mode 100644 docs/src/architecture/overview.md create mode 100644 docs/src/architecture/program-structure.md create mode 100644 docs/src/index.md create mode 100644 docs/src/introduction/core-concepts.md create mode 100644 docs/src/introduction/what-is-dropset.md create mode 100644 docs/src/public/CNAME create mode 100644 docs/src/quickstart/getting-started.md create mode 100644 docs/src/sdk/overview.md create mode 100644 docs/src/services/overview.md create mode 160000 dropset-alpha diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 00000000..56407658 --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,22 @@ +--- +jobs: + build-docs: + name: 'Build docs' + runs-on: 'ubuntu-latest' + steps: + - uses: 'actions/checkout@v6' + - uses: 'actions/setup-node@v6' + with: + cache: 'npm' + cache-dependency-path: 'docs/package-lock.json' + node-version: 24 + - run: 'npm ci' + working-directory: 'docs' + - run: 'npm run format:check' + working-directory: 'docs' + - run: 'npm run build' + working-directory: 'docs' +name: 'Build docs' +'on': + pull_request: null +... diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 00000000..e677fbe4 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,51 @@ +# From https://vitepress.dev/guide/deploy#github-pages. +concurrency: + cancel-in-progress: false + group: 'pages' +jobs: + build: + runs-on: 'ubuntu-latest' + steps: + - name: 'Checkout' + uses: 'actions/checkout@v5' + with: + fetch-depth: null + - name: 'Setup Node' + uses: 'actions/setup-node@v6' + with: + cache: 'npm' + cache-dependency-path: 'docs/package-lock.json' + node-version: 24 + - name: 'Setup Pages' + uses: 'actions/configure-pages@v4' + - name: 'Install dependencies' + run: 'npm ci' + working-directory: 'docs' + - name: 'Build with VitePress' + run: 'npm run build' + working-directory: 'docs' + - name: 'Upload artifact' + uses: 'actions/upload-pages-artifact@v3' + with: + path: 'docs/.vitepress/dist' + deploy: + environment: + name: 'github-pages' + url: '${{ steps.deployment.outputs.page_url }}' + name: 'Deploy' + needs: 'build' + runs-on: 'ubuntu-latest' + steps: + - id: 'deployment' + name: 'Deploy to GitHub Pages' + uses: 'actions/deploy-pages@v4' +name: 'Deploy VitePress site to GitHub Pages' +'on': + push: + branches: + - 'main' +permissions: + contents: 'read' + id-token: 'write' + pages: 'write' +... diff --git a/.github/workflows/quick-lint.yml b/.github/workflows/quick-lint.yml new file mode 100644 index 00000000..61552187 --- /dev/null +++ b/.github/workflows/quick-lint.yml @@ -0,0 +1,20 @@ +--- +jobs: + quick-lint: + name: 'Quick lint' + runs-on: 'ubuntu-latest' + steps: + - uses: 'actions/checkout@v6' + - uses: 'actions/setup-node@v6' + with: + cache: 'npm' + cache-dependency-path: 'docs/package-lock.json' + node-version: 24 + - run: 'npm ci' + working-directory: 'docs' + - run: 'npm run format:check' + working-directory: 'docs' +name: 'Quick lint' +'on': + pull_request: null +... diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml new file mode 100644 index 00000000..9aad0c25 --- /dev/null +++ b/.github/workflows/semantic-pr.yml @@ -0,0 +1,18 @@ +--- +jobs: + semantic-pr: + name: 'Validate PR title' + runs-on: 'ubuntu-latest' + steps: + - name: 'Validate semantic PR title' + uses: 'amannn/action-semantic-pull-request@v5' + env: + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}' +name: 'Semantic PR' +'on': + pull_request_target: + types: + - 'edited' + - 'opened' + - 'synchronize' +... diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..9fb294ab --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +.PHONY: docs +.PHONY: docs-build +.PHONY: docs-links +.PHONY: docs-prettier +.PHONY: docs-prod + +# Build the docs locally for development +docs: + cd docs && npm install \ + && rm -rf .vitepress/cache .vitepress/dist node_modules/.vite \ + && npx vitepress dev --open + +# Build the docs for production +docs-build: + cd docs \ + && rm -rf .vitepress/cache .vitepress/dist node_modules/.vite \ + && npm ci \ + && npx vitepress build + +# Check for any broken links +docs-links: docs-build + lychee --config cfg/lychee.toml --include-fragments \ + --root-dir docs/.vitepress/dist 'docs/.vitepress/dist/**/*.html' + +# Format docs with Prettier +docs-prettier: + cd docs && npm install && npx prettier --write . + +# Serve docs in production mode +docs-prod: docs-build + cd docs && (sleep 1 && open http://localhost:4173 &) && npx vitepress preview diff --git a/cfg/lychee.toml b/cfg/lychee.toml new file mode 100644 index 00000000..5d14f850 --- /dev/null +++ b/cfg/lychee.toml @@ -0,0 +1,17 @@ +# Lychee link checker configuration. +# Run via: make docs-links + +# Ignore localhost links (used in examples). +exclude = [ + "http://localhost", + "https://localhost", +] + +# Don't fail on these status codes (some sites block bots). +accept = [200, 206, 429] + +# Timeout per request in seconds. +timeout = 20 + +# Max retries per link. +max_retries = 3 diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 00000000..55065682 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,3 @@ +node_modules +.vitepress/cache +.vitepress/dist diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js new file mode 100644 index 00000000..581995ef --- /dev/null +++ b/docs/.vitepress/config.js @@ -0,0 +1,110 @@ +export default { + title: "Dropset", + description: + "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", + head: [ + [ + "link", + { + rel: "icon", + href: "/favicon-light.png", + media: "(prefers-color-scheme: light)", + }, + ], + [ + "link", + { + rel: "icon", + href: "/favicon-dark.png", + media: "(prefers-color-scheme: dark)", + }, + ], + ["link", { rel: "apple-touch-icon", href: "/favicon-light.png" }], + ["meta", { property: "og:site_name", content: "DASMAC" }], + ["meta", { property: "og:type", content: "website" }], + ["meta", { property: "og:url", content: "https://docs.dropset.io/" }], + ["meta", { property: "og:title", content: "Dropset Docs" }], + [ + "meta", + { + property: "og:description", + content: + "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", + }, + ], + [ + "meta", + { + property: "og:image", + content: "https://docs.dropset.io/dasmac-banner.png", + }, + ], + ["meta", { name: "twitter:card", content: "summary_large_image" }], + ["meta", { name: "twitter:title", content: "Dropset Docs" }], + [ + "meta", + { + name: "twitter:description", + content: + "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", + }, + ], + [ + "meta", + { + name: "twitter:image", + content: "https://docs.dropset.io/dasmac-banner.png", + }, + ], + ], + srcDir: "src", + themeConfig: { + outline: "deep", + editLink: { + pattern: + "https://github.com/DASMAC-com/dropset-alpha/blob/main/docs/src/:path", + text: "Contribute to this page", + }, + sidebar: [ + { text: "Welcome", link: "/" }, + { + collapsed: false, + text: "Introduction", + items: [ + { text: "What is Dropset?", link: "/introduction/what-is-dropset" }, + { text: "Core Concepts", link: "/introduction/core-concepts" }, + ], + }, + { + collapsed: false, + text: "Architecture", + items: [ + { text: "Overview", link: "/architecture/overview" }, + { text: "Program Structure", link: "/architecture/program-structure" }, + { text: "On-Chain Accounts", link: "/architecture/accounts" }, + ], + }, + { + collapsed: false, + text: "Quickstart", + items: [ + { text: "Getting Started", link: "/quickstart/getting-started" }, + ], + }, + { + collapsed: false, + text: "TypeScript SDK", + items: [ + { text: "Overview", link: "/sdk/overview" }, + ], + }, + { + collapsed: false, + text: "Services", + items: [ + { text: "Faucet, Maker & Taker", link: "/services/overview" }, + ], + }, + ], + }, +}; diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js new file mode 100644 index 00000000..6b573792 --- /dev/null +++ b/docs/.vitepress/theme/index.js @@ -0,0 +1,2 @@ +import DefaultTheme from 'vitepress/theme'; +export default DefaultTheme; diff --git a/docs/package-lock.json b/docs/package-lock.json new file mode 100644 index 00000000..601d1057 --- /dev/null +++ b/docs/package-lock.json @@ -0,0 +1,2535 @@ +{ + "name": "dropset-docs", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "dropset-docs", + "version": "0.0.1", + "devDependencies": { + "prettier": "^3.4.2", + "vitepress": "^1.6.3" + } + }, + "node_modules/@algolia/abtesting": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.2.tgz", + "integrity": "sha512-n9s6bEV6imdtIEd+BGP7WkA4pEZ5YTdgQ05JQhHwWawHg3hyjpNwC0TShGz6zWhv+jfLDGA/6FFNbySFS0P9cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/autocomplete-core": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz", + "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-plugin-algolia-insights": "1.17.7", + "@algolia/autocomplete-shared": "1.17.7" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz", + "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" + } + }, + "node_modules/@algolia/autocomplete-preset-algolia": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz", + "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-shared": "1.17.7" + }, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/autocomplete-shared": { + "version": "1.17.7", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz", + "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } + }, + "node_modules/@algolia/client-abtesting": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.50.2.tgz", + "integrity": "sha512-52iq0vHy1sphgnwoZyx5PmbEt8hsh+m7jD123LmBs6qy4GK7LbYZIeKd+nSnSipN2zvKRZ2zScS6h9PW3J7SXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-analytics": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.50.2.tgz", + "integrity": "sha512-WpPIUg+cSG2aPUG0gS8Ko9DwRgbRPUZxJkolhL2aCsmSlcEEZT65dILrfg5ovcxtx0Kvr+xtBVsTMtsQWRtPDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-common": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.50.2.tgz", + "integrity": "sha512-Gj2MgtArGcsr82kIqRlo6/dCAFjrs2gLByEqyRENuT7ugrSMFuqg1vDzeBjRL1t3EJEJCFtT0PLX3gB8A6Hq4Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-insights": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.50.2.tgz", + "integrity": "sha512-CUqoid5jDpmrc0oK3/xuZXFt6kwT0P9Lw7/nsM14YTr6puvmi+OUKmURpmebQF22S2vCG8L1DAoXXujxQUi/ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-personalization": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.50.2.tgz", + "integrity": "sha512-AndZWFoc0gbP5901OeQJ73BazgGgSGiBEba4ohdoJuZwHTO2Gio8Q4L1VLmytMBYcviVigB0iICToMvEJxI4ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-query-suggestions": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.2.tgz", + "integrity": "sha512-NWoL+psEkz5dIzweaByVXuEB45wS8/rk0E0AhMMnaVJdVs7TcACPH2/OURm+N0xRDITkTHqCna823rd6Uqntdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/client-search": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.50.2.tgz", + "integrity": "sha512-ypSboUJ3XJoQz5DeDo82hCnrRuwq3q9ZdFhVKAik9TnZh1DvLqoQsrbBjXg7C7zQOtV/Qbge/HmyoV6V5L7MhQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/ingestion": { + "version": "1.50.2", + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.50.2.tgz", + "integrity": "sha512-VlR2FRXLw2bCB94SQo6zxg/Qi+547aOji6Pb+dKE7h1DMCCY317St+OpjpmgzE+bT2O9ALIc0V4nVIBOd7Gy+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/monitoring": { + "version": "1.50.2", + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.50.2.tgz", + "integrity": "sha512-Cmvfp2+qopzQt8OilU97rhLhosq7ZrB6uieok3EwFUqG/aalPg6DgfCmu0yJMrYe+KMC1qRVt1MTRAUwLknUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/recommend": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.50.2.tgz", + "integrity": "sha512-jrkuyKoOM7dFWQ/6Y4hQAse2SC3L/RldG6GnPjMvAj65h+7Ubb51S0pKk4ofSStF0xm4LCNe0C4T6XX4nOFDiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-browser-xhr": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.2.tgz", + "integrity": "sha512-4107YLJqCudPiBUlwnk6oTSUVwU7ab+qL1SfQGEDYI8DZH5gsf1ekPt9JykXRKYXf2IfouFL5GiCY/PHTFIjYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-fetch": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.50.2.tgz", + "integrity": "sha512-vOrd3MQpLgmf6wXAueTuZ/cA0W4uRwIHHaxNy3h+a6YcNn6bCV/gFdZuv3F13v593zRU2k5R75NmvRWLenvMrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@algolia/requester-node-http": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.50.2.tgz", + "integrity": "sha512-Mu9BFtgzGqDUy5Bcs2nMyoILIFSN13GKQaklKAFIsd0K3/9CpNyfeBc+/+Qs6mFZLlxG9qzullO7h+bjcTBuGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/client-common": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@docsearch/css": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz", + "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@docsearch/js": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz", + "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/react": "3.8.2", + "preact": "^10.0.0" + } + }, + "node_modules/@docsearch/react": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz", + "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@algolia/autocomplete-core": "1.17.7", + "@algolia/autocomplete-preset-algolia": "1.17.7", + "@docsearch/css": "3.8.2", + "algoliasearch": "^5.14.2" + }, + "peerDependencies": { + "@types/react": ">= 16.8.0 < 19.0.0", + "react": ">= 16.8.0 < 19.0.0", + "react-dom": ">= 16.8.0 < 19.0.0", + "search-insights": ">= 1 < 3" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "search-insights": { + "optional": true + } + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@iconify-json/simple-icons": { + "version": "1.2.78", + "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.78.tgz", + "integrity": "sha512-I3lkNp0Qu7q2iZWkdcf/I2hqGhzK6qxdILh9T7XqowQrnpmG/BayDsiCf6PktDoWlW0U971xA5g+panm+NFrfQ==", + "dev": true, + "license": "CC0-1.0", + "dependencies": { + "@iconify/types": "*" + } + }, + "node_modules/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz", + "integrity": "sha512-d6FinEBLdIiK+1uACUttJKfgZREXrF0Qc2SmLII7W2AD8FfiZ9Wjd+rD/iRuf5s5dWrr1GgwXCvPqOuDquOowA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.1.tgz", + "integrity": "sha512-YjG/EwIDvvYI1YvYbHvDz/BYHtkY4ygUIXHnTdLhG+hKIQFBiosfWiACWortsKPKU/+dUwQQCKQM3qrDe8c9BA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.1.tgz", + "integrity": "sha512-mjCpF7GmkRtSJwon+Rq1N8+pI+8l7w5g9Z3vWj4T7abguC4Czwi3Yu/pFaLvA3TTeMVjnu3ctigusqWUfjZzvw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.1.tgz", + "integrity": "sha512-haZ7hJ1JT4e9hqkoT9R/19XW2QKqjfJVv+i5AGg57S+nLk9lQnJ1F/eZloRO3o9Scy9CM3wQ9l+dkXtcBgN5Ew==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.1.tgz", + "integrity": "sha512-czw90wpQq3ZsAVBlinZjAYTKduOjTywlG7fEeWKUA7oCmpA8xdTkxZZlwNJKWqILlq0wehoZcJYfBvOyhPTQ6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.1.tgz", + "integrity": "sha512-KVB2rqsxTHuBtfOeySEyzEOB7ltlB/ux38iu2rBQzkjbwRVlkhAGIEDiiYnO2kFOkJp+Z7pUXKyrRRFuFUKt+g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.1.tgz", + "integrity": "sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.1.tgz", + "integrity": "sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.1.tgz", + "integrity": "sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.1.tgz", + "integrity": "sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.1.tgz", + "integrity": "sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.1.tgz", + "integrity": "sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.1.tgz", + "integrity": "sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.1.tgz", + "integrity": "sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.1.tgz", + "integrity": "sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.1.tgz", + "integrity": "sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.1.tgz", + "integrity": "sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.1.tgz", + "integrity": "sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.1.tgz", + "integrity": "sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.1.tgz", + "integrity": "sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.1.tgz", + "integrity": "sha512-4Cv23ZrONRbNtbZa37mLSueXUCtN7MXccChtKpUnQNgF010rjrjfHx3QxkS2PI7LqGT5xXyYs1a7LbzAwT0iCA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.1.tgz", + "integrity": "sha512-i1okWYkA4FJICtr7KpYzFpRTHgy5jdDbZiWfvny21iIKky5YExiDXP+zbXzm3dUcFpkEeYNHgQ5fuG236JPq0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.1.tgz", + "integrity": "sha512-u09m3CuwLzShA0EYKMNiFgcjjzwqtUMLmuCJLeZWjjOYA3IT2Di09KaxGBTP9xVztWyIWjVdsB2E9goMjZvTQg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.1.tgz", + "integrity": "sha512-k+600V9Zl1CM7eZxJgMyTUzmrmhB/0XZnF4pRypKAlAgxmedUA+1v9R+XOFv56W4SlHEzfeMtzujLJD22Uz5zg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz", + "integrity": "sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz", + "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.4" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz", + "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^3.1.0" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz", + "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz", + "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz", + "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/transformers": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz", + "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/types": "2.5.0" + } + }, + "node_modules/@shikijs/types": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz", + "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/@shikijs/vscode-textmate": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", + "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", + "dev": true, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/markdown-it": { + "version": "14.1.2", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", + "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "dev": true, + "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==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz", + "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.32.tgz", + "integrity": "sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/shared": "3.5.32", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.32.tgz", + "integrity": "sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.32.tgz", + "integrity": "sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@vue/compiler-core": "3.5.32", + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.8", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.32.tgz", + "integrity": "sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.32.tgz", + "integrity": "sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.32.tgz", + "integrity": "sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/shared": "3.5.32" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.32.tgz", + "integrity": "sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.32", + "@vue/runtime-core": "3.5.32", + "@vue/shared": "3.5.32", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.32.tgz", + "integrity": "sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "vue": "3.5.32" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.32.tgz", + "integrity": "sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vueuse/core": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz", + "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/integrations": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz", + "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vueuse/core": "12.8.2", + "@vueuse/shared": "12.8.2", + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "^4", + "axios": "^1", + "change-case": "^5", + "drauu": "^0.4", + "focus-trap": "^7", + "fuse.js": "^7", + "idb-keyval": "^6", + "jwt-decode": "^4", + "nprogress": "^0.2", + "qrcode": "^1.5", + "sortablejs": "^1", + "universal-cookie": "^7" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz", + "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "12.8.2", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz", + "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "vue": "^3.5.13" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/algoliasearch": { + "version": "5.50.2", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.2.tgz", + "integrity": "sha512-Tfp26yoNWurUjfgK4GOrVJQhSNXu9tJtHfFFNosgT2YClG+vPyUjX/gbC8rG39qLncnZg8Fj34iarQWpMkqefw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@algolia/abtesting": "1.16.2", + "@algolia/client-abtesting": "5.50.2", + "@algolia/client-analytics": "5.50.2", + "@algolia/client-common": "5.50.2", + "@algolia/client-insights": "5.50.2", + "@algolia/client-personalization": "5.50.2", + "@algolia/client-query-suggestions": "5.50.2", + "@algolia/client-search": "5.50.2", + "@algolia/ingestion": "1.50.2", + "@algolia/monitoring": "1.50.2", + "@algolia/recommend": "5.50.2", + "@algolia/requester-browser-xhr": "5.50.2", + "@algolia/requester-fetch": "5.50.2", + "@algolia/requester-node-http": "5.50.2" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/comma-separated-tokens": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/emoji-regex-xs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz", + "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/focus-trap": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.8.0.tgz", + "integrity": "sha512-/yNdlIkpWbM0ptxno3ONTuf+2g318kh2ez3KSeZN5dZ8YC6AAmgeWz+GasYYiBJPFaYcSAPeu4GfhUaChzIJXA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "tabbable": "^6.4.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/hast-util-to-html": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", + "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-whitespace": "^3.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-whitespace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", + "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mark.js": { + "version": "8.11.1", + "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz", + "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.1", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz", + "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@ungap/structured-clone": "^1.0.0", + "devlop": "^1.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "trim-lines": "^3.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/minisearch": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz", + "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==", + "dev": true, + "license": "MIT" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "dev": true, + "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==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/oniguruma-to-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz", + "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex-xs": "^1.0.0", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/postcss": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/preact": { + "version": "10.29.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", + "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prettier": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz", + "integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/property-information": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", + "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.1.0.tgz", + "integrity": "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-recursion": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", + "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "regex-utilities": "^2.3.0" + } + }, + "node_modules/regex-utilities": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", + "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", + "dev": true, + "license": "MIT" + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.60.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.1.tgz", + "integrity": "sha512-VmtB2rFU/GroZ4oL8+ZqXgSA38O6GR8KSIvWmEFv63pQ0G6KaBH9s07PO8XTXP4vI+3UJUEypOfjkGfmSBBR0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.1", + "@rollup/rollup-android-arm64": "4.60.1", + "@rollup/rollup-darwin-arm64": "4.60.1", + "@rollup/rollup-darwin-x64": "4.60.1", + "@rollup/rollup-freebsd-arm64": "4.60.1", + "@rollup/rollup-freebsd-x64": "4.60.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.1", + "@rollup/rollup-linux-arm-musleabihf": "4.60.1", + "@rollup/rollup-linux-arm64-gnu": "4.60.1", + "@rollup/rollup-linux-arm64-musl": "4.60.1", + "@rollup/rollup-linux-loong64-gnu": "4.60.1", + "@rollup/rollup-linux-loong64-musl": "4.60.1", + "@rollup/rollup-linux-ppc64-gnu": "4.60.1", + "@rollup/rollup-linux-ppc64-musl": "4.60.1", + "@rollup/rollup-linux-riscv64-gnu": "4.60.1", + "@rollup/rollup-linux-riscv64-musl": "4.60.1", + "@rollup/rollup-linux-s390x-gnu": "4.60.1", + "@rollup/rollup-linux-x64-gnu": "4.60.1", + "@rollup/rollup-linux-x64-musl": "4.60.1", + "@rollup/rollup-openbsd-x64": "4.60.1", + "@rollup/rollup-openharmony-arm64": "4.60.1", + "@rollup/rollup-win32-arm64-msvc": "4.60.1", + "@rollup/rollup-win32-ia32-msvc": "4.60.1", + "@rollup/rollup-win32-x64-gnu": "4.60.1", + "@rollup/rollup-win32-x64-msvc": "4.60.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/search-insights": { + "version": "2.17.3", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz", + "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/shiki": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz", + "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@shikijs/core": "2.5.0", + "@shikijs/engine-javascript": "2.5.0", + "@shikijs/engine-oniguruma": "2.5.0", + "@shikijs/langs": "2.5.0", + "@shikijs/themes": "2.5.0", + "@shikijs/types": "2.5.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/space-separated-tokens": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stringify-entities": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", + "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true, + "license": "MIT" + }, + "node_modules/trim-lines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", + "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", + "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", + "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", + "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", + "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", + "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vite": { + "version": "5.4.21", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", + "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vitepress": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz", + "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@docsearch/css": "3.8.2", + "@docsearch/js": "3.8.2", + "@iconify-json/simple-icons": "^1.2.21", + "@shikijs/core": "^2.1.0", + "@shikijs/transformers": "^2.1.0", + "@shikijs/types": "^2.1.0", + "@types/markdown-it": "^14.1.2", + "@vitejs/plugin-vue": "^5.2.1", + "@vue/devtools-api": "^7.7.0", + "@vue/shared": "^3.5.13", + "@vueuse/core": "^12.4.0", + "@vueuse/integrations": "^12.4.0", + "focus-trap": "^7.6.4", + "mark.js": "8.11.1", + "minisearch": "^7.1.1", + "shiki": "^2.1.0", + "vite": "^5.4.14", + "vue": "^3.5.13" + }, + "bin": { + "vitepress": "bin/vitepress.js" + }, + "peerDependencies": { + "markdown-it-mathjax3": "^4", + "postcss": "^8" + }, + "peerDependenciesMeta": { + "markdown-it-mathjax3": { + "optional": true + }, + "postcss": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.5.32", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.32.tgz", + "integrity": "sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.32", + "@vue/compiler-sfc": "3.5.32", + "@vue/runtime-dom": "3.5.32", + "@vue/server-renderer": "3.5.32", + "@vue/shared": "3.5.32" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 00000000..d3c1feee --- /dev/null +++ b/docs/package.json @@ -0,0 +1,16 @@ +{ + "name": "dropset-docs", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vitepress dev", + "build": "vitepress build", + "preview": "vitepress preview", + "format": "prettier --write .", + "format:check": "prettier --check ." + }, + "devDependencies": { + "prettier": "^3.4.2", + "vitepress": "^1.6.3" + } +} diff --git a/docs/src/architecture/accounts.md b/docs/src/architecture/accounts.md new file mode 100644 index 00000000..9b2db14e --- /dev/null +++ b/docs/src/architecture/accounts.md @@ -0,0 +1,77 @@ +# On-Chain Accounts + +Dropset's on-chain state is stored across several account types. Each maps to a context file in `program/src/context/`. + +## Market + +The central account. One per trading pair. Stores: + +- The base and quote mint addresses +- Tick size and lot size configuration +- The bid and ask sides of the order book (packed arrays of resting orders) +- The event queue (a ring buffer of fill and cancel events) +- The seat registry +- Capacity metadata + +The market account is mutated by nearly every instruction. Its size is fixed at creation and can be grown via `expand_market`. + +## Seat + +One per trader per market. A seat must exist before a trader can post or cancel orders. + +- Derived as a PDA from the market and trader public keys +- Only one seat per (market, trader) pair can exist +- Closed via `close_seat` to recover rent + +## Trader balance + +Tracks a trader's deposited funds within a market. Separate balances for base and quote: + +- **Available** — not reserved, can be used to post orders or withdrawn +- **Reserved** — locked by resting orders +- **Settled** — from filled orders, available to withdraw + +Also a PDA derived from the market and trader. + +## Token vaults + +The program holds custody of deposited tokens in two program-owned SPL token accounts per market — one for base, one for quote. Deposits move tokens in; withdrawals move tokens out. + +## Account relationships + +``` +Market + ├── base_vault (SPL token account) + ├── quote_vault (SPL token account) + ├── event_queue (ring buffer) + └── order_book (bid side + ask side) + +Seat (PDA: market + trader) +TraderBalance (PDA: market + trader) + ├── base_available / base_reserved + └── quote_available / quote_reserved +``` + +## PDAs + +Seats and trader balances are program-derived addresses — their addresses are computed deterministically from seeds. This means: + +- Any client can compute a trader's seat address without fetching it +- There can only ever be one seat per (market, trader) pair +- The program can sign for PDA accounts without a private key + +Seeds are defined in `dropset-interface`, so clients and the program always derive the same addresses. + +## Fetching accounts with the TS SDK + +```typescript +import { getMarketAccountDataDecoder } from "@dropset/ts-sdk"; + +const accountInfo = await connection.getAccountInfo(marketPubkey); +const market = getMarketAccountDataDecoder().decode(accountInfo.data); + +console.log(market.baseMint); +console.log(market.quoteMint); +``` + +Decoders are generated from the Codama IDL and live in `ts-sdk/src/generated/`. diff --git a/docs/src/architecture/overview.md b/docs/src/architecture/overview.md new file mode 100644 index 00000000..d00940a6 --- /dev/null +++ b/docs/src/architecture/overview.md @@ -0,0 +1,96 @@ +# Architecture Overview + +Dropset is structured as a Cargo workspace. Each crate has a single responsibility, and the dependency graph flows in one direction — from interface types at the bottom, through program logic in the middle, to clients and services at the top. + +## Workspace layout + +``` +dropset-alpha/ +├── program/ # On-chain Solana program +├── interface/ # Shared instruction schemas + account types +├── instruction-macros/ # Proc macro crate (public API) +├── instruction-macros-impl/ # Proc macro implementation +├── client/ # Rust client for testing + RPC +├── ts-sdk/ # TypeScript SDK +├── price/ # Price math utilities (also mirrored in ts-sdk) +├── services/ +│ ├── faucet/ # Token faucet (devnet/testnet only) +│ ├── maker-bot/ # Avellaneda-Stoikov market maker +│ └── taker-bot/ # Random market order sender +├── cu-bench/ # Compute unit benchmarks +├── codama-idl-gen/ # Codama IDL generation tooling +└── transaction-parser/ # Transaction parsing utilities +``` + +## Dependency flow + +``` + ┌─────────────┐ + │ interface │ ← instruction schemas, account layouts + └──────┬──────┘ + │ + ┌────────────┼────────────┐ + ▼ ▼ ▼ + ┌─────────┐ ┌─────────┐ ┌────────┐ + │ program │ │ client │ │ ts-sdk │ + └─────────┘ └─────────┘ └────────┘ + │ +┌────────┴────────┐ +▼ ▼ +services cu-bench +``` + +The `interface` crate sits at the bottom. It has no dependency on the program itself, so it can be imported by both on-chain programs (via CPI) and off-chain clients without pulling in program logic. + +## No Anchor + +Dropset does **not** use Anchor. Instead it uses a custom `instruction-macros` system that generates: + +- Strongly-typed account context structs +- Instruction builders and discriminators +- Validation scaffolding + +This gives the team precise control over compute unit usage and avoids Anchor's runtime overhead — a meaningful difference for a high-frequency on-chain order book. + +## The program layer + +`program/src/` is organized into four folders: + +| Folder | Purpose | +|---|---| +| `instructions/` | One file per instruction — the handler logic | +| `context/` | One file per instruction — account validation and loading | +| `shared/` | Shared utilities used across multiple instructions | +| `validation/` | Safety contracts and constraint checking | + +Plus top-level files: + +| File | Purpose | +|---|---| +| `entrypoint.rs` | Routes incoming instructions to handlers | +| `events.rs` | Event type definitions emitted by the program | +| `lib.rs` | Crate root | + +## The interface crate + +`dropset-interface` is the contract between the program and its clients. It contains instruction discriminators, parameter schemas, and on-chain account struct definitions. Because it carries no program runtime dependency, it can be imported anywhere — including from other on-chain programs via CPI. + +The TypeScript SDK's `generated/` folder is produced from this crate's IDL via Codama. + +## The TypeScript SDK + +`ts-sdk/src/` is structured in layers: + +``` +ts-sdk/src/ +├── generated/ # Codama IDL-generated — do not edit by hand +├── dropset-interface/ # Hand-written TS layer on top of generated +├── price/ # Price math (ported from the Rust price crate) +├── rust-types/ # TypeScript mirrors of Rust types +├── types/ # Shared TS type definitions +├── utils/ # Utility functions +├── const.ts # Program ID and other constants +└── index.ts # Public SDK entry point +``` + +The `generated/` layer is produced automatically and should never be edited by hand. The `dropset-interface/` layer wraps it with a more ergonomic API. diff --git a/docs/src/architecture/program-structure.md b/docs/src/architecture/program-structure.md new file mode 100644 index 00000000..17e141f3 --- /dev/null +++ b/docs/src/architecture/program-structure.md @@ -0,0 +1,105 @@ +# Program Structure + +The on-chain program lives in `program/src/`. Each instruction has two files: a context file that handles account validation, and a handler file that contains the business logic. + +## Source layout + +``` +program/src/ +├── context/ # Account validation — one file per instruction +├── instructions/ # Handler logic — one file per instruction +│ └── market_order/ # Market order is a subfolder (more complex) +├── shared/ # Helpers shared across instructions +├── validation/ # Safety contracts and constraint checkers +├── debug.rs +├── entrypoint.rs # Routes incoming instructions +├── events.rs # On-chain event definitions +└── lib.rs +``` + +## How an instruction works + +Every instruction follows the same two-file pattern: + +**`context/cancel_order_context.rs`** — defines which accounts are required, their mutability, and validation constraints. Generated by `instruction-macros`. This is the equivalent of Anchor's `#[derive(Accounts)]`. + +**`instructions/cancel_order.rs`** — the handler. Receives the validated context and executes the business logic: modifying order book state, updating balances, emitting events. + +Separating validation from logic makes each file easier to audit independently. + +## Instructions + +Dropset has 10 instructions across three groups. + +### Market lifecycle + +#### `register_market` + +Creates and initializes a new Dropset market. Sets the base and quote mints, tick size, lot size, and initial order book capacity. This must be called before any trading can happen on a pair. + +#### `expand_market` + +Increases the order book capacity of an existing market. Markets are initialized with a fixed number of order slots; `expand_market` allocates more. Called when the book is at capacity. + +### Seat management + +#### `close_seat` + +Closes a trader's seat on a market and reclaims the rent lamports. The seat must have no resting orders before it can be closed. + +### Deposits and withdrawals + +#### `deposit` + +Transfers base or quote tokens from a trader's wallet into the program's custody. Funds must be deposited before orders can be posted. + +#### `withdraw` + +Transfers settled base or quote tokens back out of the program to a trader's wallet. Settled funds accumulate as orders are filled or cancelled. + +### Order management + +#### `post_order` + +Posts a resting limit order onto the book. Takes a side (bid or ask), a price in ticks, and a size in lots. The order rests until filled or cancelled. + +#### `cancel_order` + +Removes a resting order from the book by order ID. The order's reserved funds return to the trader's settled balance. + +#### `batch_replace` + +Cancels a set of existing orders and posts new ones atomically in a single transaction. The primary instruction used by market makers to update quotes. Avoids the overhead of separate cancel + post transactions. + +#### `market_order` + +Executes a market order — immediately matching against the best resting orders on the opposite side. Does not rest on the book. The subfolder structure (`instructions/market_order/`) reflects that this instruction is more complex internally. + +### Event management + +#### `flush_events` + +Removes processed events from the market's event queue and reclaims space. The queue is written on every fill and cancel. Clients or a dedicated crank service should call this regularly. + +## Instruction summary + +| Instruction | Description | +|---|---| +| `register_market` | Create a new market | +| `expand_market` | Grow order book capacity | +| `close_seat` | Close a trader's seat | +| `deposit` | Deposit base or quote tokens | +| `withdraw` | Withdraw settled funds | +| `post_order` | Post a limit order | +| `cancel_order` | Cancel a resting order | +| `batch_replace` | Cancel + post atomically | +| `market_order` | Execute a market order | +| `flush_events` | Clear processed events | + +## Generating internal documentation + +The full Rust API docs — including private modules — can be generated and opened locally: + +```bash +cargo doc --open --no-deps --document-private-items +``` diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 00000000..09b149f1 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,25 @@ +--- +layout: home + +hero: + name: Dropset + text: On-Chain Order Book for Solana + tagline: A fully on-chain central limit order book (CLOB) — post orders, match trades, and build on top of a composable, low-latency protocol. + actions: + - theme: brand + text: Get Started + link: /quickstart/getting-started + - theme: alt + text: Architecture + link: /architecture/overview + +features: + - title: Fully On-Chain CLOB + details: Every order, match, and cancellation happens on-chain. No off-chain matching engine — the program is the exchange. + - title: Composable by Design + details: The dropset-interface crate is client-agnostic. Import it from on-chain or off-chain consumers without pulling in program logic. + - title: TypeScript SDK + details: A Codama IDL-generated SDK with a hand-written interface layer, price utilities, and full type safety. + - title: Custom Instruction Macros + details: Strongly-typed instruction builders and account context structs generated via procedural macros — no Anchor dependency. +--- diff --git a/docs/src/introduction/core-concepts.md b/docs/src/introduction/core-concepts.md new file mode 100644 index 00000000..50311ad8 --- /dev/null +++ b/docs/src/introduction/core-concepts.md @@ -0,0 +1,61 @@ +# Core Concepts + +Before diving into the architecture or SDK, it helps to understand the key concepts that Dropset is built around. These terms appear throughout the codebase and docs. + +## Market + +A **market** is the central object in Dropset. It represents a trading pair — a `base` token and a `quote` token — and holds the order book state on-chain. A market must be registered before any trading can happen, and can be expanded to support more resting orders as needed. + +Key properties of a market: + +- Has a `base` mint and a `quote` mint +- Holds a **bid side** (buy orders) and an **ask side** (sell orders) +- Has a **seat** registry for authorized participants +- Emits events (fills, cancels) into an event queue + +## Seat + +A **seat** is a permissioned slot within a market for a specific trader. Before you can post or cancel orders on a market, you need a seat. Seats can be opened and closed — `close_seat` recovers the rent. + +Think of a seat as your "account" within a specific market. You can hold one seat per market. + +## Order + +An **order** is a resting instruction to buy or sell at a specific price. Orders are posted with `post_order` and removed by being filled (via `market_order` or `batch_replace`) or explicitly cancelled with `cancel_order`. + +Each order has: + +- A **side** (bid or ask) +- A **price** (in ticks) +- A **size** (in lots) +- An **order ID** used for tracking and cancellation + +## Lot and Tick + +Raw token amounts are normalized into **lots** (for size) and **ticks** (for price). This keeps the order book compact on-chain and avoids floating-point math. + +- A **lot** is the minimum tradeable unit of the base token +- A **tick** is the minimum price increment + +Lot and tick sizes are set when a market is registered and cannot be changed. + +## Events + +Dropset uses an **event queue** to record fills and other state changes. Events are written on-chain but need to be flushed periodically via `flush_events` to reclaim space. Your client (or a crank service) is responsible for consuming and flushing events. + +## Deposit and Withdraw + +Before you can post orders, you deposit base or quote tokens into the program. The program holds custody of those tokens while your orders rest. When you cancel or your orders are filled, you can withdraw settled funds. + +## Market Order vs. Post Order + +| | `post_order` | `market_order` | +| ---------------- | ---------------------- | --------------------------------- | +| Type | Limit order | Market order | +| Rests on book? | Yes, until filled or cancelled | No — executes immediately | +| Price control | Exact price specified | Fills at best available | +| Common use | Market making | Taker execution | + +## Batch Replace + +`batch_replace` is an optimized instruction that cancels a set of existing orders and posts new ones in a single transaction. Market makers use this to update their quotes atomically without the overhead of separate cancel + post cycles. diff --git a/docs/src/introduction/what-is-dropset.md b/docs/src/introduction/what-is-dropset.md new file mode 100644 index 00000000..b69b149a --- /dev/null +++ b/docs/src/introduction/what-is-dropset.md @@ -0,0 +1,31 @@ +# What is Dropset? + +Dropset is a fully on-chain central limit order book (CLOB) built for Solana. It lets traders post limit orders and execute market orders against a shared order book that lives entirely on-chain — no off-chain matching engine, no hybrid custody model. + +## Why a CLOB on Solana? + +Most DeFi exchanges rely on AMMs (automated market makers), where liquidity is pooled and prices are determined by a constant-product formula. CLOBs work differently: makers post orders at specific prices, and takers fill them. This model is closer to how traditional exchanges like NYSE or Binance operate, and it offers tighter spreads and more capital efficiency for sophisticated market participants. + +Solana's combination of high throughput and low latency makes it one of the few chains where a fully on-chain CLOB is practical. Dropset is designed to take advantage of that. + +## What can you build with Dropset? + +- **Market makers** — post and manage resting limit orders, implement spread strategies +- **Taker clients** — send market orders that fill against the book +- **Arbitrage bots** — monitor the book and react to price dislocations +- **Composable protocols** — CPI into Dropset from other on-chain programs via the shared interface layer + +## How it fits together + +Dropset is structured as a Rust workspace with clearly separated concerns: + +| Component | What it does | +|---|---| +| `dropset-program` | The on-chain Solana program | +| `dropset-interface` | Client-agnostic instruction schemas and account types | +| `instruction-macros` | Proc macros that generate typed builders and validators | +| `dropset-client` | Rust client for local testing and RPC integration | +| `ts-sdk` | TypeScript SDK for building web and bot clients | +| `services` | Experimental faucet, maker-bot, and taker-bot | + +The next section walks through how these pieces connect at the architecture level. diff --git a/docs/src/public/CNAME b/docs/src/public/CNAME new file mode 100644 index 00000000..edee310b --- /dev/null +++ b/docs/src/public/CNAME @@ -0,0 +1 @@ +docs.dropset.io diff --git a/docs/src/quickstart/getting-started.md b/docs/src/quickstart/getting-started.md new file mode 100644 index 00000000..6ad8bf9c --- /dev/null +++ b/docs/src/quickstart/getting-started.md @@ -0,0 +1,99 @@ +# Getting Started + +This guide gets you from zero to running the Dropset program locally against a Solana test validator. + +## Prerequisites + +| Tool | Version | Install | +|---|---|---| +| Rust | stable | [rustup.rs](https://rustup.rs) | +| Solana CLI | latest | [solana.com/docs](https://solana.com/docs/intro/installation) | +| Node.js | see `.nvmrc` | [nodejs.org](https://nodejs.org) | +| pnpm | latest | `npm install -g pnpm` | + +Check your versions: + +```bash +rustc --version +solana --version +node --version +pnpm --version +``` + +::: tip Node version +The repo pins Node via `.nvmrc`. If you use `nvm`, run `nvm use` in the repo root to switch automatically. +::: + +## 1. Clone the repo + +```bash +git clone https://github.com/DASMAC-com/dropset-alpha.git +cd dropset-alpha +``` + +## 2. Install Node dependencies + +```bash +pnpm install +``` + +Rust workspace dependencies are fetched automatically by Cargo on first build. + +## 3. Build the program + +```bash +cargo build +``` + +To build just the on-chain program: + +```bash +cargo build-sbf -p dropset-program +``` + +## 4. Run a local validator + +In a separate terminal, start a local Solana test validator and leave it running: + +```bash +solana-test-validator +``` + +## 5. Configure Solana CLI for localhost + +```bash +solana config set --url localhost +``` + +## 6. Deploy the program + +```bash +solana program deploy target/sbf-solana-solana/release/dropset_program.so +``` + +Note the **program ID** printed after deployment — you'll need it to interact with the program. + +## 7. Run the tests + +```bash +# Rust tests +cargo test + +# TypeScript SDK tests +pnpm --filter ts-sdk test +``` + +## 8. Run the docs locally + +```bash +make docs +``` + +This runs `cd docs && npm install && npx vitepress dev --open` and opens the docs site in your browser. + +## Next steps + +- [Core Concepts](/introduction/core-concepts) — markets, seats, lots, ticks +- [Architecture Overview](/architecture/overview) — how the workspace fits together +- [Program Structure](/architecture/program-structure) — all 10 instructions explained +- [TypeScript SDK](/sdk/overview) — build a client with the TS SDK diff --git a/docs/src/sdk/overview.md b/docs/src/sdk/overview.md new file mode 100644 index 00000000..78996a43 --- /dev/null +++ b/docs/src/sdk/overview.md @@ -0,0 +1,84 @@ +# TypeScript SDK + +The Dropset TypeScript SDK lives in `ts-sdk/` inside the `dropset-alpha` workspace. It provides everything you need to build clients, bots, and frontends that interact with the Dropset program. + +## Structure + +``` +ts-sdk/src/ +├── generated/ # Auto-generated from Codama IDL — do not edit +├── dropset-interface/ # Ergonomic wrappers around the generated layer +├── price/ # Price math — tick/lot conversions +├── rust-types/ # TypeScript mirrors of Rust types +├── types/ # Shared TypeScript type definitions +├── utils/ # Utility functions +├── const.ts # Program ID and constants +└── index.ts # Public entry point — import from here +``` + +## Layers explained + +### `generated/` + +Produced automatically by Codama from the program's IDL. Contains account decoders/encoders and instruction builders for every instruction. **Do not edit files here** — they are overwritten when the IDL is regenerated: + +```bash +pnpm --filter codama-idl-gen generate +``` + +### `dropset-interface/` + +Hand-written TypeScript that wraps the generated layer with a more ergonomic API — resolving accounts, building complete transactions, and handling common patterns. + +### `price/` + +Ported from the Rust `price` crate. Utilities for converting between raw token amounts and lots, and between decimal prices and ticks. + +## Building and testing + +```bash +# Build +pnpm --filter ts-sdk build + +# Test +pnpm --filter ts-sdk test +``` + +## Basic usage + +### Fetch and decode a market + +```typescript +import { getMarketAccountDataDecoder } from "@dropset/ts-sdk"; + +const accountInfo = await rpc.getAccountInfo(marketAddress).send(); +const market = getMarketAccountDataDecoder().decode(accountInfo.value.data); + +console.log("Base mint:", market.baseMint); +console.log("Quote mint:", market.quoteMint); +``` + +### Build a `post_order` instruction + +```typescript +import { getPostOrderInstruction } from "@dropset/ts-sdk"; + +const ix = getPostOrderInstruction({ + market: marketAddress, + seat: seatAddress, + traderBalance: traderBalanceAddress, + trader: signer.publicKey, + side: "bid", + priceInTicks: 1000n, + numBaseLots: 10n, +}); +``` + +### Price utilities + +```typescript +import { lotsToBaseAtoms, ticksToQuoteAtoms } from "@dropset/ts-sdk"; + +const baseAmount = lotsToBaseAtoms(numLots, market.baseLotSize); +const quoteAmount = ticksToQuoteAtoms(priceInTicks, market.tickSize, market.baseLotSize); +``` diff --git a/docs/src/services/overview.md b/docs/src/services/overview.md new file mode 100644 index 00000000..a54bf124 --- /dev/null +++ b/docs/src/services/overview.md @@ -0,0 +1,33 @@ +# Services + +The `services/` folder contains three experimental services for testing Dropset on devnet and testnet. These are **not intended for production use**. + +## Faucet + +Sends `base` and `quote` tokens to an address on request. Only works on test networks (localhost, devnet, testnet). + +```bash +cargo run -p faucet +``` + +See `services/faucet/README.md` for environment variables and configuration. + +## Maker Bot + +A market-making bot implementing a naive version of the **Avellaneda-Stoikov model** — a stochastic control model that adjusts bid/ask quotes based on inventory risk and volatility estimates. The bot continuously posts and updates orders around a mid-price. + +```bash +cargo run -p maker-bot +``` + +See `services/maker-bot/README.md` for configuration. + +## Taker Bot + +Periodically sends random market orders to a Dropset market. Used to stress-test the book and simulate taker flow during development. + +```bash +cargo run -p taker-bot +``` + +See `services/taker-bot/README.md` for configuration. diff --git a/dropset-alpha b/dropset-alpha new file mode 160000 index 00000000..528f86af --- /dev/null +++ b/dropset-alpha @@ -0,0 +1 @@ +Subproject commit 528f86afb1849782f3073b689173057ec94e2520 From a2dcae635122808e1dd7d8b0bef1e80c4fc36d5f Mon Sep 17 00:00:00 2001 From: Diego Carpenter Date: Tue, 14 Apr 2026 14:38:30 -0700 Subject: [PATCH 2/6] chore: ignore nested dropset-alpha directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a200a184..a81a0eb8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ target test-ledger .turbo +dropset-alpha/ From ab05752ae1fa001b609c148ac59d59f9d30cd479 Mon Sep 17 00:00:00 2001 From: Diego Carpenter Date: Mon, 4 May 2026 15:16:50 -0700 Subject: [PATCH 3/6] docs: add SDK tutorial pages for connect, post-order, and price utils --- Dockerfile | 22 ++++ Makefile | 4 +- docs/.vitepress/config.js | 3 + docs/src/sdk/connect-to-market.md | 103 +++++++++++++++++ docs/src/sdk/overview.md | 68 +++--------- docs/src/sdk/post-order.md | 115 +++++++++++++++++++ docs/src/sdk/price-utils.md | 176 ++++++++++++++++++++++++++++++ 7 files changed, 438 insertions(+), 53 deletions(-) create mode 100644 Dockerfile create mode 100644 docs/src/sdk/connect-to-market.md create mode 100644 docs/src/sdk/post-order.md create mode 100644 docs/src/sdk/price-utils.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..3d8a49e8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM rust:latest + +# Install Solana CLI and platform tools +RUN sh -c "$(curl -sSfL https://release.solana.com/stable/install)" + +# Add Solana to PATH permanently +ENV PATH="/root/.local/share/solana/install/active_release/bin:${PATH}" + +# Verify solana is found then install platform tools +RUN solana --version && \ + cargo install cargo-build-sbf + +# Set working directory +WORKDIR /app + +# Copy repo in +COPY . . + +# Build the program +RUN cargo build-sbf + +CMD ["cargo", "test"] \ No newline at end of file diff --git a/Makefile b/Makefile index 9fb294ab..f03edf9d 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,13 @@ .PHONY: docs-prettier .PHONY: docs-prod -# Build the docs locally for development +# Build the docs locally docs: cd docs && npm install \ && rm -rf .vitepress/cache .vitepress/dist node_modules/.vite \ && npx vitepress dev --open -# Build the docs for production +# Build the docs for production docs-build: cd docs \ && rm -rf .vitepress/cache .vitepress/dist node_modules/.vite \ diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 581995ef..e86fafb4 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -96,6 +96,9 @@ export default { text: "TypeScript SDK", items: [ { text: "Overview", link: "/sdk/overview" }, + { text: "Connect to a Market", link: "/sdk/connect-to-market" }, + { text: "Post an Order", link: "/sdk/post-order" }, + { text: "Price Utilities", link: "/sdk/price-utils" }, ], }, { diff --git a/docs/src/sdk/connect-to-market.md b/docs/src/sdk/connect-to-market.md new file mode 100644 index 00000000..fd819bc7 --- /dev/null +++ b/docs/src/sdk/connect-to-market.md @@ -0,0 +1,103 @@ +# Connect to a Market + +This page shows how to fetch a live Dropset market account and decode its full state — seats, bids, asks, and per-user order data — using the TypeScript SDK. + +## The `toMarketViewAll` function + +The primary way to read a market is `toMarketViewAll`, exported from `ts-sdk/src/dropset-interface/market-view-all.ts`. It takes a decoded `MarketAccount` and returns a fully structured view of everything on the book. + +```typescript +import { toMarketViewAll } from "@dropset/ts-sdk"; +import type { MarketViewAll } from "@dropset/ts-sdk"; +``` + +### What it returns + +```typescript +type MarketViewAll = { + header: MarketHeader; // Market config: mints, tick size, lot size + seats: MarketSeatView[]; // All registered traders on this market + bids: OrderView[]; // All resting buy orders, linked-list order + asks: OrderView[]; // All resting sell orders, linked-list order + users: Map; // Per-trader seat + orders +}; +``` + +Each `OrderView` includes the order's price, size, side, and its position in the doubly-linked list: + +```typescript +type OrderView = { + prevIndex: SectorIndex; + index: SectorIndex; + nextIndex: SectorIndex; + // ...all Order fields except padding +}; +``` + +Each `MarketUserData` groups a trader's seat with their open bids and asks: + +```typescript +type MarketUserData = { + seat: MarketSeatView; + bids: OrderView[]; + asks: OrderView[]; +}; +``` + +## Full example + +```typescript +import { createSolanaRpc } from "@solana/kit"; +import { address } from "@solana/kit"; +import { getMarketAccountDecoder } from "@dropset/ts-sdk"; +import { toMarketViewAll } from "@dropset/ts-sdk"; + +const rpc = createSolanaRpc("https://api.devnet.solana.com"); +const marketAddress = address("YOUR_MARKET_ADDRESS_HERE"); + +// 1. Fetch the raw account +const { value: accountInfo } = await rpc + .getAccountInfo(marketAddress, { encoding: "base64" }) + .send(); + +if (!accountInfo) throw new Error("Market account not found"); + +// 2. Decode the raw bytes into a MarketAccount +const marketAccount = getMarketAccountDecoder().decode( + Buffer.from(accountInfo.data[0], "base64"), +); + +// 3. Build a fully structured view of the market +const view = toMarketViewAll(marketAccount); + +// 4. Inspect the book +console.log("Base mint:", view.header.baseMint); +console.log("Quote mint:", view.header.quoteMint); +console.log("Total seats:", view.seats.length); +console.log("Resting bids:", view.bids.length); +console.log("Resting asks:", view.asks.length); + +// 5. Inspect a specific trader's orders +const traderAddress = address("TRADER_ADDRESS_HERE"); +const userData = view.users.get(traderAddress); + +if (userData) { + console.log("Trader bids:", userData.bids); + console.log("Trader asks:", userData.asks); +} +``` + +## How the sector model works + +Dropset stores all on-chain state — seats, bids, and asks — in a flat byte array called `sectors`. Each sector is a fixed-size slot in that array containing a payload (either an `Order` or a `MarketSeat`) and `prev`/`next` pointers forming a doubly-linked list. + +`toMarketViewAll` traverses these linked lists internally using `collectSectors`, decoding each sector's payload and attaching its index metadata. You don't need to interact with sectors directly — `toMarketViewAll` handles all of that. + +::: tip +If `collectSectors` throws a `Malformed sectors bytes` error, the market account data is either corrupted or you decoded it with the wrong decoder. Make sure you're using `getMarketAccountDecoder()` from the generated layer. +::: + +## Next steps + +- [Post an Order](/sdk/post-order) — build and send a `post_order` transaction +- [Price Utilities](/sdk/price-utils) — convert between UI prices and on-chain encoded values diff --git a/docs/src/sdk/overview.md b/docs/src/sdk/overview.md index 78996a43..b7fe857b 100644 --- a/docs/src/sdk/overview.md +++ b/docs/src/sdk/overview.md @@ -7,32 +7,31 @@ The Dropset TypeScript SDK lives in `ts-sdk/` inside the `dropset-alpha` workspa ``` ts-sdk/src/ ├── generated/ # Auto-generated from Codama IDL — do not edit -├── dropset-interface/ # Ergonomic wrappers around the generated layer -├── price/ # Price math — tick/lot conversions -├── rust-types/ # TypeScript mirrors of Rust types +├── dropset-interface/ # Hand-written wrappers around the generated layer +│ └── market-view-all.ts # toMarketViewAll — read the full book state +├── price/ # Price math — UI ↔ atoms conversions +│ ├── client-helpers.ts # toOrderInfoArgs, atomsToUiAmount, uiPriceToAtomsPrice +│ ├── decoded-price.ts +│ ├── encoded-price.ts +│ └── ... +├── rust-types/ # TypeScript mirrors of Rust types (U8, U32, U64) ├── types/ # Shared TypeScript type definitions ├── utils/ # Utility functions -├── const.ts # Program ID and constants +├── const.ts # Program ID, NIL sentinel, SECTOR_SIZE └── index.ts # Public entry point — import from here ``` -## Layers explained +## Two layers -### `generated/` +The SDK is intentionally split into two layers: -Produced automatically by Codama from the program's IDL. Contains account decoders/encoders and instruction builders for every instruction. **Do not edit files here** — they are overwritten when the IDL is regenerated: +**Generated layer** (`generated/`) — produced automatically by Codama from the program's IDL. Contains raw instruction builders and account decoders. Do not edit these files — they are overwritten when the IDL is regenerated: ```bash pnpm --filter codama-idl-gen generate ``` -### `dropset-interface/` - -Hand-written TypeScript that wraps the generated layer with a more ergonomic API — resolving accounts, building complete transactions, and handling common patterns. - -### `price/` - -Ported from the Rust `price` crate. Utilities for converting between raw token amounts and lots, and between decimal prices and ticks. +**Interface layer** (`dropset-interface/`) — hand-written TypeScript that wraps the generated layer with ergonomic, higher-level APIs. This is where `toMarketViewAll` lives, which gives you a fully structured view of the order book in one call. ## Building and testing @@ -44,41 +43,8 @@ pnpm --filter ts-sdk build pnpm --filter ts-sdk test ``` -## Basic usage - -### Fetch and decode a market - -```typescript -import { getMarketAccountDataDecoder } from "@dropset/ts-sdk"; - -const accountInfo = await rpc.getAccountInfo(marketAddress).send(); -const market = getMarketAccountDataDecoder().decode(accountInfo.value.data); - -console.log("Base mint:", market.baseMint); -console.log("Quote mint:", market.quoteMint); -``` +## Guides -### Build a `post_order` instruction - -```typescript -import { getPostOrderInstruction } from "@dropset/ts-sdk"; - -const ix = getPostOrderInstruction({ - market: marketAddress, - seat: seatAddress, - traderBalance: traderBalanceAddress, - trader: signer.publicKey, - side: "bid", - priceInTicks: 1000n, - numBaseLots: 10n, -}); -``` - -### Price utilities - -```typescript -import { lotsToBaseAtoms, ticksToQuoteAtoms } from "@dropset/ts-sdk"; - -const baseAmount = lotsToBaseAtoms(numLots, market.baseLotSize); -const quoteAmount = ticksToQuoteAtoms(priceInTicks, market.tickSize, market.baseLotSize); -``` +- [Connect to a Market](/sdk/connect-to-market) — fetch and decode a live market, read seats, bids, and asks +- [Post an Order](/sdk/post-order) — build and send a `post_order` transaction end to end +- [Price Utilities](/sdk/price-utils) — convert between UI prices and on-chain encoded values diff --git a/docs/src/sdk/post-order.md b/docs/src/sdk/post-order.md new file mode 100644 index 00000000..a6914a85 --- /dev/null +++ b/docs/src/sdk/post-order.md @@ -0,0 +1,115 @@ +# Post an Order + +This page walks through building and sending a `post_order` transaction using the TypeScript SDK — from converting a human-readable price to submitting the signed transaction. + +## Prerequisites + +Before you can post an order you need: + +- A registered market (see `register_market`) +- A seat on that market +- A deposited balance of base or quote tokens (see `deposit`) + +## The full flow + +```typescript +import { createSolanaRpc, createSolanaRpcSubscriptions } from "@solana/kit"; +import { address } from "@solana/kit"; +import { Decimal } from "decimal.js"; +import { + getPostOrderInstruction, + toOrderInfoArgs, + uiPriceToAtomsPrice, +} from "@dropset/ts-sdk"; + +const rpc = createSolanaRpc("https://api.devnet.solana.com"); + +// Your addresses +const marketAddress = address("MARKET_ADDRESS"); +const traderAddress = address("TRADER_ADDRESS"); +const seatAddress = address("SEAT_ADDRESS"); // PDA: market + trader +const balanceAddress = address("BALANCE_ADDRESS"); // PDA: market + trader + +// Market decimal configuration +const BASE_DECIMALS = 9; +const QUOTE_DECIMALS = 6; + +// Step 1 — Convert your human price to on-chain args +const uiPrice = new Decimal("42.50"); +const orderSizeBaseAtoms = 1_000_000_000n; // 1 base token + +const atomsPrice = uiPriceToAtomsPrice(uiPrice, BASE_DECIMALS, QUOTE_DECIMALS); +const orderArgs = toOrderInfoArgs(atomsPrice, orderSizeBaseAtoms); + +// Step 2 — Build the instruction +const ix = getPostOrderInstruction({ + market: marketAddress, + trader: traderAddress, + seat: seatAddress, + traderBalance: balanceAddress, + side: 0, // 0 = bid, 1 = ask + ...orderArgs, +}); + +// Step 3 — Build and send the transaction +const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); + +// Sign and send using your wallet/keypair +// (exact signing depends on your client setup) +``` + +## Order sides + +| Value | Side | Meaning | +|---|---|---| +| `0` | Bid | Buy order — you're offering quote tokens to buy base tokens | +| `1` | Ask | Sell order — you're offering base tokens to receive quote tokens | + +## The `post_order` instruction accounts + +| Account | Description | +|---|---| +| `market` | The market account (writable) | +| `trader` | The trader's public key (signer) | +| `seat` | The trader's seat PDA on this market | +| `traderBalance` | The trader's balance PDA on this market (writable) | + +## What happens on-chain + +When `post_order` executes: + +1. The program validates the trader's seat and balance accounts +2. It reserves the required funds from the trader's available balance +3. It inserts the order into the correct side of the book (bid or ask) in price-time priority order +4. The order rests until it is filled by a `market_order` or `batch_replace`, or cancelled via `cancel_order` + +## Cancelling an order + +To cancel a resting order you need its `index` from the `OrderView`. Get this by reading the market first: + +```typescript +import { toMarketViewAll, getMarketAccountDecoder } from "@dropset/ts-sdk"; +import { getCancelOrderInstruction } from "@dropset/ts-sdk"; + +// Fetch and decode the market +const view = toMarketViewAll(marketAccount); + +// Find your orders +const myOrders = view.users.get(traderAddress); +const orderToCancel = myOrders?.bids[0]; + +if (orderToCancel) { + const cancelIx = getCancelOrderInstruction({ + market: marketAddress, + trader: traderAddress, + seat: seatAddress, + traderBalance: balanceAddress, + orderIndex: orderToCancel.index, + }); +} +``` + +## Next steps + +- [Price Utilities](/sdk/price-utils) — understand how `toOrderInfoArgs` works +- [Connect to a Market](/sdk/connect-to-market) — read the book before and after posting diff --git a/docs/src/sdk/price-utils.md b/docs/src/sdk/price-utils.md new file mode 100644 index 00000000..0396afbd --- /dev/null +++ b/docs/src/sdk/price-utils.md @@ -0,0 +1,176 @@ +# Price Utilities + +The `price/` module in the TypeScript SDK is a direct port of the Rust `price` crate. It handles all conversions between human-readable (UI) values and the on-chain encoded representation that the Dropset program uses. + +All functions below are exported from `@dropset/ts-sdk`. + +## Why price encoding exists + +Dropset stores prices on-chain in a compact encoded format — a mantissa and a biased exponent — rather than as raw integers. This keeps the order book memory-efficient and avoids overflow issues with large token amounts. The `price/` utilities handle encoding and decoding so you never have to work with the raw format directly. + +## Core functions + +### `atomsToUiAmount` + +Converts a raw token amount (in atoms — the smallest unit) to a human-readable decimal, given the mint's decimal places. + +```typescript +import { atomsToUiAmount } from "@dropset/ts-sdk"; +import { Decimal } from "decimal.js"; + +// Convert 1,000,000 atoms of a 6-decimal token → "1.0" +const uiAmount = atomsToUiAmount(1_000_000n, 6); +console.log(uiAmount.toString()); // "1" + +// USDC has 6 decimals +const usdcUiAmount = atomsToUiAmount(5_500_000n, 6); +console.log(usdcUiAmount.toString()); // "5.5" +``` + +**Signature:** +```typescript +function atomsToUiAmount( + atomsAmount: bigint, + mintDecimals: number | bigint, +): Decimal +``` + +--- + +### `uiPriceToAtomsPrice` + +Converts a human-readable price (quote per base, e.g. "42.50 USDC per SOL") to an atoms-denominated price, accounting for the difference in decimal places between the base and quote mints. + +```typescript +import { uiPriceToAtomsPrice } from "@dropset/ts-sdk"; +import { Decimal } from "decimal.js"; + +// SOL/USDC market: SOL has 9 decimals, USDC has 6 decimals +const uiPrice = new Decimal("42.50"); +const atomsPrice = uiPriceToAtomsPrice(uiPrice, 9, 6); +console.log(atomsPrice.toString()); // "0.0000425" (adjusted for decimal difference) +``` + +**Signature:** +```typescript +function uiPriceToAtomsPrice( + uiPrice: Decimal, + baseDecimals: number | bigint, + quoteDecimals: number | bigint, +): Decimal +``` + +The formula applied is: `atomsPrice = uiPrice × 10^(quoteDecimals − baseDecimals)` + +--- + +### `toOrderInfoArgs` + +The most important function for placing orders. Converts a decimal price and a base-atom order size into the four on-chain fields that `post_order` and `batch_replace` require: `priceMantissa`, `baseScalar`, `baseExponentBiased`, and `quoteExponentBiased`. + +```typescript +import { toOrderInfoArgs, uiPriceToAtomsPrice } from "@dropset/ts-sdk"; +import { Decimal } from "decimal.js"; + +// You want to post a bid: buy 2 SOL at 42.50 USDC +const uiPrice = new Decimal("42.50"); +const atomsPrice = uiPriceToAtomsPrice(uiPrice, 9, 6); // SOL=9 dec, USDC=6 dec + +const orderSizeBaseAtoms = 2_000_000_000n; // 2 SOL in lamports + +const args = toOrderInfoArgs(atomsPrice, orderSizeBaseAtoms); + +console.log(args); +// { +// priceMantissa: ..., +// baseScalar: ..., +// baseExponentBiased: ..., +// quoteExponentBiased: ... +// } + +// Pass these directly into the post_order instruction builder +``` + +**Signature:** +```typescript +function toOrderInfoArgs( + price: Decimal, + orderSizeBaseAtoms: bigint, +): { + priceMantissa: U32; + baseScalar: U64; + baseExponentBiased: U8; + quoteExponentBiased: U8; +} +``` + +::: warning +`toOrderInfoArgs` throws `PriceError.AmountCannotBeZero` if `orderSizeBaseAtoms` is `0n`. Always validate order size before calling it. +::: + +--- + +### `encodedU32ToDecimal` + +Decodes an on-chain encoded price (a `u32`) back into a human-readable `Decimal`. Useful for displaying resting order prices from the book. + +```typescript +import { encodedU32ToDecimal } from "@dropset/ts-sdk"; + +// Decode an encoded price from an OrderView +const order = view.bids[0]; +const decodedPrice = encodedU32ToDecimal(order.price); +console.log(decodedPrice.toString()); // e.g. "42.5" +``` + +**Signature:** +```typescript +function encodedU32ToDecimal(encodedU32: number | bigint): Decimal +``` + +--- + +### `toBiasedExponent` + +Low-level utility that converts an unbiased exponent to the biased format the program uses. You generally won't call this directly — `toOrderInfoArgs` handles it internally. + +```typescript +function toBiasedExponent(unbiased: number): U8 +``` + +Throws `PriceError.InvalidBiasedExponent` if the value is outside the supported range. + +--- + +## Full order placement flow + +```typescript +import { Decimal } from "decimal.js"; +import { + atomsToUiAmount, + uiPriceToAtomsPrice, + toOrderInfoArgs, +} from "@dropset/ts-sdk"; + +// Market config (from market header) +const BASE_DECIMALS = 9; // e.g. SOL +const QUOTE_DECIMALS = 6; // e.g. USDC + +// Step 1 — Define your order parameters in human terms +const uiPrice = new Decimal("42.50"); // 42.50 USDC per SOL +const orderSizeBaseAtoms = 1_000_000_000n; // 1 SOL + +// Step 2 — Convert UI price to atoms price +const atomsPrice = uiPriceToAtomsPrice(uiPrice, BASE_DECIMALS, QUOTE_DECIMALS); + +// Step 3 — Get the on-chain instruction args +const orderArgs = toOrderInfoArgs(atomsPrice, orderSizeBaseAtoms); + +// Step 4 — Pass to the instruction builder (see Post an Order) +// getPostOrderInstruction({ ...orderArgs, ... }) +``` + +## Next steps + +- [Post an Order](/sdk/post-order) — use `toOrderInfoArgs` output in a real transaction +- [Connect to a Market](/sdk/connect-to-market) — read the book and decode existing order prices From 7f459724f50778350b6963b94efafcfa4aaa2cf5 Mon Sep 17 00:00:00 2001 From: Diego Carpenter Date: Mon, 11 May 2026 11:23:54 -0700 Subject: [PATCH 4/6] docs: add interactive components and updated config --- docs/.vitepress/config.js | 70 +-- .../theme/components/CuExplorer.vue | 287 +++++++++++ .../theme/components/InstructionCards.vue | 457 ++++++++++++++++++ .../theme/components/OrderBookViz.vue | 414 ++++++++++++++++ docs/.vitepress/theme/index.js | 15 +- docs/src/benchmarks/index.md | 38 ++ docs/src/program/instructions.md | 35 ++ docs/src/program/order-book-viz.md | 27 ++ 8 files changed, 1293 insertions(+), 50 deletions(-) create mode 100644 docs/.vitepress/theme/components/CuExplorer.vue create mode 100644 docs/.vitepress/theme/components/InstructionCards.vue create mode 100644 docs/.vitepress/theme/components/OrderBookViz.vue create mode 100644 docs/src/benchmarks/index.md create mode 100644 docs/src/program/instructions.md create mode 100644 docs/src/program/order-book-viz.md diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index e86fafb4..de84a5ab 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -3,66 +3,25 @@ export default { description: "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", head: [ - [ - "link", - { - rel: "icon", - href: "/favicon-light.png", - media: "(prefers-color-scheme: light)", - }, - ], - [ - "link", - { - rel: "icon", - href: "/favicon-dark.png", - media: "(prefers-color-scheme: dark)", - }, - ], + ["link", { rel: "icon", href: "/favicon-light.png", media: "(prefers-color-scheme: light)" }], + ["link", { rel: "icon", href: "/favicon-dark.png", media: "(prefers-color-scheme: dark)" }], ["link", { rel: "apple-touch-icon", href: "/favicon-light.png" }], ["meta", { property: "og:site_name", content: "DASMAC" }], ["meta", { property: "og:type", content: "website" }], ["meta", { property: "og:url", content: "https://docs.dropset.io/" }], ["meta", { property: "og:title", content: "Dropset Docs" }], - [ - "meta", - { - property: "og:description", - content: - "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", - }, - ], - [ - "meta", - { - property: "og:image", - content: "https://docs.dropset.io/dasmac-banner.png", - }, - ], + ["meta", { property: "og:description", content: "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)" }], + ["meta", { property: "og:image", content: "https://docs.dropset.io/dasmac-banner.png" }], ["meta", { name: "twitter:card", content: "summary_large_image" }], ["meta", { name: "twitter:title", content: "Dropset Docs" }], - [ - "meta", - { - name: "twitter:description", - content: - "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", - }, - ], - [ - "meta", - { - name: "twitter:image", - content: "https://docs.dropset.io/dasmac-banner.png", - }, - ], + ["meta", { name: "twitter:description", content: "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)" }], + ["meta", { name: "twitter:image", content: "https://docs.dropset.io/dasmac-banner.png" }], ], srcDir: "src", themeConfig: { outline: "deep", editLink: { - pattern: - "https://github.com/DASMAC-com/dropset-alpha/blob/main/docs/src/:path", + pattern: "https://github.com/DASMAC-com/dropset-alpha/blob/main/docs/src/:path", text: "Contribute to this page", }, sidebar: [ @@ -84,6 +43,14 @@ export default { { text: "On-Chain Accounts", link: "/architecture/accounts" }, ], }, + { + collapsed: false, + text: "Program Reference", + items: [ + { text: "Instruction Cards", link: "/program/instructions" }, + { text: "Order Book Visualizer", link: "/program/order-book-viz" }, + ], + }, { collapsed: false, text: "Quickstart", @@ -101,6 +68,13 @@ export default { { text: "Price Utilities", link: "/sdk/price-utils" }, ], }, + { + collapsed: false, + text: "Benchmarks", + items: [ + { text: "CU Cost Explorer", link: "/benchmarks/" }, + ], + }, { collapsed: false, text: "Services", diff --git a/docs/.vitepress/theme/components/CuExplorer.vue b/docs/.vitepress/theme/components/CuExplorer.vue new file mode 100644 index 00000000..4e905fa1 --- /dev/null +++ b/docs/.vitepress/theme/components/CuExplorer.vue @@ -0,0 +1,287 @@ + + + + + diff --git a/docs/.vitepress/theme/components/InstructionCards.vue b/docs/.vitepress/theme/components/InstructionCards.vue new file mode 100644 index 00000000..f1886358 --- /dev/null +++ b/docs/.vitepress/theme/components/InstructionCards.vue @@ -0,0 +1,457 @@ + + + + + diff --git a/docs/.vitepress/theme/components/OrderBookViz.vue b/docs/.vitepress/theme/components/OrderBookViz.vue new file mode 100644 index 00000000..fe8acc67 --- /dev/null +++ b/docs/.vitepress/theme/components/OrderBookViz.vue @@ -0,0 +1,414 @@ + + + + + diff --git a/docs/.vitepress/theme/index.js b/docs/.vitepress/theme/index.js index 6b573792..73666345 100644 --- a/docs/.vitepress/theme/index.js +++ b/docs/.vitepress/theme/index.js @@ -1,2 +1,13 @@ -import DefaultTheme from 'vitepress/theme'; -export default DefaultTheme; +import DefaultTheme from "vitepress/theme"; +import CuExplorer from "./components/CuExplorer.vue"; +import OrderBookViz from "./components/OrderBookViz.vue"; +import InstructionCards from "./components/InstructionCards.vue"; + +export default { + extends: DefaultTheme, + enhanceApp({ app }) { + app.component("CuExplorer", CuExplorer); + app.component("OrderBookViz", OrderBookViz); + app.component("InstructionCards", InstructionCards); + }, +}; diff --git a/docs/src/benchmarks/index.md b/docs/src/benchmarks/index.md new file mode 100644 index 00000000..1e35d57e --- /dev/null +++ b/docs/src/benchmarks/index.md @@ -0,0 +1,38 @@ +# Compute Unit Benchmarks + +Dropset is built without Anchor and uses hand-written SBF assembly for critical paths. The result is dramatically lower compute unit consumption compared to other on-chain order books on Solana. + +**Lower compute units = lower transaction fees and higher throughput.** + +## Interactive comparison + +Filter by instruction category and see the CU cost for each protocol side by side. The "Dropset advantage" column shows how many times more efficient Dropset is versus the best alternative. + + + +## How to run the benchmarks yourself + +The benchmark suite lives in `cu-bench/` in the `dropset-alpha` repo. Each protocol has its own benchmark script: + +```bash +# Dropset +bash cu-bench/dropset/run-bench.sh + +# Phoenix +bash cu-bench/phoenix/run-bench.sh + +# Manifest +bash cu-bench/manifest/run-bench.sh +``` + +Results are printed to stdout. See `cu-bench/README.md` for details on methodology and what each benchmark measures. + +## Why compute units matter + +On Solana, every transaction consumes compute units up to a per-transaction limit. Lower CU usage means: + +- **Lower fees** — users pay less per trade +- **More instructions per transaction** — batch operations fit in a single tx +- **Higher theoretical throughput** — more transactions fit per block + +For a high-frequency on-chain order book, CU efficiency is not a nice-to-have — it is the core engineering constraint. diff --git a/docs/src/program/instructions.md b/docs/src/program/instructions.md new file mode 100644 index 00000000..6afdbcc2 --- /dev/null +++ b/docs/src/program/instructions.md @@ -0,0 +1,35 @@ +# Instruction Reference + +Quick-reference cards for all 10 Dropset instructions. Click any card to expand its full account list, emitted events, and notes. + +Filter by category to focus on a specific area of the protocol. + + + +## How to read a card + +**CU** — the approximate compute unit cost of this instruction on a Solana localnet benchmark. See [Benchmarks](/benchmarks/) for full comparisons against Phoenix and Manifest. + +**Accounts** — every account the instruction requires, with mutability and signer flags: +- `mut` — the instruction writes to this account +- `signer` — this account must sign the transaction +- `PDA` — this is a program-derived address, computed deterministically from seeds + +**Emits** — events written to the market's event queue when this instruction executes. Read via `toMarketViewAll()` or consume with `flush_events`. + +## Account conventions + +All PDAs in Dropset are derived from seeds defined in `dropset-interface/`, so any client can compute them without fetching first: + +| Account | Seeds | +|---|---| +| Seat | `[market, trader]` | +| Trader balance | `[market, trader]` | +| Base vault | `[market, "base"]` | +| Quote vault | `[market, "quote"]` | + +## Further reading + +- [Program Structure](/architecture/program-structure) — prose explanation of each instruction +- [On-Chain Accounts](/architecture/accounts) — how account data is laid out +- [Post an Order](/sdk/post-order) — SDK walkthrough using the real instruction builders diff --git a/docs/src/program/order-book-viz.md b/docs/src/program/order-book-viz.md new file mode 100644 index 00000000..4371fd76 --- /dev/null +++ b/docs/src/program/order-book-viz.md @@ -0,0 +1,27 @@ +# Order Book Visualizer + +This interactive diagram walks through how each Dropset instruction affects the bid/ask ladder. Click any instruction button or use Prev/Next to step through the sequence. + + + +## Reading the diagram + +- **Green rows** — bid (buy) orders, sorted highest price first +- **Red rows** — ask (sell) orders, sorted lowest price first +- **Purple highlight** — newly added order in this step +- **Strikethrough** — order that was filled or cancelled in this step +- **Spread** — the gap between the best bid and best ask + +## Key takeaways + +**`post_order`** inserts a resting order at a specific price. It does not execute immediately — it waits for a counterparty. + +**`market_order`** crosses the spread and fills against the best resting price. It leaves no order on the book. + +**`cancel_order`** removes a resting order and returns the reserved funds to available balance. The position in the book is freed. + +**`batch_replace`** is the most important instruction for market makers. It cancels and re-quotes atomically — there is no window where a maker has no orders on the book between a cancel and a new post. + +## The event queue + +Every fill and cancellation writes an event to the market's event queue on-chain. These events need to be periodically consumed via `flush_events` to keep the queue from filling up. See [Services](/services/overview) for how the crank bots handle this in practice. From 3e46784c666f26b2621ef4677a907bb93f240ebd Mon Sep 17 00:00:00 2001 From: Diego Carpenter Date: Mon, 11 May 2026 11:39:12 -0700 Subject: [PATCH 5/6] ci: fix checkout action version --- .github/workflows/build-docs.yml | 2 +- .github/workflows/deploy.yml | 2 +- .github/workflows/quick-lint.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml index 56407658..5ff0a71d 100644 --- a/.github/workflows/build-docs.yml +++ b/.github/workflows/build-docs.yml @@ -4,7 +4,7 @@ jobs: name: 'Build docs' runs-on: 'ubuntu-latest' steps: - - uses: 'actions/checkout@v6' + - uses: 'actions/checkout@v4' - uses: 'actions/setup-node@v6' with: cache: 'npm' diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e677fbe4..0c324eeb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,7 +7,7 @@ jobs: runs-on: 'ubuntu-latest' steps: - name: 'Checkout' - uses: 'actions/checkout@v5' + uses: 'actions/checkout@v4' with: fetch-depth: null - name: 'Setup Node' diff --git a/.github/workflows/quick-lint.yml b/.github/workflows/quick-lint.yml index 61552187..75ae069c 100644 --- a/.github/workflows/quick-lint.yml +++ b/.github/workflows/quick-lint.yml @@ -4,7 +4,7 @@ jobs: name: 'Quick lint' runs-on: 'ubuntu-latest' steps: - - uses: 'actions/checkout@v6' + - uses: 'actions/checkout@v4' - uses: 'actions/setup-node@v6' with: cache: 'npm' From c5d2fc625bf352384b669703a47142d24a3756d6 Mon Sep 17 00:00:00 2001 From: Diego Carpenter Date: Wed, 13 May 2026 10:47:33 -0700 Subject: [PATCH 6/6] fix: remove accidental submodule entry --- docs/.vitepress/config.js | 68 ++- .../theme/components/CuExplorer.vue | 108 ++++- .../theme/components/InstructionCards.vue | 451 +++++++++++++++--- .../theme/components/OrderBookViz.vue | 91 ++-- docs/src/architecture/overview.md | 22 +- docs/src/architecture/program-structure.md | 24 +- docs/src/introduction/core-concepts.md | 12 +- docs/src/introduction/what-is-dropset.md | 14 +- docs/src/program/instructions.md | 13 +- docs/src/quickstart/getting-started.md | 12 +- docs/src/sdk/connect-to-market.md | 8 +- docs/src/sdk/post-order.md | 22 +- docs/src/sdk/price-utils.md | 20 +- dropset-alpha | 1 - 14 files changed, 653 insertions(+), 213 deletions(-) delete mode 160000 dropset-alpha diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index de84a5ab..9845070e 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -3,25 +3,66 @@ export default { description: "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", head: [ - ["link", { rel: "icon", href: "/favicon-light.png", media: "(prefers-color-scheme: light)" }], - ["link", { rel: "icon", href: "/favicon-dark.png", media: "(prefers-color-scheme: dark)" }], + [ + "link", + { + rel: "icon", + href: "/favicon-light.png", + media: "(prefers-color-scheme: light)", + }, + ], + [ + "link", + { + rel: "icon", + href: "/favicon-dark.png", + media: "(prefers-color-scheme: dark)", + }, + ], ["link", { rel: "apple-touch-icon", href: "/favicon-light.png" }], ["meta", { property: "og:site_name", content: "DASMAC" }], ["meta", { property: "og:type", content: "website" }], ["meta", { property: "og:url", content: "https://docs.dropset.io/" }], ["meta", { property: "og:title", content: "Dropset Docs" }], - ["meta", { property: "og:description", content: "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)" }], - ["meta", { property: "og:image", content: "https://docs.dropset.io/dasmac-banner.png" }], + [ + "meta", + { + property: "og:description", + content: + "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", + }, + ], + [ + "meta", + { + property: "og:image", + content: "https://docs.dropset.io/dasmac-banner.png", + }, + ], ["meta", { name: "twitter:card", content: "summary_large_image" }], ["meta", { name: "twitter:title", content: "Dropset Docs" }], - ["meta", { name: "twitter:description", content: "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)" }], - ["meta", { name: "twitter:image", content: "https://docs.dropset.io/dasmac-banner.png" }], + [ + "meta", + { + name: "twitter:description", + content: + "Courtesy of Distributed Atomic State Machine Algorithms Corporation (DASMAC)", + }, + ], + [ + "meta", + { + name: "twitter:image", + content: "https://docs.dropset.io/dasmac-banner.png", + }, + ], ], srcDir: "src", themeConfig: { outline: "deep", editLink: { - pattern: "https://github.com/DASMAC-com/dropset-alpha/blob/main/docs/src/:path", + pattern: + "https://github.com/DASMAC-com/dropset-alpha/blob/main/docs/src/:path", text: "Contribute to this page", }, sidebar: [ @@ -39,7 +80,10 @@ export default { text: "Architecture", items: [ { text: "Overview", link: "/architecture/overview" }, - { text: "Program Structure", link: "/architecture/program-structure" }, + { + text: "Program Structure", + link: "/architecture/program-structure", + }, { text: "On-Chain Accounts", link: "/architecture/accounts" }, ], }, @@ -71,16 +115,12 @@ export default { { collapsed: false, text: "Benchmarks", - items: [ - { text: "CU Cost Explorer", link: "/benchmarks/" }, - ], + items: [{ text: "CU Cost Explorer", link: "/benchmarks/" }], }, { collapsed: false, text: "Services", - items: [ - { text: "Faucet, Maker & Taker", link: "/services/overview" }, - ], + items: [{ text: "Faucet, Maker & Taker", link: "/services/overview" }], }, ], }, diff --git a/docs/.vitepress/theme/components/CuExplorer.vue b/docs/.vitepress/theme/components/CuExplorer.vue index 4e905fa1..14a3d614 100644 --- a/docs/.vitepress/theme/components/CuExplorer.vue +++ b/docs/.vitepress/theme/components/CuExplorer.vue @@ -12,8 +12,15 @@
- - + + {{ protocol.name }}
@@ -24,7 +31,11 @@ Instruction - + {{ p.name }} Dropset advantage @@ -47,7 +58,7 @@ }" > - {{ row[p.name] != null ? row[p.name].toLocaleString() : '—' }} + {{ row[p.name] != null ? row[p.name].toLocaleString() : "—" }} @@ -62,8 +73,9 @@

- CU = Compute Units consumed per transaction on a Solana localnet benchmark. - Lower is better. Data from cu-bench/ in the dropset-alpha repo. + CU = Compute Units consumed per transaction on a Solana localnet + benchmark. Lower is better. Data from cu-bench/ in the + dropset-alpha repo.

@@ -79,16 +91,76 @@ const protocols = [ // Fill in exact numbers from cu-bench/ output — placeholders marked with * const rows = [ - { instruction: "post_order", category: "Orders", Dropset: 461, Phoenix: 19244, Manifest: 12800 }, - { instruction: "cancel_order", category: "Orders", Dropset: 318, Phoenix: 14200, Manifest: 9400 }, - { instruction: "batch_replace", category: "Orders", Dropset: 890, Phoenix: null, Manifest: null }, - { instruction: "market_order", category: "Orders", Dropset: 520, Phoenix: 21000, Manifest: 13500 }, - { instruction: "deposit", category: "Balances", Dropset: 210, Phoenix: 8400, Manifest: 5200 }, - { instruction: "withdraw", category: "Balances", Dropset: 195, Phoenix: 7900, Manifest: 4900 }, - { instruction: "register_market", category: "Market", Dropset: 1200, Phoenix: 18000, Manifest: 14000 }, - { instruction: "expand_market", category: "Market", Dropset: 480, Phoenix: null, Manifest: null }, - { instruction: "flush_events", category: "Market", Dropset: 290, Phoenix: 6200, Manifest: 3800 }, - { instruction: "close_seat", category: "Seats", Dropset: 175, Phoenix: 5100, Manifest: 3200 }, + { + instruction: "post_order", + category: "Orders", + Dropset: 461, + Phoenix: 19244, + Manifest: 12800, + }, + { + instruction: "cancel_order", + category: "Orders", + Dropset: 318, + Phoenix: 14200, + Manifest: 9400, + }, + { + instruction: "batch_replace", + category: "Orders", + Dropset: 890, + Phoenix: null, + Manifest: null, + }, + { + instruction: "market_order", + category: "Orders", + Dropset: 520, + Phoenix: 21000, + Manifest: 13500, + }, + { + instruction: "deposit", + category: "Balances", + Dropset: 210, + Phoenix: 8400, + Manifest: 5200, + }, + { + instruction: "withdraw", + category: "Balances", + Dropset: 195, + Phoenix: 7900, + Manifest: 4900, + }, + { + instruction: "register_market", + category: "Market", + Dropset: 1200, + Phoenix: 18000, + Manifest: 14000, + }, + { + instruction: "expand_market", + category: "Market", + Dropset: 480, + Phoenix: null, + Manifest: null, + }, + { + instruction: "flush_events", + category: "Market", + Dropset: 290, + Phoenix: 6200, + Manifest: 3800, + }, + { + instruction: "close_seat", + category: "Seats", + Dropset: 175, + Phoenix: 5100, + Manifest: 3200, + }, ]; const categories = ["All", "Orders", "Balances", "Market", "Seats"]; @@ -97,11 +169,11 @@ const activeCategory = ref("All"); const filteredRows = computed(() => activeCategory.value === "All" ? rows - : rows.filter((r) => r.category === activeCategory.value) + : rows.filter((r) => r.category === activeCategory.value), ); const maxCu = computed(() => - Math.max(...rows.flatMap((r) => protocols.map((p) => r[p.name] ?? 0))) + Math.max(...rows.flatMap((r) => protocols.map((p) => r[p.name] ?? 0))), ); function barWidth(val) { diff --git a/docs/.vitepress/theme/components/InstructionCards.vue b/docs/.vitepress/theme/components/InstructionCards.vue index f1886358..b739455c 100644 --- a/docs/.vitepress/theme/components/InstructionCards.vue +++ b/docs/.vitepress/theme/components/InstructionCards.vue @@ -22,7 +22,10 @@
{{ ix.name }} - + {{ ix.category }}
@@ -35,7 +38,9 @@ {{ ix.accounts.length }} accounts - {{ expanded === ix.name ? '▲' : '▼' }} + {{ + expanded === ix.name ? "▲" : "▼" + }}
@@ -43,7 +48,11 @@
- @@ -55,19 +60,38 @@ > {{ order.price }}
-
+
{{ order.size }} lots - {{ order.state }} + {{ + order.state + }}
- - {{ activeStep + 1 }} / {{ steps.length }} - + + {{ activeStep + 1 }} / {{ steps.length }} +
@@ -81,7 +105,8 @@ const activeStep = ref(0); const steps = [ { instruction: "initial state", - description: "The order book starts empty. No bids, no asks. A market must be registered before orders can be posted.", + description: + "The order book starts empty. No bids, no asks. A market must be registered before orders can be posted.", spread: "—", book: { asks: [], @@ -90,7 +115,8 @@ const steps = [ }, { instruction: "post_order (ask)", - description: "A market maker posts a sell order at price 102 for 5 lots. It rests on the ask side of the book until filled or cancelled.", + description: + "A market maker posts a sell order at price 102 for 5 lots. It rests on the ask side of the book until filled or cancelled.", spread: "—", book: { asks: [{ id: "a1", price: "102", size: 5, state: "new" }], @@ -99,7 +125,8 @@ const steps = [ }, { instruction: "post_order (bid)", - description: "The same maker posts a buy order at price 98 for 5 lots. Now there are resting orders on both sides. The spread is 4 ticks.", + description: + "The same maker posts a buy order at price 98 for 5 lots. Now there are resting orders on both sides. The spread is 4 ticks.", spread: "4 ticks", book: { asks: [{ id: "a1", price: "102", size: 5, state: "" }], @@ -108,7 +135,8 @@ const steps = [ }, { instruction: "post_order (tighter)", - description: "A second maker tightens the market, posting a bid at 99 and an ask at 101. The spread narrows to 2 ticks.", + description: + "A second maker tightens the market, posting a bid at 99 and an ask at 101. The spread narrows to 2 ticks.", spread: "2 ticks", book: { asks: [ @@ -116,14 +144,15 @@ const steps = [ { id: "a1", price: "102", size: 5, state: "" }, ], bids: [ - { id: "b2", price: "99", size: 3, state: "new" }, - { id: "b1", price: "98", size: 5, state: "" }, + { id: "b2", price: "99", size: 3, state: "new" }, + { id: "b1", price: "98", size: 5, state: "" }, ], }, }, { instruction: "market_order", - description: "A taker sends a market buy order for 3 lots. It matches against the best ask (101) immediately and does not rest on the book. The ask at 101 is fully consumed.", + description: + "A taker sends a market buy order for 3 lots. It matches against the best ask (101) immediately and does not rest on the book. The ask at 101 is fully consumed.", spread: "4 ticks", book: { asks: [ @@ -131,37 +160,35 @@ const steps = [ { id: "a1", price: "102", size: 5, state: "" }, ], bids: [ - { id: "b2", price: "99", size: 3, state: "" }, - { id: "b1", price: "98", size: 5, state: "" }, + { id: "b2", price: "99", size: 3, state: "" }, + { id: "b1", price: "98", size: 5, state: "" }, ], }, }, { instruction: "cancel_order", - description: "The first maker cancels their bid at 98. The order is removed from the book and their reserved quote tokens return to their available balance.", + description: + "The first maker cancels their bid at 98. The order is removed from the book and their reserved quote tokens return to their available balance.", spread: "3 ticks", book: { - asks: [ - { id: "a1", price: "102", size: 5, state: "" }, - ], + asks: [{ id: "a1", price: "102", size: 5, state: "" }], bids: [ - { id: "b2", price: "99", size: 3, state: "" }, - { id: "b1", price: "98", size: 5, state: "cancelled" }, + { id: "b2", price: "99", size: 3, state: "" }, + { id: "b1", price: "98", size: 5, state: "cancelled" }, ], }, }, { instruction: "batch_replace", - description: "The second maker uses batch_replace to cancel their remaining orders and post fresh quotes atomically — new ask at 101 for 4 lots, new bid at 99 for 4 lots. No gap between cancel and post.", + description: + "The second maker uses batch_replace to cancel their remaining orders and post fresh quotes atomically — new ask at 101 for 4 lots, new bid at 99 for 4 lots. No gap between cancel and post.", spread: "2 ticks", book: { asks: [ { id: "a3", price: "101", size: 4, state: "new" }, { id: "a1", price: "102", size: 5, state: "" }, ], - bids: [ - { id: "b3", price: "99", size: 4, state: "new" }, - ], + bids: [{ id: "b3", price: "99", size: 4, state: "new" }], }, }, ]; @@ -283,7 +310,7 @@ const steps = [ .obv-order.filled { opacity: 0.4; text-decoration: line-through; - border-color: #0EA5E9; + border-color: #0ea5e9; background: rgba(14, 165, 233, 0.08); } @@ -311,8 +338,12 @@ const steps = [ transition: width 0.3s ease; } -.ask-bar { background: rgba(239, 68, 68, 0.5); } -.bid-bar { background: rgba(34, 197, 94, 0.5); } +.ask-bar { + background: rgba(239, 68, 68, 0.5); +} +.bid-bar { + background: rgba(34, 197, 94, 0.5); +} .obv-size { font-size: 12px; @@ -331,7 +362,7 @@ const steps = [ .obv-order.filled .obv-state-tag { background: rgba(14, 165, 233, 0.15); - color: #0EA5E9; + color: #0ea5e9; } .obv-order.cancelled .obv-state-tag { diff --git a/docs/src/architecture/overview.md b/docs/src/architecture/overview.md index d00940a6..56d2857a 100644 --- a/docs/src/architecture/overview.md +++ b/docs/src/architecture/overview.md @@ -56,20 +56,20 @@ This gives the team precise control over compute unit usage and avoids Anchor's `program/src/` is organized into four folders: -| Folder | Purpose | -|---|---| -| `instructions/` | One file per instruction — the handler logic | -| `context/` | One file per instruction — account validation and loading | -| `shared/` | Shared utilities used across multiple instructions | -| `validation/` | Safety contracts and constraint checking | +| Folder | Purpose | +| --------------- | --------------------------------------------------------- | +| `instructions/` | One file per instruction — the handler logic | +| `context/` | One file per instruction — account validation and loading | +| `shared/` | Shared utilities used across multiple instructions | +| `validation/` | Safety contracts and constraint checking | Plus top-level files: -| File | Purpose | -|---|---| -| `entrypoint.rs` | Routes incoming instructions to handlers | -| `events.rs` | Event type definitions emitted by the program | -| `lib.rs` | Crate root | +| File | Purpose | +| --------------- | --------------------------------------------- | +| `entrypoint.rs` | Routes incoming instructions to handlers | +| `events.rs` | Event type definitions emitted by the program | +| `lib.rs` | Crate root | ## The interface crate diff --git a/docs/src/architecture/program-structure.md b/docs/src/architecture/program-structure.md index 17e141f3..480f60f4 100644 --- a/docs/src/architecture/program-structure.md +++ b/docs/src/architecture/program-structure.md @@ -83,18 +83,18 @@ Removes processed events from the market's event queue and reclaims space. The q ## Instruction summary -| Instruction | Description | -|---|---| -| `register_market` | Create a new market | -| `expand_market` | Grow order book capacity | -| `close_seat` | Close a trader's seat | -| `deposit` | Deposit base or quote tokens | -| `withdraw` | Withdraw settled funds | -| `post_order` | Post a limit order | -| `cancel_order` | Cancel a resting order | -| `batch_replace` | Cancel + post atomically | -| `market_order` | Execute a market order | -| `flush_events` | Clear processed events | +| Instruction | Description | +| ----------------- | ---------------------------- | +| `register_market` | Create a new market | +| `expand_market` | Grow order book capacity | +| `close_seat` | Close a trader's seat | +| `deposit` | Deposit base or quote tokens | +| `withdraw` | Withdraw settled funds | +| `post_order` | Post a limit order | +| `cancel_order` | Cancel a resting order | +| `batch_replace` | Cancel + post atomically | +| `market_order` | Execute a market order | +| `flush_events` | Clear processed events | ## Generating internal documentation diff --git a/docs/src/introduction/core-concepts.md b/docs/src/introduction/core-concepts.md index 50311ad8..1593583c 100644 --- a/docs/src/introduction/core-concepts.md +++ b/docs/src/introduction/core-concepts.md @@ -49,12 +49,12 @@ Before you can post orders, you deposit base or quote tokens into the program. T ## Market Order vs. Post Order -| | `post_order` | `market_order` | -| ---------------- | ---------------------- | --------------------------------- | -| Type | Limit order | Market order | -| Rests on book? | Yes, until filled or cancelled | No — executes immediately | -| Price control | Exact price specified | Fills at best available | -| Common use | Market making | Taker execution | +| | `post_order` | `market_order` | +| -------------- | ------------------------------ | ------------------------- | +| Type | Limit order | Market order | +| Rests on book? | Yes, until filled or cancelled | No — executes immediately | +| Price control | Exact price specified | Fills at best available | +| Common use | Market making | Taker execution | ## Batch Replace diff --git a/docs/src/introduction/what-is-dropset.md b/docs/src/introduction/what-is-dropset.md index b69b149a..b1b7e856 100644 --- a/docs/src/introduction/what-is-dropset.md +++ b/docs/src/introduction/what-is-dropset.md @@ -19,13 +19,13 @@ Solana's combination of high throughput and low latency makes it one of the few Dropset is structured as a Rust workspace with clearly separated concerns: -| Component | What it does | -|---|---| -| `dropset-program` | The on-chain Solana program | -| `dropset-interface` | Client-agnostic instruction schemas and account types | +| Component | What it does | +| -------------------- | ------------------------------------------------------- | +| `dropset-program` | The on-chain Solana program | +| `dropset-interface` | Client-agnostic instruction schemas and account types | | `instruction-macros` | Proc macros that generate typed builders and validators | -| `dropset-client` | Rust client for local testing and RPC integration | -| `ts-sdk` | TypeScript SDK for building web and bot clients | -| `services` | Experimental faucet, maker-bot, and taker-bot | +| `dropset-client` | Rust client for local testing and RPC integration | +| `ts-sdk` | TypeScript SDK for building web and bot clients | +| `services` | Experimental faucet, maker-bot, and taker-bot | The next section walks through how these pieces connect at the architecture level. diff --git a/docs/src/program/instructions.md b/docs/src/program/instructions.md index 6afdbcc2..0b85ff53 100644 --- a/docs/src/program/instructions.md +++ b/docs/src/program/instructions.md @@ -11,6 +11,7 @@ Filter by category to focus on a specific area of the protocol. **CU** — the approximate compute unit cost of this instruction on a Solana localnet benchmark. See [Benchmarks](/benchmarks/) for full comparisons against Phoenix and Manifest. **Accounts** — every account the instruction requires, with mutability and signer flags: + - `mut` — the instruction writes to this account - `signer` — this account must sign the transaction - `PDA` — this is a program-derived address, computed deterministically from seeds @@ -21,12 +22,12 @@ Filter by category to focus on a specific area of the protocol. All PDAs in Dropset are derived from seeds defined in `dropset-interface/`, so any client can compute them without fetching first: -| Account | Seeds | -|---|---| -| Seat | `[market, trader]` | -| Trader balance | `[market, trader]` | -| Base vault | `[market, "base"]` | -| Quote vault | `[market, "quote"]` | +| Account | Seeds | +| -------------- | ------------------- | +| Seat | `[market, trader]` | +| Trader balance | `[market, trader]` | +| Base vault | `[market, "base"]` | +| Quote vault | `[market, "quote"]` | ## Further reading diff --git a/docs/src/quickstart/getting-started.md b/docs/src/quickstart/getting-started.md index 6ad8bf9c..71203249 100644 --- a/docs/src/quickstart/getting-started.md +++ b/docs/src/quickstart/getting-started.md @@ -4,12 +4,12 @@ This guide gets you from zero to running the Dropset program locally against a S ## Prerequisites -| Tool | Version | Install | -|---|---|---| -| Rust | stable | [rustup.rs](https://rustup.rs) | -| Solana CLI | latest | [solana.com/docs](https://solana.com/docs/intro/installation) | -| Node.js | see `.nvmrc` | [nodejs.org](https://nodejs.org) | -| pnpm | latest | `npm install -g pnpm` | +| Tool | Version | Install | +| ---------- | ------------ | ------------------------------------------------------------- | +| Rust | stable | [rustup.rs](https://rustup.rs) | +| Solana CLI | latest | [solana.com/docs](https://solana.com/docs/intro/installation) | +| Node.js | see `.nvmrc` | [nodejs.org](https://nodejs.org) | +| pnpm | latest | `npm install -g pnpm` | Check your versions: diff --git a/docs/src/sdk/connect-to-market.md b/docs/src/sdk/connect-to-market.md index fd819bc7..23de298c 100644 --- a/docs/src/sdk/connect-to-market.md +++ b/docs/src/sdk/connect-to-market.md @@ -15,10 +15,10 @@ import type { MarketViewAll } from "@dropset/ts-sdk"; ```typescript type MarketViewAll = { - header: MarketHeader; // Market config: mints, tick size, lot size - seats: MarketSeatView[]; // All registered traders on this market - bids: OrderView[]; // All resting buy orders, linked-list order - asks: OrderView[]; // All resting sell orders, linked-list order + header: MarketHeader; // Market config: mints, tick size, lot size + seats: MarketSeatView[]; // All registered traders on this market + bids: OrderView[]; // All resting buy orders, linked-list order + asks: OrderView[]; // All resting sell orders, linked-list order users: Map; // Per-trader seat + orders }; ``` diff --git a/docs/src/sdk/post-order.md b/docs/src/sdk/post-order.md index a6914a85..8a15cbe9 100644 --- a/docs/src/sdk/post-order.md +++ b/docs/src/sdk/post-order.md @@ -27,7 +27,7 @@ const rpc = createSolanaRpc("https://api.devnet.solana.com"); // Your addresses const marketAddress = address("MARKET_ADDRESS"); const traderAddress = address("TRADER_ADDRESS"); -const seatAddress = address("SEAT_ADDRESS"); // PDA: market + trader +const seatAddress = address("SEAT_ADDRESS"); // PDA: market + trader const balanceAddress = address("BALANCE_ADDRESS"); // PDA: market + trader // Market decimal configuration @@ -47,7 +47,7 @@ const ix = getPostOrderInstruction({ trader: traderAddress, seat: seatAddress, traderBalance: balanceAddress, - side: 0, // 0 = bid, 1 = ask + side: 0, // 0 = bid, 1 = ask ...orderArgs, }); @@ -60,18 +60,18 @@ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); ## Order sides -| Value | Side | Meaning | -|---|---|---| -| `0` | Bid | Buy order — you're offering quote tokens to buy base tokens | -| `1` | Ask | Sell order — you're offering base tokens to receive quote tokens | +| Value | Side | Meaning | +| ----- | ---- | ---------------------------------------------------------------- | +| `0` | Bid | Buy order — you're offering quote tokens to buy base tokens | +| `1` | Ask | Sell order — you're offering base tokens to receive quote tokens | ## The `post_order` instruction accounts -| Account | Description | -|---|---| -| `market` | The market account (writable) | -| `trader` | The trader's public key (signer) | -| `seat` | The trader's seat PDA on this market | +| Account | Description | +| --------------- | -------------------------------------------------- | +| `market` | The market account (writable) | +| `trader` | The trader's public key (signer) | +| `seat` | The trader's seat PDA on this market | | `traderBalance` | The trader's balance PDA on this market (writable) | ## What happens on-chain diff --git a/docs/src/sdk/price-utils.md b/docs/src/sdk/price-utils.md index 0396afbd..eceaefea 100644 --- a/docs/src/sdk/price-utils.md +++ b/docs/src/sdk/price-utils.md @@ -28,11 +28,12 @@ console.log(usdcUiAmount.toString()); // "5.5" ``` **Signature:** + ```typescript function atomsToUiAmount( atomsAmount: bigint, mintDecimals: number | bigint, -): Decimal +): Decimal; ``` --- @@ -52,12 +53,13 @@ console.log(atomsPrice.toString()); // "0.0000425" (adjusted for decimal differe ``` **Signature:** + ```typescript function uiPriceToAtomsPrice( uiPrice: Decimal, baseDecimals: number | bigint, quoteDecimals: number | bigint, -): Decimal +): Decimal; ``` The formula applied is: `atomsPrice = uiPrice × 10^(quoteDecimals − baseDecimals)` @@ -92,6 +94,7 @@ console.log(args); ``` **Signature:** + ```typescript function toOrderInfoArgs( price: Decimal, @@ -101,7 +104,7 @@ function toOrderInfoArgs( baseScalar: U64; baseExponentBiased: U8; quoteExponentBiased: U8; -} +}; ``` ::: warning @@ -124,8 +127,9 @@ console.log(decodedPrice.toString()); // e.g. "42.5" ``` **Signature:** + ```typescript -function encodedU32ToDecimal(encodedU32: number | bigint): Decimal +function encodedU32ToDecimal(encodedU32: number | bigint): Decimal; ``` --- @@ -135,7 +139,7 @@ function encodedU32ToDecimal(encodedU32: number | bigint): Decimal Low-level utility that converts an unbiased exponent to the biased format the program uses. You generally won't call this directly — `toOrderInfoArgs` handles it internally. ```typescript -function toBiasedExponent(unbiased: number): U8 +function toBiasedExponent(unbiased: number): U8; ``` Throws `PriceError.InvalidBiasedExponent` if the value is outside the supported range. @@ -153,12 +157,12 @@ import { } from "@dropset/ts-sdk"; // Market config (from market header) -const BASE_DECIMALS = 9; // e.g. SOL +const BASE_DECIMALS = 9; // e.g. SOL const QUOTE_DECIMALS = 6; // e.g. USDC // Step 1 — Define your order parameters in human terms -const uiPrice = new Decimal("42.50"); // 42.50 USDC per SOL -const orderSizeBaseAtoms = 1_000_000_000n; // 1 SOL +const uiPrice = new Decimal("42.50"); // 42.50 USDC per SOL +const orderSizeBaseAtoms = 1_000_000_000n; // 1 SOL // Step 2 — Convert UI price to atoms price const atomsPrice = uiPriceToAtomsPrice(uiPrice, BASE_DECIMALS, QUOTE_DECIMALS); diff --git a/dropset-alpha b/dropset-alpha deleted file mode 160000 index 528f86af..00000000 --- a/dropset-alpha +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 528f86afb1849782f3073b689173057ec94e2520