commit 3f36194a10da46c0af5a1d5e787895e981f30dfd Author: Thomas Silkjær Date: Thu Jul 3 09:24:20 2025 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..16d54bb --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store + +# jetbrains setting folder +.idea/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..22a1505 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,4 @@ +{ + "recommendations": ["astro-build.astro-vscode"], + "unwantedRecommendations": [] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..d642209 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,11 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "command": "./node_modules/.bin/astro dev", + "name": "Development server", + "request": "launch", + "type": "node-terminal" + } + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..53e3887 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +# Xahau website and documentation + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/Xahau/xahau-web/tree/main) +[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/sandbox/github/Xahau/xahau-web/tree/main) + +## Project Structure + +Inside the project, these are the most relevant folders for collaboration + +```text +/ +├── public/ +├── src/ +│ └── assets/ +│ └── ecosystem-logos/ +│ └── content/ +│ └── docs/ +│ └── docs/ +│ └── pages/ +│ └── schemas/ +``` + +The project is using `.mdx` files for content, which combines markdown with JSX. When editing content, look at the existing files for reference on how various elements are used, such as `LinkButton`, `LinkCard`, `Aside` etc. + +## Commands + +All commands are run from the root of the project, from a terminal: + +| Command | Action | +| :------------------------ | :----------------------------------------------- | +| `npm install` | Installs dependencies | +| `npm run dev` | Starts local dev server at `localhost:4321` | +| `npm run build` | Build your production site to `./dist/` | +| `npm run preview` | Preview your build locally, before deploying | +| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | +| `npm run astro -- --help` | Get help using the Astro CLI | \ No newline at end of file diff --git a/astro.config.mjs b/astro.config.mjs new file mode 100644 index 0000000..dcdbcaa --- /dev/null +++ b/astro.config.mjs @@ -0,0 +1,300 @@ +// @ts-check +import { defineConfig } from 'astro/config'; +import react from '@astrojs/react'; +import mdx from '@astrojs/mdx'; +import tailwindcss from '@tailwindcss/vite'; +import starlight from '@astrojs/starlight'; +import starlightOpenAPI, { openAPISidebarGroups } from 'starlight-openapi' + +// https://astro.build/config +export default defineConfig({ + integrations: [ + react(), + starlight({ + title: 'Xahau Docs', + description: 'Documentation for the Xahau blockchain', + tableOfContents: { + minHeadingLevel: 1, + maxHeadingLevel: 3, + }, + editLink: { + baseUrl: 'https://github.com/Xahau/xahau-web/edit/main/', + }, + components: { + PageFrame: './src/layouts/DocsLayout.astro', + TwoColumnContent: './src/components/DocsTwoColumnContent.astro', + PageSidebar: './src/components/DocsPageSidebar.astro', + Sidebar: './src/components/DocsSidebar.astro', + MobileMenuToggle: './src/components/DocsMobileMenuToggle.astro', + ThemeProvider: './src/components/DocsForceLightTheme.astro', + }, + plugins: [ + starlightOpenAPI([ + { + base: 'docs/data-apis/data-api', + schema: './src/schemas/dataapi.json', + sidebar: { + label: 'Xahau Data API' + } + }, + ]), + ], + sidebar: [ + { + label: 'Get started', + items: [ + 'docs', + 'docs/what-is-different' + ], + }, + { + label: 'Features', + items: [ + 'docs/features/public-nodes-rpc', + 'docs/features/amendments', + { + label: 'Transaction Signing', + autogenerate: { directory: 'docs/features/transaction-signing' }, + collapsed: true + }, + { + label: 'Developer Tooling', + autogenerate: { directory: 'docs/features/developer-tooling' }, + collapsed: true + }, + { + label: 'HTTP / WebSocket APIs', + autogenerate: { directory: 'docs/features/http-websocket-apis' }, + collapsed: true + }, + { + label: 'Network Features', + autogenerate: { directory: 'docs/features/network-features' }, + collapsed: true + }, + 'docs/features/faucet-and-explorer', + 'docs/features/balance-adjustments', + 'docs/features/governance-game', + 'docs/features/burn-2-mint', + 'docs/features/versioning-process', + ] + }, + { + label: 'Protocol Reference', + items: [ + { + label: 'Transactions', + collapsed: true, + items: [ + 'docs/protocol-reference/transactions', + { + label: 'Transaction Types', + autogenerate: { directory: 'docs/protocol-reference/transactions/transaction-types' }, + collapsed: true, + }, + { + label: 'Pseudo Transaction Types', + autogenerate: { directory: 'docs/protocol-reference/transactions/pseudo-transaction-types' }, + collapsed: true, + }, + { + label: 'Transaction Results', + autogenerate: { directory: 'docs/protocol-reference/transactions/transaction-results' }, + collapsed: true, + }, + 'docs/protocol-reference/transactions/transaction-common-fields', + 'docs/protocol-reference/transactions/transaction-metadata', + ] + }, + { + label: 'Ledger Data', + collapsed: true, + items: [ + 'docs/protocol-reference/ledger-data', + { + label: 'Ledger Objects Types', + autogenerate: { directory: 'docs/protocol-reference/ledger-data/ledger-objects-types' }, + collapsed: true, + }, + 'docs/protocol-reference/ledger-data/ledger-header', + 'docs/protocol-reference/ledger-data/ledger-object-ids', + ] + }, + { + label: 'Data Types', + collapsed: true, + items: [ + 'docs/protocol-reference/data-types', + 'docs/protocol-reference/data-types/currency-formats', + 'docs/protocol-reference/data-types/base-58-encodings', + ] + }, + 'docs/protocol-reference/binary-format', + ] + }, + { + label: 'Hooks', + items: [ + 'docs/hooks', + { + label: 'Concepts', + collapsed: true, + items: [ + 'docs/hooks/concepts/introduction', + 'docs/hooks/concepts/terminology', + 'docs/hooks/concepts/loops-and-guarding', + 'docs/hooks/concepts/compiling-hooks', + 'docs/hooks/concepts/chaining', + 'docs/hooks/concepts/weak-and-strong', + 'docs/hooks/concepts/collect-call', + 'docs/hooks/concepts/sethook-transaction', + 'docs/hooks/concepts/parameters', + 'docs/hooks/concepts/namespaces', + 'docs/hooks/concepts/grants', + 'docs/hooks/concepts/hookon-field', + 'docs/hooks/concepts/reference-counted-hook-definitions', + 'docs/hooks/concepts/hook-fees', + 'docs/hooks/concepts/execution-metadata', + 'docs/hooks/concepts/debugging-hooks', + 'docs/hooks/concepts/state-management', + 'docs/hooks/concepts/slots-and-keylets', + 'docs/hooks/concepts/floating-point-numbers-xfl', + 'docs/hooks/concepts/emitted-transactions', + 'docs/hooks/concepts/serialized-objects', + ] + }, + { + label: 'Functions', + collapsed: true, + items: [ + { + label: 'Overview', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/overview' }, + }, + { + label: 'Developer Defined', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/developer-defined' }, + }, + { + label: 'Control', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/control' }, + }, + { + label: 'Utilities', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/utilities' }, + }, + { + label: 'Serialization', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/serialization' }, + }, + { + label: 'Emitted Transaction', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/emitted-transaction' }, + }, + { + label: 'Float', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/float' }, + }, + { + label: 'Ledger', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/ledger' }, + }, + { + label: 'Hook Context', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/hook-context' }, + }, + { + label: 'Slot', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/slot' }, + }, + { + label: 'State', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/state' }, + }, + { + label: 'Trace (Debug)', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/trace-debug' }, + }, + { + label: 'Originating Transaction', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/originating-transaction' }, + }, + { + label: 'WebSocket APIs', + collapsed: true, + autogenerate: { directory: 'docs/hooks/functions/websocket-apis' }, + }, + ] + }, + ] + }, + { + label: 'Data APIs', + items: [ + 'docs/data-apis', + ...openAPISidebarGroups + ] + }, + { + label: 'Compliance', + items: [ + 'docs/compliance/security-audit', + 'docs/compliance/responsible-disclosure', + ] + }, + { + label: 'Infrastructure', + items: [ + 'docs/infrastructure/node-requirements', + { + label: 'Running a Node', + collapsed: true, + items: [ + 'docs/infrastructure/running-a-node/running-a-mainnet-node', + 'docs/infrastructure/running-a-node/running-a-testnet-node', + ] + }, + { + label: 'Building Xahau (Dev)', + collapsed: true, + items: [ + 'docs/infrastructure/building-xahau', + 'docs/infrastructure/building-xahau/ubuntu-22-04', + 'docs/infrastructure/building-xahau/mac-os-13-5-2', + ] + } + ] + }, + { + label: 'Resources', + items: [ + 'docs/resources/whitepaper', + 'docs/resources/media-kit', + ], + }, + { + label: 'Support', + autogenerate: { directory: 'docs/support' }, + }, + ], + }), + mdx() + ], + vite: { + plugins: [tailwindcss()], + }, + site: 'https://www.xahau.network/' +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..055b767 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,7465 @@ +{ + "name": "helpless-hubble", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "helpless-hubble", + "version": "0.0.1", + "dependencies": { + "@astrojs/mdx": "^4.3.0", + "@astrojs/react": "^4.3.0", + "@astrojs/starlight": "^0.34.4", + "@astrojs/starlight-tailwind": "^4.0.1", + "@headlessui/react": "^2.2.4", + "@heroicons/react": "^2.2.0", + "@tailwindcss/vite": "^4.1.11", + "astro": "^5.10.1", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "starlight-openapi": "^0.19.1", + "tailwindcss": "^4.1.11", + "vanilla-cookieconsent": "^3.1.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "license": "MIT" + }, + "node_modules/@astrojs/compiler": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.12.2.tgz", + "integrity": "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw==" + }, + "node_modules/@astrojs/internal-helpers": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.6.1.tgz", + "integrity": "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A==" + }, + "node_modules/@astrojs/markdown-remark": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.2.tgz", + "integrity": "sha512-bO35JbWpVvyKRl7cmSJD822e8YA8ThR/YbUsciWNA7yTcqpIAL2hJDToWP5KcZBWxGT6IOdOkHSXARSNZc4l/Q==", + "dependencies": { + "@astrojs/internal-helpers": "0.6.1", + "@astrojs/prism": "3.3.0", + "github-slugger": "^2.0.0", + "hast-util-from-html": "^2.0.3", + "hast-util-to-text": "^4.0.2", + "import-meta-resolve": "^4.1.0", + "js-yaml": "^4.1.0", + "mdast-util-definitions": "^6.0.0", + "rehype-raw": "^7.0.0", + "rehype-stringify": "^10.0.1", + "remark-gfm": "^4.0.1", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-smartypants": "^3.0.2", + "shiki": "^3.2.1", + "smol-toml": "^1.3.1", + "unified": "^11.0.5", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1", + "vfile": "^6.0.3" + } + }, + "node_modules/@astrojs/mdx": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.0.tgz", + "integrity": "sha512-OGX2KvPeBzjSSKhkCqrUoDMyzFcjKt5nTE5SFw3RdoLf0nrhyCXBQcCyclzWy1+P+XpOamn+p+hm1EhpCRyPxw==", + "dependencies": { + "@astrojs/markdown-remark": "6.3.2", + "@mdx-js/mdx": "^3.1.0", + "acorn": "^8.14.1", + "es-module-lexer": "^1.6.0", + "estree-util-visit": "^2.0.0", + "hast-util-to-html": "^9.0.5", + "kleur": "^4.1.5", + "rehype-raw": "^7.0.0", + "remark-gfm": "^4.0.1", + "remark-smartypants": "^3.0.2", + "source-map": "^0.7.4", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.3" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + }, + "peerDependencies": { + "astro": "^5.0.0" + } + }, + "node_modules/@astrojs/prism": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", + "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", + "dependencies": { + "prismjs": "^1.30.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@astrojs/react": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.3.0.tgz", + "integrity": "sha512-N02aj52Iezn69qHyx5+XvPqgsPMEnel9mI5JMbGiRMTzzLMuNaxRVoQTaq2024Dpr7BLsxCjqMkNvelqMDhaHA==", + "dependencies": { + "@vitejs/plugin-react": "^4.4.1", + "ultrahtml": "^1.6.0", + "vite": "^6.3.5" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + }, + "peerDependencies": { + "@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0", + "@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0", + "react": "^17.0.2 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@astrojs/sitemap": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.4.1.tgz", + "integrity": "sha512-VjZvr1e4FH6NHyyHXOiQgLiw94LnCVY4v06wN/D0gZKchTMkg71GrAHJz81/huafcmavtLkIv26HnpfDq6/h/Q==", + "dependencies": { + "sitemap": "^8.0.0", + "stream-replace-string": "^2.0.0", + "zod": "^3.24.2" + } + }, + "node_modules/@astrojs/starlight": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.34.4.tgz", + "integrity": "sha512-NfQ6S2OaDG8aaiE+evVxSMpgqMkXPLa/yCpzG340EX2pRzFxPeTSvpei3Uz9KouevXRCctjHSItKjuZP+2syrQ==", + "dependencies": { + "@astrojs/markdown-remark": "^6.3.1", + "@astrojs/mdx": "^4.2.3", + "@astrojs/sitemap": "^3.3.0", + "@pagefind/default-ui": "^1.3.0", + "@types/hast": "^3.0.4", + "@types/js-yaml": "^4.0.9", + "@types/mdast": "^4.0.4", + "astro-expressive-code": "^0.41.1", + "bcp-47": "^2.1.0", + "hast-util-from-html": "^2.0.1", + "hast-util-select": "^6.0.2", + "hast-util-to-string": "^3.0.0", + "hastscript": "^9.0.0", + "i18next": "^23.11.5", + "js-yaml": "^4.1.0", + "klona": "^2.0.6", + "mdast-util-directive": "^3.0.0", + "mdast-util-to-markdown": "^2.1.0", + "mdast-util-to-string": "^4.0.0", + "pagefind": "^1.3.0", + "rehype": "^13.0.1", + "rehype-format": "^5.0.0", + "remark-directive": "^3.0.0", + "ultrahtml": "^1.6.0", + "unified": "^11.0.5", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.2" + }, + "peerDependencies": { + "astro": "^5.5.0" + } + }, + "node_modules/@astrojs/starlight-tailwind": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@astrojs/starlight-tailwind/-/starlight-tailwind-4.0.1.tgz", + "integrity": "sha512-AOOEWTGqJ7fG66U04xTmZQZ40oZnUYe4Qljpr+No88ozKywtsD1DiXOrGTeHCnZu0hRtMbRtBGB1fZsf0L62iw==", + "peerDependencies": { + "@astrojs/starlight": ">=0.34.0", + "tailwindcss": "^4.0.0" + } + }, + "node_modules/@astrojs/telemetry": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", + "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", + "dependencies": { + "ci-info": "^4.2.0", + "debug": "^4.4.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "is-docker": "^3.0.0", + "is-wsl": "^3.1.0", + "which-pm-runs": "^1.1.0" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.27.7.tgz", + "integrity": "sha512-xgu/ySj2mTiUFmdE9yCMfBxLp4DHd5DwmbbD05YAuICfodYT3VvRxbrh81LGQ/8UpSdtMdfKMn3KouYDX59DGQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.27.7.tgz", + "integrity": "sha512-BU2f9tlKQ5CAthiMIgpzAh4eDTLWo1mqi9jqE2OxMG0E/OM199VJt2q8BztTxpnSW0i1ymdwLXRJnYzvDM5r2w==", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.27.3", + "@babel/helpers": "^7.27.6", + "@babel/parser": "^7.27.7", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.27.7", + "@babel/types": "^7.27.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.5.tgz", + "integrity": "sha512-ZGhA37l0e/g2s1Cnzdix0O3aLYm66eF8aufiVteOgnwxgnRP8GoyMj7VWsgWnQbVKXyge7hqrFh2K2TQM6t1Hw==", + "dependencies": { + "@babel/parser": "^7.27.5", + "@babel/types": "^7.27.3", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz", + "integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "engines": { + "node": ">=6.9.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==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.6.tgz", + "integrity": "sha512-muE8Tt8M22638HU31A3CgfSUciwz1fhATfoVai05aPXGor//CdWDCbnlY1yvBPo07njuVOCNGCSp/GTt12lIug==", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.7.tgz", + "integrity": "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q==", + "dependencies": { + "@babel/types": "^7.27.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz", + "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.7.tgz", + "integrity": "sha512-X6ZlfR/O/s5EQ/SnUSLzr+6kGnkg8HXGMzpgsMsrJVcfDtH1vIp6ctCN4eZ1LS5c0+te5Cb6Y514fASjMRJ1nw==", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.27.5", + "@babel/parser": "^7.27.7", + "@babel/template": "^7.27.2", + "@babel/types": "^7.27.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.7.tgz", + "integrity": "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw==", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@capsizecss/unpack": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-2.4.0.tgz", + "integrity": "sha512-GrSU71meACqcmIUxPYOJvGKF0yryjN/L1aCuE9DViCTJI7bfkjgYDPD1zbNDcINJwSSP6UaBZY9GAbYDO7re0Q==", + "dependencies": { + "blob-to-buffer": "^1.2.8", + "cross-fetch": "^3.0.4", + "fontkit": "^2.0.2" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.1.0.tgz", + "integrity": "sha512-WyOx8cJQ+FQus4Mm4uPIZA64gbk3Wxh0so5Lcii0aJifqwoVOlfFtorjLE0Hen4OYyHZMXDWqMmaQemBhgxFRQ==", + "engines": { + "node": ">=14" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", + "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", + "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", + "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", + "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", + "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", + "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", + "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", + "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", + "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", + "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", + "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", + "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", + "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", + "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", + "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", + "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", + "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", + "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", + "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", + "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", + "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", + "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", + "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", + "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", + "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@expressive-code/core": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.2.tgz", + "integrity": "sha512-AJW5Tp9czbLqKMzwudL9Rv4js9afXBxkSGLmCNPq1iRgAYcx9NkTPJiSNCesjKRWoVC328AdSu6fqrD22zDgDg==", + "dependencies": { + "@ctrl/tinycolor": "^4.0.4", + "hast-util-select": "^6.0.2", + "hast-util-to-html": "^9.0.1", + "hast-util-to-text": "^4.0.1", + "hastscript": "^9.0.0", + "postcss": "^8.4.38", + "postcss-nested": "^6.0.1", + "unist-util-visit": "^5.0.0", + "unist-util-visit-parents": "^6.0.1" + } + }, + "node_modules/@expressive-code/plugin-frames": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.2.tgz", + "integrity": "sha512-pfy0hkJI4nbaONjmksFDcuHmIuyPTFmi1JpABe4q2ajskiJtfBf+WDAL2pg595R9JNoPrrH5+aT9lbkx2noicw==", + "dependencies": { + "@expressive-code/core": "^0.41.2" + } + }, + "node_modules/@expressive-code/plugin-shiki": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.2.tgz", + "integrity": "sha512-xD4zwqAkDccXqye+235BH5bN038jYiSMLfUrCOmMlzxPDGWdxJDk5z4uUB/aLfivEF2tXyO2zyaarL3Oqht0fQ==", + "dependencies": { + "@expressive-code/core": "^0.41.2", + "shiki": "^3.2.2" + } + }, + "node_modules/@expressive-code/plugin-text-markers": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.2.tgz", + "integrity": "sha512-JFWBz2qYxxJOJkkWf96LpeolbnOqJY95TvwYc0hXIHf9oSWV0h0SY268w/5N3EtQaD9KktzDE+VIVwb9jdb3nw==", + "dependencies": { + "@expressive-code/core": "^0.41.2" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", + "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", + "dependencies": { + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.1.tgz", + "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", + "dependencies": { + "@floating-ui/core": "^1.7.1", + "@floating-ui/utils": "^0.2.9" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.26.28", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.28.tgz", + "integrity": "sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw==", + "dependencies": { + "@floating-ui/react-dom": "^2.1.2", + "@floating-ui/utils": "^0.2.8", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.3.tgz", + "integrity": "sha512-huMBfiU9UnQ2oBwIhgzyIiSpVgvlDstU8CX0AF+wS+KzmYMs0J2a3GwuFHV1Lz+jlrQGeC1fF+Nv0QoumyV0bA==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", + "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==" + }, + "node_modules/@headlessui/react": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-2.2.4.tgz", + "integrity": "sha512-lz+OGcAH1dK93rgSMzXmm1qKOJkBUqZf1L4M8TWLNplftQD3IkoEDdUFNfAn4ylsN6WOTVtWaLmvmaHOUk1dTA==", + "dependencies": { + "@floating-ui/react": "^0.26.16", + "@react-aria/focus": "^3.20.2", + "@react-aria/interactions": "^3.25.0", + "@tanstack/react-virtual": "^3.13.9", + "use-sync-external-store": "^1.5.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/@heroicons/react": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.2.0.tgz", + "integrity": "sha512-LMcepvRaS9LYHJGsF0zzmgKCUim/X3N/DQKc4jepAXJ7l8QxJ1PmxJzqplF2Z3FE4PqBAIGyJAQ/w4B5dsqbtQ==", + "peerDependencies": { + "react": ">= 16 || ^19.0.0-rc" + } + }, + "node_modules/@humanwhocodes/momoa": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/momoa/-/momoa-2.0.4.tgz", + "integrity": "sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==", + "license": "Apache-2.0", + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "license": "MIT" + }, + "node_modules/@mdx-js/mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz", + "integrity": "sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdx": "^2.0.0", + "collapse-white-space": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-util-scope": "^1.0.0", + "estree-walker": "^3.0.0", + "hast-util-to-jsx-runtime": "^2.0.0", + "markdown-extensions": "^2.0.0", + "recma-build-jsx": "^1.0.0", + "recma-jsx": "^1.0.0", + "recma-stringify": "^1.0.0", + "rehype-recma": "^1.0.0", + "remark-mdx": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.0.0", + "source-map": "^0.7.0", + "unified": "^11.0.0", + "unist-util-position-from-estree": "^2.0.0", + "unist-util-stringify-position": "^4.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/@oslojs/encoding": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", + "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==" + }, + "node_modules/@pagefind/darwin-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.3.0.tgz", + "integrity": "sha512-365BEGl6ChOsauRjyVpBjXybflXAOvoMROw3TucAROHIcdBvXk9/2AmEvGFU0r75+vdQI4LJdJdpH4Y6Yqaj4A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/darwin-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.3.0.tgz", + "integrity": "sha512-zlGHA23uuXmS8z3XxEGmbHpWDxXfPZ47QS06tGUq0HDcZjXjXHeLG+cboOy828QIV5FXsm9MjfkP5e4ZNbOkow==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@pagefind/default-ui": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.3.0.tgz", + "integrity": "sha512-CGKT9ccd3+oRK6STXGgfH+m0DbOKayX6QGlq38TfE1ZfUcPc5+ulTuzDbZUnMo+bubsEOIypm4Pl2iEyzZ1cNg==" + }, + "node_modules/@pagefind/linux-arm64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.3.0.tgz", + "integrity": "sha512-8lsxNAiBRUk72JvetSBXs4WRpYrQrVJXjlRRnOL6UCdBN9Nlsz0t7hWstRk36+JqHpGWOKYiuHLzGYqYAqoOnQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/linux-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.3.0.tgz", + "integrity": "sha512-hAvqdPJv7A20Ucb6FQGE6jhjqy+vZ6pf+s2tFMNtMBG+fzcdc91uTw7aP/1Vo5plD0dAOHwdxfkyw0ugal4kcQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@pagefind/windows-x64": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.3.0.tgz", + "integrity": "sha512-BR1bIRWOMqkf8IoU576YDhij1Wd/Zf2kX/kCI0b2qzCKC8wcc2GQJaaRMCpzvCCrmliO4vtJ6RITp/AnoYUUmQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@react-aria/focus": { + "version": "3.20.5", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.5.tgz", + "integrity": "sha512-JpFtXmWQ0Oca7FcvkqgjSyo6xEP7v3oQOLUId6o0xTvm4AD5W0mU2r3lYrbhsJ+XxdUUX4AVR5473sZZ85kU4A==", + "dependencies": { + "@react-aria/interactions": "^3.25.3", + "@react-aria/utils": "^3.29.1", + "@react-types/shared": "^3.30.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/interactions": { + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.25.3.tgz", + "integrity": "sha512-J1bhlrNtjPS/fe5uJQ+0c7/jiXniwa4RQlP+Emjfc/iuqpW2RhbF9ou5vROcLzWIyaW8tVMZ468J68rAs/aZ5A==", + "dependencies": { + "@react-aria/ssr": "^3.9.9", + "@react-aria/utils": "^3.29.1", + "@react-stately/flags": "^3.1.2", + "@react-types/shared": "^3.30.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/ssr": { + "version": "3.9.9", + "resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.9.tgz", + "integrity": "sha512-2P5thfjfPy/np18e5wD4WPt8ydNXhij1jwA8oehxZTFqlgVMGXzcWKxTb4RtJrLFsqPO7RUQTiY8QJk0M4Vy2g==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/utils": { + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.29.1.tgz", + "integrity": "sha512-yXMFVJ73rbQ/yYE/49n5Uidjw7kh192WNN9PNQGV0Xoc7EJUlSOxqhnpHmYTyO0EotJ8fdM1fMH8durHjUSI8g==", + "dependencies": { + "@react-aria/ssr": "^3.9.9", + "@react-stately/flags": "^3.1.2", + "@react-stately/utils": "^3.10.7", + "@react-types/shared": "^3.30.0", + "@swc/helpers": "^0.5.0", + "clsx": "^2.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-stately/flags": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.2.tgz", + "integrity": "sha512-2HjFcZx1MyQXoPqcBGALwWWmgFVUk2TuKVIQxCbRq7fPyWXIl6VHcakCLurdtYC2Iks7zizvz0Idv48MQ38DWg==", + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, + "node_modules/@react-stately/utils": { + "version": "3.10.7", + "resolved": "https://registry.npmjs.org/@react-stately/utils/-/utils-3.10.7.tgz", + "integrity": "sha512-cWvjGAocvy4abO9zbr6PW6taHgF24Mwy/LbQ4TC4Aq3tKdKDntxyD+sh7AkSRfJRT2ccMVaHVv2+FfHThd3PKQ==", + "dependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-types/shared": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.30.0.tgz", + "integrity": "sha512-COIazDAx1ncDg046cTJ8SFYsX8aS3lB/08LDnbkH/SkdYrFPWDlXMrO/sUam8j1WWM+PJ+4d1mj7tODIKNiFog==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@readme/better-ajv-errors": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@readme/better-ajv-errors/-/better-ajv-errors-2.3.2.tgz", + "integrity": "sha512-T4GGnRAlY3C339NhoUpgJJFsMYko9vIgFAlhgV+/vEGFw66qEY4a4TRJIAZBcX/qT1pq5DvXSme+SQODHOoBrw==", + "license": "Apache-2.0", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/runtime": "^7.22.5", + "@humanwhocodes/momoa": "^2.0.3", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "ajv": "4.11.8 - 8" + } + }, + "node_modules/@readme/json-schema-ref-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@readme/json-schema-ref-parser/-/json-schema-ref-parser-1.2.1.tgz", + "integrity": "sha512-FKCnFnpKklBPu8atyXqmSRBPSYlZLdcdbIilX19y0vVFiVthqKV9SQp4GZ8L4rOqSVmjn14uZ4Ono5tZKMr1SQ==", + "deprecated": "This package is no longer maintained. Please use `@apidevtools/json-schema-ref-parser` instead.", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.12", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@readme/openapi-parser": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-parser/-/openapi-parser-2.7.0.tgz", + "integrity": "sha512-P8WSr8WTOxilnT89tcCRKWYsG/II4sAwt1a/DIWub8xTtkrG9cCBBy/IUcvc5X8oGWN82MwcTA3uEkDrXZd/7A==", + "license": "MIT", + "dependencies": { + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "@readme/better-ajv-errors": "^2.0.0", + "@readme/json-schema-ref-parser": "^1.2.0", + "@readme/openapi-schemas": "^3.1.0", + "ajv": "^8.12.0", + "ajv-draft-04": "^1.0.0", + "call-me-maybe": "^1.0.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@readme/openapi-schemas": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@readme/openapi-schemas/-/openapi-schemas-3.1.0.tgz", + "integrity": "sha512-9FC/6ho8uFa8fV50+FPy/ngWN53jaUu4GRXlAjcxIRrzhltJnpKkBG2Tp0IDraFJeWrOpk84RJ9EMEEYzaI1Bw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.19.tgz", + "integrity": "sha512-3FL3mnMbPu0muGOCaKAhhFEYmqv9eTfPSJRJmANrCwtgK8VuxpsZDGK+m0LYAGoyO8+0j5uRe4PeyPDK1yA/hA==" + }, + "node_modules/@rollup/pluginutils": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.2.0.tgz", + "integrity": "sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/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==" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.44.1.tgz", + "integrity": "sha512-JAcBr1+fgqx20m7Fwe1DxPUl/hPkee6jA6Pl7n1v2EFiktAHenTaXl5aIFjUIEsfn9w3HE4gK1lEgNGMzBDs1w==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.44.1.tgz", + "integrity": "sha512-RurZetXqTu4p+G0ChbnkwBuAtwAbIwJkycw1n6GvlGlBuS4u5qlr5opix8cBAYFJgaY05TWtM+LaoFggUmbZEQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.44.1.tgz", + "integrity": "sha512-fM/xPesi7g2M7chk37LOnmnSTHLG/v2ggWqKj3CCA1rMA4mm5KVBT1fNoswbo1JhPuNNZrVwpTvlCVggv8A2zg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.44.1.tgz", + "integrity": "sha512-gDnWk57urJrkrHQ2WVx9TSVTH7lSlU7E3AFqiko+bgjlh78aJ88/3nycMax52VIVjIm3ObXnDL2H00e/xzoipw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.44.1.tgz", + "integrity": "sha512-wnFQmJ/zPThM5zEGcnDcCJeYJgtSLjh1d//WuHzhf6zT3Md1BvvhJnWoy+HECKu2bMxaIcfWiu3bJgx6z4g2XA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.44.1.tgz", + "integrity": "sha512-uBmIxoJ4493YATvU2c0upGz87f99e3wop7TJgOA/bXMFd2SvKCI7xkxY/5k50bv7J6dw1SXT4MQBQSLn8Bb/Uw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.44.1.tgz", + "integrity": "sha512-n0edDmSHlXFhrlmTK7XBuwKlG5MbS7yleS1cQ9nn4kIeW+dJH+ExqNgQ0RrFRew8Y+0V/x6C5IjsHrJmiHtkxQ==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.44.1.tgz", + "integrity": "sha512-8WVUPy3FtAsKSpyk21kV52HCxB+me6YkbkFHATzC2Yd3yuqHwy2lbFL4alJOLXKljoRw08Zk8/xEj89cLQ/4Nw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.44.1.tgz", + "integrity": "sha512-yuktAOaeOgorWDeFJggjuCkMGeITfqvPgkIXhDqsfKX8J3jGyxdDZgBV/2kj/2DyPaLiX6bPdjJDTu9RB8lUPQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.44.1.tgz", + "integrity": "sha512-W+GBM4ifET1Plw8pdVaecwUgxmiH23CfAUj32u8knq0JPFyK4weRy6H7ooxYFD19YxBulL0Ktsflg5XS7+7u9g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loongarch64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.44.1.tgz", + "integrity": "sha512-1zqnUEMWp9WrGVuVak6jWTl4fEtrVKfZY7CvcBmUUpxAJ7WcSowPSAWIKa/0o5mBL/Ij50SIf9tuirGx63Ovew==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.44.1.tgz", + "integrity": "sha512-Rl3JKaRu0LHIx7ExBAAnf0JcOQetQffaw34T8vLlg9b1IhzcBgaIdnvEbbsZq9uZp3uAH+JkHd20Nwn0h9zPjA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.44.1.tgz", + "integrity": "sha512-j5akelU3snyL6K3N/iX7otLBIl347fGwmd95U5gS/7z6T4ftK288jKq3A5lcFKcx7wwzb5rgNvAg3ZbV4BqUSw==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.44.1.tgz", + "integrity": "sha512-ppn5llVGgrZw7yxbIm8TTvtj1EoPgYUAbfw0uDjIOzzoqlZlZrLJ/KuiE7uf5EpTpCTrNt1EdtzF0naMm0wGYg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.44.1.tgz", + "integrity": "sha512-Hu6hEdix0oxtUma99jSP7xbvjkUM/ycke/AQQ4EC5g7jNRLLIwjcNwaUy95ZKBJJwg1ZowsclNnjYqzN4zwkAw==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.44.1.tgz", + "integrity": "sha512-EtnsrmZGomz9WxK1bR5079zee3+7a+AdFlghyd6VbAjgRJDbTANJ9dcPIPAi76uG05micpEL+gPGmAKYTschQw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.44.1.tgz", + "integrity": "sha512-iAS4p+J1az6Usn0f8xhgL4PaU878KEtutP4hqw52I4IO6AGoyOkHCxcc4bqufv1tQLdDWFx8lR9YlwxKuv3/3g==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.44.1.tgz", + "integrity": "sha512-NtSJVKcXwcqozOl+FwI41OH3OApDyLk3kqTJgx8+gp6On9ZEt5mYhIsKNPGuaZr3p9T6NWPKGU/03Vw4CNU9qg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.44.1.tgz", + "integrity": "sha512-JYA3qvCOLXSsnTR3oiyGws1Dm0YTuxAAeaYGVlGpUsHqloPcFjPg+X0Fj2qODGLNwQOAcCiQmHub/V007kiH5A==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.44.1.tgz", + "integrity": "sha512-J8o22LuF0kTe7m+8PvW9wk3/bRq5+mRo5Dqo6+vXb7otCm3TPhYOJqOaQtGU9YMWQSL3krMnoOxMr0+9E6F3Ug==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@shikijs/core": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.7.0.tgz", + "integrity": "sha512-yilc0S9HvTPyahHpcum8eonYrQtmGTU0lbtwxhA6jHv4Bm1cAdlPFRCJX4AHebkCm75aKTjjRAW+DezqD1b/cg==", + "dependencies": { + "@shikijs/types": "3.7.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4", + "hast-util-to-html": "^9.0.5" + } + }, + "node_modules/@shikijs/engine-javascript": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.7.0.tgz", + "integrity": "sha512-0t17s03Cbv+ZcUvv+y33GtX75WBLQELgNdVghnsdhTgU3hVcWcMsoP6Lb0nDTl95ZJfbP1mVMO0p3byVh3uuzA==", + "dependencies": { + "@shikijs/types": "3.7.0", + "@shikijs/vscode-textmate": "^10.0.2", + "oniguruma-to-es": "^4.3.3" + } + }, + "node_modules/@shikijs/engine-oniguruma": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.7.0.tgz", + "integrity": "sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==", + "dependencies": { + "@shikijs/types": "3.7.0", + "@shikijs/vscode-textmate": "^10.0.2" + } + }, + "node_modules/@shikijs/langs": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.7.0.tgz", + "integrity": "sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==", + "dependencies": { + "@shikijs/types": "3.7.0" + } + }, + "node_modules/@shikijs/themes": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.7.0.tgz", + "integrity": "sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==", + "dependencies": { + "@shikijs/types": "3.7.0" + } + }, + "node_modules/@shikijs/types": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.7.0.tgz", + "integrity": "sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==", + "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==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.17", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", + "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", + "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", + "dependencies": { + "@ampproject/remapping": "^2.3.0", + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.30.1", + "magic-string": "^0.30.17", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", + "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", + "hasInstallScript": true, + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-arm64": "4.1.11", + "@tailwindcss/oxide-darwin-x64": "4.1.11", + "@tailwindcss/oxide-freebsd-x64": "4.1.11", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", + "@tailwindcss/oxide-linux-x64-musl": "4.1.11", + "@tailwindcss/oxide-wasm32-wasi": "4.1.11", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", + "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", + "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", + "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", + "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", + "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", + "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", + "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", + "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", + "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", + "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@emnapi/wasi-threads": "^1.0.2", + "@napi-rs/wasm-runtime": "^0.2.11", + "@tybys/wasm-util": "^0.9.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.4.3", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "inBundle": true, + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.4.3", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "inBundle": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "inBundle": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.11", + "integrity": "sha512-9DPkXtvHydrcOsopiYpUgPHpmj0HWZKMUnL2dZqpvC42lsratuBG06V5ipyno0fUek5VlFsNQ+AcFATSrJXgMA==", + "inBundle": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "inBundle": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.0", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", + "inBundle": true, + "optional": true + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", + "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", + "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/vite": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", + "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", + "dependencies": { + "@tailwindcss/node": "4.1.11", + "@tailwindcss/oxide": "4.1.11", + "tailwindcss": "4.1.11" + }, + "peerDependencies": { + "vite": "^5.2.0 || ^6 || ^7" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.13.11", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.11.tgz", + "integrity": "sha512-u5EaOSJOq08T9NXFuDopMdxZBNDFuEMohIFFU45fBYDXXh9SjYdbpNq1OLFSOpQnDRPjqgmY96ipZTkzom9t9Q==", + "dependencies": { + "@tanstack/virtual-core": "3.13.11" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.13.11", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.11.tgz", + "integrity": "sha512-ORL6UyuZJ0D9X33LDR4TcgcM+K2YiS2j4xbvH1vnhhObwR1Z4dKwPTL/c0kj2Yeb4Yp2lBv1wpyVaqlohk8zpg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "node_modules/@types/estree-jsx": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", + "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/@types/fontkit": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/@types/fontkit/-/fontkit-2.0.8.tgz", + "integrity": "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew==", + "dependencies": { + "@types/node": "*" + } + }, + "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==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "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==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/mdx": { + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", + "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==" + }, + "node_modules/@types/nlcst": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", + "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/node": { + "version": "24.0.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.8.tgz", + "integrity": "sha512-WytNrFSgWO/esSH9NbpWUfTMGQwCGIKfCmNlmFDNiI5gGhgMmEA+V1AEvKLeBNvvtBnailJtkrEa2OIISwrVAA==", + "license": "MIT", + "dependencies": { + "undici-types": "~7.8.0" + } + }, + "node_modules/@types/react": { + "version": "19.1.8", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.8.tgz", + "integrity": "sha512-AwAfQ2Wa5bCx9WP8nZL2uMZWod7J7/JSplxbTmBQ5ms6QpqNYm672H0Vu9ZVKVngQ+ii4R/byguVEUZQyeg44g==", + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.6", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.6.tgz", + "integrity": "sha512-4hOiT/dwO8Ko0gV1m/TJZYk3y0KBnY9vzDh7W+DH17b2HFSOGgdj33dhihPeuy3l0q23+4e+hoXHV6hCC4dCXw==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/sax": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", + "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", + "dependencies": { + "@types/node": "*" + } + }, + "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==" + }, + "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==" + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.6.0.tgz", + "integrity": "sha512-5Kgff+m8e2PB+9j51eGHEpn5kUzRKH2Ry0qGoe8ItJg7pqnkPrYPkDQZGgGmTa0EGarHrkjLvOdU3b1fzI8otQ==", + "dependencies": { + "@babel/core": "^7.27.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.19", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-draft-04": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", + "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", + "license": "MIT", + "peerDependencies": { + "ajv": "^8.5.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-iterate": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", + "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/astring": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", + "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", + "bin": { + "astring": "bin/astring" + } + }, + "node_modules/astro": { + "version": "5.10.1", + "resolved": "https://registry.npmjs.org/astro/-/astro-5.10.1.tgz", + "integrity": "sha512-DJVmt+51jU1xmgmAHCDwuUgcG/5aVFSU+tcX694acAZqPVt8EMUAmUZcJDX36Z7/EztnPph9HR3pm72jS2EgHQ==", + "dependencies": { + "@astrojs/compiler": "^2.12.2", + "@astrojs/internal-helpers": "0.6.1", + "@astrojs/markdown-remark": "6.3.2", + "@astrojs/telemetry": "3.3.0", + "@capsizecss/unpack": "^2.4.0", + "@oslojs/encoding": "^1.1.0", + "@rollup/pluginutils": "^5.1.4", + "acorn": "^8.14.1", + "aria-query": "^5.3.2", + "axobject-query": "^4.1.0", + "boxen": "8.0.1", + "ci-info": "^4.2.0", + "clsx": "^2.1.1", + "common-ancestor-path": "^1.0.1", + "cookie": "^1.0.2", + "cssesc": "^3.0.0", + "debug": "^4.4.0", + "deterministic-object-hash": "^2.0.2", + "devalue": "^5.1.1", + "diff": "^5.2.0", + "dlv": "^1.1.3", + "dset": "^3.1.4", + "es-module-lexer": "^1.6.0", + "esbuild": "^0.25.0", + "estree-walker": "^3.0.3", + "flattie": "^1.1.1", + "fontace": "~0.3.0", + "github-slugger": "^2.0.0", + "html-escaper": "3.0.3", + "http-cache-semantics": "^4.1.1", + "import-meta-resolve": "^4.1.0", + "js-yaml": "^4.1.0", + "kleur": "^4.1.5", + "magic-string": "^0.30.17", + "magicast": "^0.3.5", + "mrmime": "^2.0.1", + "neotraverse": "^0.6.18", + "p-limit": "^6.2.0", + "p-queue": "^8.1.0", + "package-manager-detector": "^1.1.0", + "picomatch": "^4.0.2", + "prompts": "^2.4.2", + "rehype": "^13.0.2", + "semver": "^7.7.1", + "shiki": "^3.2.1", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.12", + "tsconfck": "^3.1.5", + "ultrahtml": "^1.6.0", + "unifont": "~0.5.0", + "unist-util-visit": "^5.0.0", + "unstorage": "^1.15.0", + "vfile": "^6.0.3", + "vite": "^6.3.4", + "vitefu": "^1.0.6", + "xxhash-wasm": "^1.1.0", + "yargs-parser": "^21.1.1", + "yocto-spinner": "^0.2.1", + "zod": "^3.24.2", + "zod-to-json-schema": "^3.24.5", + "zod-to-ts": "^1.2.0" + }, + "bin": { + "astro": "astro.js" + }, + "engines": { + "node": "18.20.8 || ^20.3.0 || >=22.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/astrodotbuild" + }, + "optionalDependencies": { + "sharp": "^0.33.3" + } + }, + "node_modules/astro-expressive-code": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.2.tgz", + "integrity": "sha512-HN0jWTnhr7mIV/2e6uu4PPRNNo/k4UEgTLZqbp3MrHU+caCARveG2yZxaZVBmxyiVdYqW5Pd3u3n2zjnshixbw==", + "dependencies": { + "rehype-expressive-code": "^0.41.2" + }, + "peerDependencies": { + "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" + } + }, + "node_modules/astro/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/bail": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", + "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/base-64": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", + "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bcp-47": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", + "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/bcp-47-match": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", + "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/blob-to-buffer": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/blob-to-buffer/-/blob-to-buffer-1.2.9.tgz", + "integrity": "sha512-BF033y5fN6OCofD3vgHmNtwZWRcq9NLyyxyILx9hfMy1sXYy4ojFl765hJ2lP0YaN2fuxPaLO2Vzzoxy0FLFFA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/boxen": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", + "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", + "dependencies": { + "ansi-align": "^3.0.1", + "camelcase": "^8.0.0", + "chalk": "^5.3.0", + "cli-boxes": "^3.0.0", + "string-width": "^7.2.0", + "type-fest": "^4.21.0", + "widest-line": "^5.0.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brotli": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", + "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", + "dependencies": { + "base64-js": "^1.1.2" + } + }, + "node_modules/browserslist": { + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" + }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001726", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001726.tgz", + "integrity": "sha512-VQAUIUzBiZ/UnlM28fSp2CRF3ivUn1BWEvxMcVTNwpw91Py1pGbPIyIKtd+tzct9C3ouceCVdGAXxZOpZAsgdw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chalk": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "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==", + "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==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-reference-invalid": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", + "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "engines": { + "node": ">=18" + } + }, + "node_modules/ci-info": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", + "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-boxes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", + "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/collapse-white-space": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", + "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "optional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "optional": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "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==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/common-ancestor-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", + "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" + }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "engines": { + "node": ">=18" + } + }, + "node_modules/cookie-es": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", + "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==" + }, + "node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, + "node_modules/crossws": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", + "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", + "dependencies": { + "uncrypto": "^0.1.3" + } + }, + "node_modules/css-selector-parser": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.1.3.tgz", + "integrity": "sha512-gJMigczVZqYAk0hPVzx/M4Hm1D9QOtqkdQk9005TNzDIUGzo5cnHEDiKUT7jGPximL/oYb+LIitcHFQ4aKupxg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ] + }, + "node_modules/css-tree": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", + "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", + "dependencies": { + "mdn-data": "2.12.2", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "license": "MIT", + "peer": true + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==" + }, + "node_modules/detect-libc": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", + "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/deterministic-object-hash": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", + "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", + "dependencies": { + "base-64": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/devalue": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", + "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==" + }, + "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==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dfa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", + "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==" + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/direction": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", + "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", + "bin": { + "direction": "cli.js" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/dset": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", + "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.177", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz", + "integrity": "sha512-7EH2G59nLsEMj97fpDuvVcYi6lwTcM1xuWw3PssD8xzboAW7zj7iB3COEEEATUfjLHrs5uKBLQT03V/8URx06g==" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/enhanced-resolve": { + "version": "5.18.2", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz", + "integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==" + }, + "node_modules/esast-util-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", + "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esast-util-from-js": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", + "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "acorn": "^8.0.0", + "esast-util-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/esbuild": { + "version": "0.25.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", + "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.5", + "@esbuild/android-arm": "0.25.5", + "@esbuild/android-arm64": "0.25.5", + "@esbuild/android-x64": "0.25.5", + "@esbuild/darwin-arm64": "0.25.5", + "@esbuild/darwin-x64": "0.25.5", + "@esbuild/freebsd-arm64": "0.25.5", + "@esbuild/freebsd-x64": "0.25.5", + "@esbuild/linux-arm": "0.25.5", + "@esbuild/linux-arm64": "0.25.5", + "@esbuild/linux-ia32": "0.25.5", + "@esbuild/linux-loong64": "0.25.5", + "@esbuild/linux-mips64el": "0.25.5", + "@esbuild/linux-ppc64": "0.25.5", + "@esbuild/linux-riscv64": "0.25.5", + "@esbuild/linux-s390x": "0.25.5", + "@esbuild/linux-x64": "0.25.5", + "@esbuild/netbsd-arm64": "0.25.5", + "@esbuild/netbsd-x64": "0.25.5", + "@esbuild/openbsd-arm64": "0.25.5", + "@esbuild/openbsd-x64": "0.25.5", + "@esbuild/sunos-x64": "0.25.5", + "@esbuild/win32-arm64": "0.25.5", + "@esbuild/win32-ia32": "0.25.5", + "@esbuild/win32-x64": "0.25.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/estree-util-attach-comments": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", + "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", + "dependencies": { + "@types/estree": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-build-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", + "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "estree-walker": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-is-identifier-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", + "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-scope": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", + "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-to-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", + "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "astring": "^1.8.0", + "source-map": "^0.7.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-util-visit": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", + "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" + }, + "node_modules/expressive-code": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.2.tgz", + "integrity": "sha512-aLZiZaqorRtNExtGpUjK9zFH9aTpWeoTXMyLo4b4IcuXfPqtLPPxhRm/QlPb8QqIcMMXnSiGRHSFpQfX0m7HJw==", + "dependencies": { + "@expressive-code/core": "^0.41.2", + "@expressive-code/plugin-frames": "^0.41.2", + "@expressive-code/plugin-shiki": "^0.41.2", + "@expressive-code/plugin-text-markers": "^0.41.2" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-uri": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fdir": { + "version": "6.4.6", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", + "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/flattie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", + "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/fontace": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.3.0.tgz", + "integrity": "sha512-czoqATrcnxgWb/nAkfyIrRp6Q8biYj7nGnL6zfhTcX+JKKpWHFBnb8uNMw/kZr7u++3Y3wYSYoZgHkCcsuBpBg==", + "dependencies": { + "@types/fontkit": "^2.0.8", + "fontkit": "^2.0.4" + } + }, + "node_modules/fontkit": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", + "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", + "dependencies": { + "@swc/helpers": "^0.5.12", + "brotli": "^1.3.2", + "clone": "^2.1.2", + "dfa": "^1.2.0", + "fast-deep-equal": "^3.1.3", + "restructure": "^3.0.0", + "tiny-inflate": "^1.0.3", + "unicode-properties": "^1.4.0", + "unicode-trie": "^2.0.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==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", + "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/h3": { + "version": "1.15.3", + "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.3.tgz", + "integrity": "sha512-z6GknHqyX0h9aQaTx22VZDf6QyZn+0Nh+Ym8O/u0SGSkyF5cuTJYKlc8MkzW3Nzf9LE1ivcpmYC3FUGpywhuUQ==", + "dependencies": { + "cookie-es": "^1.2.2", + "crossws": "^0.3.4", + "defu": "^6.1.4", + "destr": "^2.0.5", + "iron-webcrypto": "^1.2.1", + "node-mock-http": "^1.0.0", + "radix3": "^1.1.2", + "ufo": "^1.6.1", + "uncrypto": "^0.1.3" + } + }, + "node_modules/hast-util-embedded": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", + "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-format": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", + "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-minify-whitespace": "^1.0.0", + "hast-util-phrasing": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "html-whitespace-sensitive-tag-names": "^3.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-html": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", + "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.1.0", + "hast-util-from-parse5": "^8.0.0", + "parse5": "^7.0.0", + "vfile": "^6.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-from-parse5": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", + "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "hastscript": "^9.0.0", + "property-information": "^7.0.0", + "vfile": "^6.0.0", + "vfile-location": "^5.0.0", + "web-namespaces": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-has-property": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", + "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-body-ok-link": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", + "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-is-element": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", + "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-minify-whitespace": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", + "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-parse-selector": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", + "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-phrasing": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", + "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-embedded": "^3.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-is-body-ok-link": "^3.0.0", + "hast-util-is-element": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-raw": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", + "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "@ungap/structured-clone": "^1.0.0", + "hast-util-from-parse5": "^8.0.0", + "hast-util-to-parse5": "^8.0.0", + "html-void-elements": "^3.0.0", + "mdast-util-to-hast": "^13.0.0", + "parse5": "^7.0.0", + "unist-util-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "vfile": "^6.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-select": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", + "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "bcp-47-match": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "css-selector-parser": "^3.0.0", + "devlop": "^1.0.0", + "direction": "^2.0.0", + "hast-util-has-property": "^3.0.0", + "hast-util-to-string": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "nth-check": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-estree": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", + "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-attach-comments": "^3.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "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==", + "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-to-jsx-runtime": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", + "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "hast-util-whitespace": "^3.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0", + "style-to-js": "^1.0.0", + "unist-util-position": "^5.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", + "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "devlop": "^1.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "web-namespaces": "^2.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-parse5/node_modules/property-information": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", + "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/hast-util-to-string": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", + "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hast-util-to-text": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", + "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/unist": "^3.0.0", + "hast-util-is-element": "^3.0.0", + "unist-util-find-after": "^5.0.0" + }, + "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==", + "dependencies": { + "@types/hast": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/hastscript": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", + "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", + "dependencies": { + "@types/hast": "^3.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-parse-selector": "^4.0.0", + "property-information": "^7.0.0", + "space-separated-tokens": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==" + }, + "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==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/html-whitespace-sensitive-tag-names": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", + "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==" + }, + "node_modules/i18next": { + "version": "23.16.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", + "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/inline-style-parser": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", + "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" + }, + "node_modules/iron-webcrypto": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", + "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", + "funding": { + "url": "https://github.com/sponsors/brc-dd" + } + }, + "node_modules/is-alphabetical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", + "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-alphanumerical": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", + "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", + "dependencies": { + "is-alphabetical": "^2.0.0", + "is-decimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "optional": true + }, + "node_modules/is-decimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", + "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-hexadecimal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", + "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/klona": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", + "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/magicast": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.3.5.tgz", + "integrity": "sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==", + "dependencies": { + "@babel/parser": "^7.25.4", + "@babel/types": "^7.25.4", + "source-map-js": "^1.2.0" + } + }, + "node_modules/markdown-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", + "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/mdast-util-definitions": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", + "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-directive": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", + "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.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/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", + "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx-expression": "^2.0.0", + "mdast-util-mdx-jsx": "^3.0.0", + "mdast-util-mdxjs-esm": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-expression": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", + "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdx-jsx": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", + "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "ccount": "^2.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "parse-entities": "^4.0.0", + "stringify-entities": "^4.0.0", + "unist-util-stringify-position": "^4.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-mdxjs-esm": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", + "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", + "dependencies": { + "@types/estree-jsx": "^1.0.0", + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-hast": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", + "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", + "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/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdn-data": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", + "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==" + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-directive": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", + "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "parse-entities": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-expression": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", + "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-mdx-jsx": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", + "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "estree-util-is-identifier-name": "^3.0.0", + "micromark-factory-mdx-expression": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdx-md": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", + "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", + "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", + "dependencies": { + "acorn": "^8.0.0", + "acorn-jsx": "^5.0.0", + "micromark-extension-mdx-expression": "^3.0.0", + "micromark-extension-mdx-jsx": "^3.0.0", + "micromark-extension-mdx-md": "^2.0.0", + "micromark-extension-mdxjs-esm": "^3.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-mdxjs-esm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", + "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-mdx-expression": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", + "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-events-to-acorn": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-position-from-estree": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "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==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^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==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-events-to-acorn": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", + "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "@types/estree": "^1.0.0", + "@types/unist": "^3.0.0", + "devlop": "^1.0.0", + "estree-util-visit": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "vfile-message": "^4.0.0" + } + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "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==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^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==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "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==", + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ] + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", + "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/neotraverse": { + "version": "0.6.18", + "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", + "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/nlcst-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", + "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", + "dependencies": { + "@types/nlcst": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.6.tgz", + "integrity": "sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==" + }, + "node_modules/node-mock-http": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.1.tgz", + "integrity": "sha512-0gJJgENizp4ghds/Ywu2FCmcRsgBTmRQzYPZm61wy+Em2sBarSka0OhQS5huLBg6od1zkNpnWMCZloQDFVvOMQ==" + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/ofetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz", + "integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==", + "dependencies": { + "destr": "^2.0.3", + "node-fetch-native": "^1.6.4", + "ufo": "^1.5.4" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==" + }, + "node_modules/oniguruma-parser": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", + "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==" + }, + "node_modules/oniguruma-to-es": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz", + "integrity": "sha512-rPiZhzC3wXwE59YQMRDodUwwT9FZ9nNBwQQfsd1wfdtlKEyCdRV0avrTcSZ5xlIvGRVPd/cx6ZN45ECmS39xvg==", + "dependencies": { + "oniguruma-parser": "^0.12.1", + "regex": "^6.0.1", + "regex-recursion": "^6.0.2" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, + "node_modules/p-limit": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", + "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", + "dependencies": { + "yocto-queue": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-queue": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.0.tgz", + "integrity": "sha512-mxLDbbGIBEXTJL0zEx8JIylaj3xQ7Z/7eEVjcF9fJX4DBiH9oqe+oahYnlKKxm0Ci9TlWTyhSHgygxMxjIB2jw==", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^6.1.2" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", + "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz", + "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==" + }, + "node_modules/pagefind": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.3.0.tgz", + "integrity": "sha512-8KPLGT5g9s+olKMRTU9LFekLizkVIu9tes90O1/aigJ0T5LmyPqTzGJrETnSw3meSYg58YH7JTzhTTW/3z6VAw==", + "bin": { + "pagefind": "lib/runner/bin.cjs" + }, + "optionalDependencies": { + "@pagefind/darwin-arm64": "1.3.0", + "@pagefind/darwin-x64": "1.3.0", + "@pagefind/linux-arm64": "1.3.0", + "@pagefind/linux-x64": "1.3.0", + "@pagefind/windows-x64": "1.3.0" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/parse-entities": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", + "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", + "dependencies": { + "@types/unist": "^2.0.0", + "character-entities-legacy": "^3.0.0", + "character-reference-invalid": "^2.0.0", + "decode-named-character-reference": "^1.0.0", + "is-alphanumerical": "^2.0.0", + "is-decimal": "^2.0.0", + "is-hexadecimal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse-entities/node_modules/@types/unist": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", + "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==" + }, + "node_modules/parse-latin": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", + "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", + "dependencies": { + "@types/nlcst": "^2.0.0", + "@types/unist": "^3.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-modify-children": "^4.0.0", + "unist-util-visit-children": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "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" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prompts/node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "engines": { + "node": ">=6" + } + }, + "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==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/radix3": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", + "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==" + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/recma-build-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", + "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-build-jsx": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-jsx": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.0.tgz", + "integrity": "sha512-5vwkv65qWwYxg+Atz95acp8DMu1JDSqdGkA2Of1j6rCreyFUE/gp15fC8MnGEuG1W68UKjM6x6+YTWIh7hZM/Q==", + "dependencies": { + "acorn-jsx": "^5.0.0", + "estree-util-to-js": "^2.0.0", + "recma-parse": "^1.0.0", + "recma-stringify": "^1.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-parse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", + "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", + "dependencies": { + "@types/estree": "^1.0.0", + "esast-util-from-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/recma-stringify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", + "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-util-to-js": "^2.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", + "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", + "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==", + "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==" + }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-expressive-code": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.2.tgz", + "integrity": "sha512-vHYfWO9WxAw6kHHctddOt+P4266BtyT1mrOIuxJD+1ELuvuJAa5uBIhYt0OVMyOhlvf57hzWOXJkHnMhpaHyxw==", + "dependencies": { + "expressive-code": "^0.41.2" + } + }, + "node_modules/rehype-format": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", + "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-format": "^1.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-parse": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", + "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-from-html": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-raw": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", + "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-raw": "^9.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-recma": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", + "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", + "dependencies": { + "@types/estree": "^1.0.0", + "@types/hast": "^3.0.0", + "hast-util-to-estree": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-directive": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", + "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-directive": "^3.0.0", + "micromark-extension-directive": "^3.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-gfm": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", + "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-mdx": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.0.tgz", + "integrity": "sha512-Ngl/H3YXyBV9RcRNdlYsZujAmhsxwzxpDzpDEhFBVAGthS4GDgnctpDjgFl/ULx5UEDzqtW1cyBSNKqYYrqLBA==", + "dependencies": { + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-parse": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", + "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-rehype": { + "version": "11.1.2", + "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", + "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", + "dependencies": { + "@types/hast": "^3.0.0", + "@types/mdast": "^4.0.0", + "mdast-util-to-hast": "^13.0.0", + "unified": "^11.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/remark-smartypants": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", + "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", + "dependencies": { + "retext": "^9.0.0", + "retext-smartypants": "^6.0.0", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restructure": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", + "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==" + }, + "node_modules/retext": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", + "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", + "dependencies": { + "@types/nlcst": "^2.0.0", + "retext-latin": "^4.0.0", + "retext-stringify": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-latin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", + "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", + "dependencies": { + "@types/nlcst": "^2.0.0", + "parse-latin": "^7.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-smartypants": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", + "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unist-util-visit": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/retext-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", + "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", + "dependencies": { + "@types/nlcst": "^2.0.0", + "nlcst-to-string": "^4.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/rollup": { + "version": "4.44.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.44.1.tgz", + "integrity": "sha512-x8H8aPvD+xbl0Do8oez5f5o8eMS3trfCghc4HhLAnCkj7Vl0d1JWGs0UF/D886zLW2rOj2QymV/JcSSsw+XDNg==", + "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.44.1", + "@rollup/rollup-android-arm64": "4.44.1", + "@rollup/rollup-darwin-arm64": "4.44.1", + "@rollup/rollup-darwin-x64": "4.44.1", + "@rollup/rollup-freebsd-arm64": "4.44.1", + "@rollup/rollup-freebsd-x64": "4.44.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.44.1", + "@rollup/rollup-linux-arm-musleabihf": "4.44.1", + "@rollup/rollup-linux-arm64-gnu": "4.44.1", + "@rollup/rollup-linux-arm64-musl": "4.44.1", + "@rollup/rollup-linux-loongarch64-gnu": "4.44.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-gnu": "4.44.1", + "@rollup/rollup-linux-riscv64-musl": "4.44.1", + "@rollup/rollup-linux-s390x-gnu": "4.44.1", + "@rollup/rollup-linux-x64-gnu": "4.44.1", + "@rollup/rollup-linux-x64-musl": "4.44.1", + "@rollup/rollup-win32-arm64-msvc": "4.44.1", + "@rollup/rollup-win32-ia32-msvc": "4.44.1", + "@rollup/rollup-win32-x64-msvc": "4.44.1", + "fsevents": "~2.3.2" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shiki": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.7.0.tgz", + "integrity": "sha512-ZcI4UT9n6N2pDuM2n3Jbk0sR4Swzq43nLPgS/4h0E3B/NrFn2HKElrDtceSf8Zx/OWYOo7G1SAtBLypCp+YXqg==", + "dependencies": { + "@shikijs/core": "3.7.0", + "@shikijs/engine-javascript": "3.7.0", + "@shikijs/engine-oniguruma": "3.7.0", + "@shikijs/langs": "3.7.0", + "@shikijs/themes": "3.7.0", + "@shikijs/types": "3.7.0", + "@shikijs/vscode-textmate": "^10.0.2", + "@types/hast": "^3.0.4" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, + "node_modules/sitemap": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.0.tgz", + "integrity": "sha512-+AbdxhM9kJsHtruUF39bwS/B0Fytw6Fr1o4ZAIAEqA6cke2xcoO2GleBw9Zw7nRzILVEgz7zBM5GiTJjie1G9A==", + "dependencies": { + "@types/node": "^17.0.5", + "@types/sax": "^1.2.1", + "arg": "^5.0.0", + "sax": "^1.2.4" + }, + "bin": { + "sitemap": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=6.0.0" + } + }, + "node_modules/sitemap/node_modules/@types/node": { + "version": "17.0.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", + "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", + "license": "MIT" + }, + "node_modules/smol-toml": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.3.4.tgz", + "integrity": "sha512-UOPtVuYkzYGee0Bd2Szz8d2G3RfMfJ2t3qVdZUAozZyAk+a0Sxa+QKix0YCwjL/A1RR0ar44nCxaoN9FxdJGwA==", + "engines": { + "node": ">= 18" + }, + "funding": { + "url": "https://github.com/sponsors/cyyynthia" + } + }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "engines": { + "node": ">= 8" + } + }, + "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==", + "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==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/starlight-openapi": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/starlight-openapi/-/starlight-openapi-0.19.1.tgz", + "integrity": "sha512-hEwbLlxpWaEceJM6Cj66Amh/CCDH5mbZ/MO55byWSUmBGmitkmWMUMTPhbSj8Y7MD2SQ7uJ83tcnfaDpfwxk4Q==", + "license": "MIT", + "dependencies": { + "@readme/openapi-parser": "^2.7.0", + "github-slugger": "^2.0.0", + "url-template": "^3.1.1" + }, + "engines": { + "node": ">=18.17.1" + }, + "peerDependencies": { + "@astrojs/markdown-remark": ">=6.0.1", + "@astrojs/starlight": ">=0.34.0", + "astro": ">=5.5.0" + } + }, + "node_modules/stream-replace-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", + "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==" + }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==" + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "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==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/style-to-js": { + "version": "1.1.17", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.17.tgz", + "integrity": "sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==", + "dependencies": { + "style-to-object": "1.0.9" + } + }, + "node_modules/style-to-object": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.9.tgz", + "integrity": "sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==", + "dependencies": { + "inline-style-parser": "0.2.4" + } + }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, + "node_modules/tailwindcss": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", + "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==" + }, + "node_modules/tapable": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", + "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", + "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.0.1", + "mkdirp": "^3.0.1", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "engines": { + "node": ">=18" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", + "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==" + }, + "node_modules/tinyglobby": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", + "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "dependencies": { + "fdir": "^6.4.4", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "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==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/trough": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", + "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/tsconfck": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", + "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", + "bin": { + "tsconfck": "bin/tsconfck.js" + }, + "engines": { + "node": "^18 || >=20" + }, + "peerDependencies": { + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/ufo": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", + "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==" + }, + "node_modules/ultrahtml": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", + "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==" + }, + "node_modules/uncrypto": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", + "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==" + }, + "node_modules/undici-types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.8.0.tgz", + "integrity": "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw==", + "license": "MIT" + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", + "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", + "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unified": { + "version": "11.0.5", + "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", + "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", + "dependencies": { + "@types/unist": "^3.0.0", + "bail": "^2.0.0", + "devlop": "^1.0.0", + "extend": "^3.0.0", + "is-plain-obj": "^4.0.0", + "trough": "^2.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unifont": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.5.2.tgz", + "integrity": "sha512-LzR4WUqzH9ILFvjLAUU7dK3Lnou/qd5kD+IakBtBK4S15/+x2y9VX+DcWQv6s551R6W+vzwgVS6tFg3XggGBgg==", + "dependencies": { + "css-tree": "^3.0.0", + "ofetch": "^1.4.1", + "ohash": "^2.0.0" + } + }, + "node_modules/unist-util-find-after": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", + "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-modify-children": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", + "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", + "dependencies": { + "@types/unist": "^3.0.0", + "array-iterate": "^2.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==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-position-from-estree": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", + "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-remove-position": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", + "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-visit": "^5.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==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "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-children": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", + "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unstorage": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.16.0.tgz", + "integrity": "sha512-WQ37/H5A7LcRPWfYOrDa1Ys02xAbpPJq6q5GkO88FBXVSQzHd7+BjEwfRqyaSWCv9MbsJy058GWjjPjcJ16GGA==", + "dependencies": { + "anymatch": "^3.1.3", + "chokidar": "^4.0.3", + "destr": "^2.0.5", + "h3": "^1.15.2", + "lru-cache": "^10.4.3", + "node-fetch-native": "^1.6.6", + "ofetch": "^1.4.1", + "ufo": "^1.6.1" + }, + "peerDependencies": { + "@azure/app-configuration": "^1.8.0", + "@azure/cosmos": "^4.2.0", + "@azure/data-tables": "^13.3.0", + "@azure/identity": "^4.6.0", + "@azure/keyvault-secrets": "^4.9.0", + "@azure/storage-blob": "^12.26.0", + "@capacitor/preferences": "^6.0.3 || ^7.0.0", + "@deno/kv": ">=0.9.0", + "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0", + "@planetscale/database": "^1.19.0", + "@upstash/redis": "^1.34.3", + "@vercel/blob": ">=0.27.1", + "@vercel/kv": "^1.0.1", + "aws4fetch": "^1.0.20", + "db0": ">=0.2.1", + "idb-keyval": "^6.2.1", + "ioredis": "^5.4.2", + "uploadthing": "^7.4.4" + }, + "peerDependenciesMeta": { + "@azure/app-configuration": { + "optional": true + }, + "@azure/cosmos": { + "optional": true + }, + "@azure/data-tables": { + "optional": true + }, + "@azure/identity": { + "optional": true + }, + "@azure/keyvault-secrets": { + "optional": true + }, + "@azure/storage-blob": { + "optional": true + }, + "@capacitor/preferences": { + "optional": true + }, + "@deno/kv": { + "optional": true + }, + "@netlify/blobs": { + "optional": true + }, + "@planetscale/database": { + "optional": true + }, + "@upstash/redis": { + "optional": true + }, + "@vercel/blob": { + "optional": true + }, + "@vercel/kv": { + "optional": true + }, + "aws4fetch": { + "optional": true + }, + "db0": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "uploadthing": { + "optional": true + } + } + }, + "node_modules/unstorage/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/url-template": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/url-template/-/url-template-3.1.1.tgz", + "integrity": "sha512-4oszoaEKE/mQOtAmdMWqIRHmkxWkUZMnXFnjQ5i01CuRSK3uluxcH1MRVVVWmhlnzT1SCDfKxxficm2G37qzCA==", + "license": "BSD-3-Clause", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/vanilla-cookieconsent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vanilla-cookieconsent/-/vanilla-cookieconsent-3.1.0.tgz", + "integrity": "sha512-/McNRtm/3IXzb9dhqMIcbquoU45SzbN2VB+To4jxEPqMmp7uVniP6BhGLjU8MC7ZCDsNQVOp27fhQTM/ruIXAA==", + "license": "MIT" + }, + "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==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile-message": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-location": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", + "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", + "dependencies": { + "@types/unist": "^3.0.0", + "vfile": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/vfile-message": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.2.tgz", + "integrity": "sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==", + "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": "6.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", + "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.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 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vitefu": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.7.tgz", + "integrity": "sha512-eRWXLBbJjW3X5z5P5IHcSm2yYbYRPb2kQuc+oqsbAl99WB5kVsPbiiox+cymo8twTzifA6itvhr2CmjnaZZp0Q==", + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true + } + } + }, + "node_modules/web-namespaces": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", + "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which-pm-runs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", + "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/widest-line": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", + "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", + "dependencies": { + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/xxhash-wasm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", + "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==" + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yocto-queue": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.1.tgz", + "integrity": "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-spinner": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", + "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", + "dependencies": { + "yoctocolors": "^2.1.1" + }, + "engines": { + "node": ">=18.19" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yoctocolors": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz", + "integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.25.67", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.67.tgz", + "integrity": "sha512-idA2YXwpCdqUSKRCACDE6ItZD9TZzy3OZMtpfLoh6oPR47lipysRrJfjzMqFxQ3uJuUPyUeWe1r9vLH33xO/Qw==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "peerDependencies": { + "zod": "^3.24.1" + } + }, + "node_modules/zod-to-ts": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", + "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", + "peerDependencies": { + "typescript": "^4.9.4 || ^5.0.2", + "zod": "^3" + } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..cf0b54a --- /dev/null +++ b/package.json @@ -0,0 +1,25 @@ +{ + "name": "helpless-hubble", + "type": "module", + "version": "0.0.1", + "scripts": { + "dev": "astro dev", + "build": "astro build", + "preview": "astro preview" + }, + "dependencies": { + "@astrojs/mdx": "^4.3.0", + "@astrojs/react": "^4.3.0", + "@astrojs/starlight": "^0.34.4", + "@astrojs/starlight-tailwind": "^4.0.1", + "@headlessui/react": "^2.2.4", + "@heroicons/react": "^2.2.0", + "@tailwindcss/vite": "^4.1.11", + "astro": "^5.10.1", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "starlight-openapi": "^0.19.1", + "tailwindcss": "^4.1.11", + "vanilla-cookieconsent": "^3.1.0" + } +} diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..acbb196 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/CookieConsentConfig.ts b/src/CookieConsentConfig.ts new file mode 100644 index 0000000..2064b33 --- /dev/null +++ b/src/CookieConsentConfig.ts @@ -0,0 +1,73 @@ +import type { CookieConsentConfig } from 'vanilla-cookieconsent'; + +export const config: CookieConsentConfig = { + guiOptions: { + consentModal: { + layout: "box", + position: "bottom left", + equalWeightButtons: true, + flipButtons: false + }, + preferencesModal: { + layout: "box", + position: "right", + equalWeightButtons: true, + flipButtons: false + } + }, + categories: { + necessary: { + readOnly: true + }, + functionality: { + enabled: true + }, + analytics: { + enabled: true + } + }, + language: { + default: "en", + translations: { + en: { + consentModal: { + title: "Select your cookie preferences", + description: "We use cookies to ensure you get the best experience on our website.", + acceptAllBtn: "Accept all", + acceptNecessaryBtn: "Reject all", + showPreferencesBtn: "Manage preferences", + footer: "Privacy Policy" + }, + preferencesModal: { + title: "Consent Preferences Center", + acceptAllBtn: "Accept all", + acceptNecessaryBtn: "Reject all", + savePreferencesBtn: "Save preferences", + closeIconLabel: "Close modal", + serviceCounterLabel: "Service|Services", + sections: [ + { + title: "Strictly Necessary Cookies Always Enabled", + description: "Some cookies are essential in order to use the website and use some of its features.", + linkedCategory: "necessary" + }, + { + title: "Functionality Cookies", + description: "These cookies are used to enhance the performance and functionality of the website but are non-essential to their use. However, without these cookies, certain functionality (like videos) may become unavailable.", + linkedCategory: "functionality" + }, + { + title: "Analytics Cookies", + description: "We use analytics cookies to understand how you use our website so we can improve it.", + linkedCategory: "analytics" + }, + { + title: "More information", + description: "For any query in relation to the policy on cookies and your choices, please refer to the Privacy Policy." + } + ] + } + } + } + } +}; \ No newline at end of file diff --git a/src/assets/ecosystem-logos/bithomp.png b/src/assets/ecosystem-logos/bithomp.png new file mode 100644 index 0000000..bbdd323 Binary files /dev/null and b/src/assets/ecosystem-logos/bithomp.png differ diff --git a/src/assets/ecosystem-logos/bitrue.png b/src/assets/ecosystem-logos/bitrue.png new file mode 100644 index 0000000..7bcec83 Binary files /dev/null and b/src/assets/ecosystem-logos/bitrue.png differ diff --git a/src/assets/ecosystem-logos/dcent.png b/src/assets/ecosystem-logos/dcent.png new file mode 100644 index 0000000..c0b3843 Binary files /dev/null and b/src/assets/ecosystem-logos/dcent.png differ diff --git a/src/assets/ecosystem-logos/gatehub.png b/src/assets/ecosystem-logos/gatehub.png new file mode 100644 index 0000000..199f050 Binary files /dev/null and b/src/assets/ecosystem-logos/gatehub.png differ diff --git a/src/assets/ecosystem-logos/xahau-services.png b/src/assets/ecosystem-logos/xahau-services.png new file mode 100644 index 0000000..ffd0bed Binary files /dev/null and b/src/assets/ecosystem-logos/xahau-services.png differ diff --git a/src/assets/ecosystem-logos/xahscan.png b/src/assets/ecosystem-logos/xahscan.png new file mode 100644 index 0000000..3487b37 Binary files /dev/null and b/src/assets/ecosystem-logos/xahscan.png differ diff --git a/src/assets/ecosystem-logos/xaman.png b/src/assets/ecosystem-logos/xaman.png new file mode 100644 index 0000000..2c88bd9 Binary files /dev/null and b/src/assets/ecosystem-logos/xaman.png differ diff --git a/src/assets/ecosystem-logos/xrplwin.png b/src/assets/ecosystem-logos/xrplwin.png new file mode 100644 index 0000000..04c1864 Binary files /dev/null and b/src/assets/ecosystem-logos/xrplwin.png differ diff --git a/src/assets/gems/1.png b/src/assets/gems/1.png new file mode 100644 index 0000000..9fb31c3 Binary files /dev/null and b/src/assets/gems/1.png differ diff --git a/src/assets/gems/10.png b/src/assets/gems/10.png new file mode 100644 index 0000000..7f6a2ad Binary files /dev/null and b/src/assets/gems/10.png differ diff --git a/src/assets/gems/11.png b/src/assets/gems/11.png new file mode 100644 index 0000000..cf52c27 Binary files /dev/null and b/src/assets/gems/11.png differ diff --git a/src/assets/gems/12.png b/src/assets/gems/12.png new file mode 100644 index 0000000..4a7e320 Binary files /dev/null and b/src/assets/gems/12.png differ diff --git a/src/assets/gems/13.png b/src/assets/gems/13.png new file mode 100644 index 0000000..7482561 Binary files /dev/null and b/src/assets/gems/13.png differ diff --git a/src/assets/gems/14.png b/src/assets/gems/14.png new file mode 100644 index 0000000..ec7bb75 Binary files /dev/null and b/src/assets/gems/14.png differ diff --git a/src/assets/gems/15.png b/src/assets/gems/15.png new file mode 100644 index 0000000..afe441b Binary files /dev/null and b/src/assets/gems/15.png differ diff --git a/src/assets/gems/16.png b/src/assets/gems/16.png new file mode 100644 index 0000000..6505f92 Binary files /dev/null and b/src/assets/gems/16.png differ diff --git a/src/assets/gems/17.png b/src/assets/gems/17.png new file mode 100644 index 0000000..2780358 Binary files /dev/null and b/src/assets/gems/17.png differ diff --git a/src/assets/gems/2.png b/src/assets/gems/2.png new file mode 100644 index 0000000..f5e2cd6 Binary files /dev/null and b/src/assets/gems/2.png differ diff --git a/src/assets/gems/3.png b/src/assets/gems/3.png new file mode 100644 index 0000000..3ac3d63 Binary files /dev/null and b/src/assets/gems/3.png differ diff --git a/src/assets/gems/4.png b/src/assets/gems/4.png new file mode 100644 index 0000000..6e8953d Binary files /dev/null and b/src/assets/gems/4.png differ diff --git a/src/assets/gems/5.png b/src/assets/gems/5.png new file mode 100644 index 0000000..98709be Binary files /dev/null and b/src/assets/gems/5.png differ diff --git a/src/assets/gems/6.png b/src/assets/gems/6.png new file mode 100644 index 0000000..58d680a Binary files /dev/null and b/src/assets/gems/6.png differ diff --git a/src/assets/gems/7.png b/src/assets/gems/7.png new file mode 100644 index 0000000..eaba987 Binary files /dev/null and b/src/assets/gems/7.png differ diff --git a/src/assets/gems/8.png b/src/assets/gems/8.png new file mode 100644 index 0000000..a69a72d Binary files /dev/null and b/src/assets/gems/8.png differ diff --git a/src/assets/gems/9.png b/src/assets/gems/9.png new file mode 100644 index 0000000..dc26c30 Binary files /dev/null and b/src/assets/gems/9.png differ diff --git a/src/assets/roadmap_2025.jpeg b/src/assets/roadmap_2025.jpeg new file mode 100644 index 0000000..37e09aa Binary files /dev/null and b/src/assets/roadmap_2025.jpeg differ diff --git a/src/assets/worldmap.svg b/src/assets/worldmap.svg new file mode 100644 index 0000000..756909a --- /dev/null +++ b/src/assets/worldmap.svg @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/xahau-logo.svg b/src/assets/xahau-logo.svg new file mode 100644 index 0000000..86551da --- /dev/null +++ b/src/assets/xahau-logo.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/components/CookieConsent.astro b/src/components/CookieConsent.astro new file mode 100644 index 0000000..74148b5 --- /dev/null +++ b/src/components/CookieConsent.astro @@ -0,0 +1,10 @@ +--- +import 'vanilla-cookieconsent/dist/cookieconsent.css'; +--- + \ No newline at end of file diff --git a/src/components/DocsForceLightTheme.astro b/src/components/DocsForceLightTheme.astro new file mode 100644 index 0000000..5d9b900 --- /dev/null +++ b/src/components/DocsForceLightTheme.astro @@ -0,0 +1,12 @@ +--- + +--- + + + \ No newline at end of file diff --git a/src/components/DocsMobileMenuToggle.astro b/src/components/DocsMobileMenuToggle.astro new file mode 100644 index 0000000..f03b8fe --- /dev/null +++ b/src/components/DocsMobileMenuToggle.astro @@ -0,0 +1,107 @@ +--- +import { ChevronDownIcon, Bars3Icon, XMarkIcon } from '@heroicons/react/20/solid' +--- + + + + + + + + + + \ No newline at end of file diff --git a/src/components/DocsPageSidebar.astro b/src/components/DocsPageSidebar.astro new file mode 100644 index 0000000..18041ef --- /dev/null +++ b/src/components/DocsPageSidebar.astro @@ -0,0 +1,55 @@ +--- +import TableOfContents from '@astrojs/starlight/components/TableOfContents.astro'; +--- + +{ + Astro.locals.starlightRoute.toc && ( + <> + + + ) +} + + \ No newline at end of file diff --git a/src/components/DocsSidebar.astro b/src/components/DocsSidebar.astro new file mode 100644 index 0000000..c621ff0 --- /dev/null +++ b/src/components/DocsSidebar.astro @@ -0,0 +1,10 @@ +--- +import SidebarPersister from '@astrojs/starlight/components/SidebarPersister.astro'; +import SidebarSublist from '@astrojs/starlight/components/SidebarSublist.astro'; + +const { sidebar } = Astro.locals.starlightRoute; +--- + + + + \ No newline at end of file diff --git a/src/components/DocsTwoColumnContent.astro b/src/components/DocsTwoColumnContent.astro new file mode 100644 index 0000000..3a4577c --- /dev/null +++ b/src/components/DocsTwoColumnContent.astro @@ -0,0 +1,48 @@ +
+
+ { + Astro.locals.starlightRoute.toc && ( + + ) + } +
+ + \ No newline at end of file diff --git a/src/components/EcosystemButton.astro b/src/components/EcosystemButton.astro new file mode 100644 index 0000000..b3df5e1 --- /dev/null +++ b/src/components/EcosystemButton.astro @@ -0,0 +1,7 @@ +--- +const { class: className, ...rest } = Astro.props +import { Image } from 'astro:assets'; +--- + + {Astro.props.imageSrc ? {Astro.props.title} : Astro.props.title} + diff --git a/src/components/Footer.astro b/src/components/Footer.astro new file mode 100644 index 0000000..4c1e977 --- /dev/null +++ b/src/components/Footer.astro @@ -0,0 +1,38 @@ +--- +import logo from '../assets/xahau-logo.svg' +import { Image } from 'astro:assets'; +--- + + \ No newline at end of file diff --git a/src/components/Header.jsx b/src/components/Header.jsx new file mode 100644 index 0000000..fc76e42 --- /dev/null +++ b/src/components/Header.jsx @@ -0,0 +1,163 @@ +'use client' + +import { useState } from 'react' +import { + Dialog, + DialogPanel, + Disclosure, + DisclosureButton, + DisclosurePanel, + Popover, + PopoverButton, + PopoverGroup, + PopoverPanel, +} from '@headlessui/react' +import { ChevronDownIcon, Bars3Icon, XMarkIcon } from '@heroicons/react/20/solid' + +const socials = [ + { name: 'X', href: 'https://x.com/XahauNetwork' }, + { name: 'GitHub', href: 'https://github.com/Xahau' }, + { name: 'Community Discord', href: 'https://discord.com/invite/UzU58haAn4' }, +] + +const docs = [ + { name: 'Get started', href: '/docs' }, + { name: 'Protocol Reference', href: '/docs/protocol-reference/transactions' }, + { name: 'Hooks', href: '/docs/hooks' }, + { name: 'Data APIs', href: '/docs/data-apis' }, + { name: 'Infrastructure', href: '/docs/infrastructure/node-requirements' }, + { name: 'Whitepaper', href: '/docs/resources/whitepaper' }, +] + +import logo from '../assets/xahau-logo.svg' + +export default function Header(props) { + const [mobileMenuOpen, setMobileMenuOpen] = useState(false) + + return ( +
+ + +
+ +
+ + Your Company + + + + + + +
+
+
+
+ About + Features + Whitepaper + Ecosystem + Roadmap + + + Documentation + + + {[...docs].map((item) => ( + + {item.name} + + ))} + + + + + Connect + + + {[...socials].map((item) => ( + + {item.name} + + ))} + + + Explorer +
+
+
+
+
+
+ ) +} \ No newline at end of file diff --git a/src/components/PageSection.astro b/src/components/PageSection.astro new file mode 100644 index 0000000..9c366ef --- /dev/null +++ b/src/components/PageSection.astro @@ -0,0 +1,79 @@ +--- +const { class: className, ...rest } = Astro.props +import { Image } from 'astro:assets'; +import gem1 from '../assets/gems/1.png'; +import gem2 from '../assets/gems/2.png'; +import gem3 from '../assets/gems/3.png'; +import gem4 from '../assets/gems/4.png'; +import gem5 from '../assets/gems/5.png'; +import gem6 from '../assets/gems/6.png'; +import gem7 from '../assets/gems/7.png'; +import gem8 from '../assets/gems/8.png'; +import gem9 from '../assets/gems/9.png'; +import gem10 from '../assets/gems/10.png'; +import gem11 from '../assets/gems/11.png'; +import gem12 from '../assets/gems/12.png'; +import gem13 from '../assets/gems/13.png'; +import gem14 from '../assets/gems/14.png'; +import gem15 from '../assets/gems/15.png'; +import gem16 from '../assets/gems/16.png'; +import gem17 from '../assets/gems/17.png'; + +const gemMap = { + "1": gem1, + "2": gem2, + "3": gem3, + "4": gem4, + "5": gem5, + "6": gem6, + "7": gem7, + "8": gem8, + "9": gem9, + "10": gem10, + "11": gem11, + "12": gem12, + "13": gem13, + "14": gem14, + "15": gem15, + "16": gem16, + "17": gem17, +}; + +const gem = gemMap[Astro.props.gem as keyof typeof gemMap] || gem1; + +var gemSize = "size-80"; +if (Astro.props.gemSize && Astro.props.gemSize === "large") { + gemSize = "size-120 -top-40"; +} +--- + +
+
+ + {Astro.props.align ? ( +
+ {Astro.props.align === "right" && Astro.props.gem && ( + + )} +
+ +
+ {Astro.props.align === "left" && Astro.props.gem && ( + + )} +
+ ) : ( + + )} +
+
\ No newline at end of file diff --git a/src/content.config.ts b/src/content.config.ts new file mode 100644 index 0000000..6a7b7a0 --- /dev/null +++ b/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from 'astro:content'; +import { docsLoader } from '@astrojs/starlight/loaders'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/src/content/docs/docs/assets/cdn.feather-2.webp b/src/content/docs/docs/assets/cdn.feather-2.webp new file mode 100644 index 0000000..9aa27e6 Binary files /dev/null and b/src/content/docs/docs/assets/cdn.feather-2.webp differ diff --git a/src/content/docs/docs/assets/image.png b/src/content/docs/docs/assets/image.png new file mode 100644 index 0000000..fe3a60c Binary files /dev/null and b/src/content/docs/docs/assets/image.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_0OucxySTRinbe13SITJT_5561b32-sethook-Page-3.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_0OucxySTRinbe13SITJT_5561b32-sethook-Page-3.png new file mode 100644 index 0000000..43f2b1c Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_0OucxySTRinbe13SITJT_5561b32-sethook-Page-3.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_6S9mLMliCrlQ5JqjDld6_909b3a9-4.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_6S9mLMliCrlQ5JqjDld6_909b3a9-4.png new file mode 100644 index 0000000..a902b3e Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_6S9mLMliCrlQ5JqjDld6_909b3a9-4.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_FvVVFLYOs9skdbzL2PbX_468e0b5-3.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_FvVVFLYOs9skdbzL2PbX_468e0b5-3.png new file mode 100644 index 0000000..1b65602 Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_FvVVFLYOs9skdbzL2PbX_468e0b5-3.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_NbV5W3McCRKkL4eJeF6v_cdf692e-sethook.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_NbV5W3McCRKkL4eJeF6v_cdf692e-sethook.png new file mode 100644 index 0000000..2ca36be Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_NbV5W3McCRKkL4eJeF6v_cdf692e-sethook.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_TlDL7tsVNYi1yU64EZQh_3ef0cee-sethook-Page-2.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_TlDL7tsVNYi1yU64EZQh_3ef0cee-sethook-Page-2.png new file mode 100644 index 0000000..18ab80c Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_TlDL7tsVNYi1yU64EZQh_3ef0cee-sethook-Page-2.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_VXmzY1NcJIEjMtFsdj5y_08dee14-2.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_VXmzY1NcJIEjMtFsdj5y_08dee14-2.png new file mode 100644 index 0000000..f5c9857 Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_VXmzY1NcJIEjMtFsdj5y_08dee14-2.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_XJgZhbZv8VsmtWVy9H73_d404753-1.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_XJgZhbZv8VsmtWVy9H73_d404753-1.png new file mode 100644 index 0000000..11fe362 Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_XJgZhbZv8VsmtWVy9H73_d404753-1.png differ diff --git a/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_sEBiInWuRskTqxB29Xgd_7359187-Hooks_High_Level2x_1.png b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_sEBiInWuRskTqxB29Xgd_7359187-Hooks_High_Level2x_1.png new file mode 100644 index 0000000..e4e4f81 Binary files /dev/null and b/src/content/docs/docs/assets/spaces_m6f29os4wP16vCS4lHNh_uploads_sEBiInWuRskTqxB29Xgd_7359187-Hooks_High_Level2x_1.png differ diff --git a/src/content/docs/docs/compliance/responsible-disclosure.mdx b/src/content/docs/docs/compliance/responsible-disclosure.mdx new file mode 100644 index 0000000..b788f4c --- /dev/null +++ b/src/content/docs/docs/compliance/responsible-disclosure.mdx @@ -0,0 +1,69 @@ +--- +title: Responsible Disclosure +description: >- + Our Responsible Disclosure Policy provides clear guidelines for submitting + reports through our support portal, ensuring confidentiality. +--- +import { Aside } from '@astrojs/starlight/components'; + +### Responsible Disclosure Policy + +At Xahau, we believe that the security of our systems is extremely important. + +Despite our concern for the security of our systems during product development and maintenance, there's always the possibility of someone finding something we need to improve/update/change/fix /... + +We appreciate you notifying us if you have found a weak point in one of our systems as soon as possible so we can immediately take measures to protect our customers and their data. + +### How to Report + +If you believe you have found a security issue in one of our systems, please notify us as soon as possible by posting a **high level description of your finding and contact information (so someone can reach out) on Github:** [**https://github.com/Xahau/xahaud/issues**](https://github.com/Xahau/xahaud/issues) + +### Rules + +This responsible disclosure policy is not an open invitation to actively scan our network and applications for vulnerabilities. Our continuous monitoring will likely detect your scan, and these will be investigated. + +#### We ask you to: + +* Not share information about the security issue with others until the problem is resolved, and to immediately delete any confidential data acquired +* Not further abuse the problem, for example, by downloading more data than is necessary to demonstrate the leak or to view, delete, or amend the data of third parties +* Provide detailed information in order for us to reproduce, validate, and resolve the problem as quickly as possible. Include your test data, timestamps, and URL(s) of the system(s) involved +* Leave your contact details (e-mail address and/or phone number) so that we may contact you about the progress of the solution. We do accept anonymous reports. +* Do not use attacks on physical security, social engineering, distributed denial of service, spam, or applications of third parties + +### Responsible Disclosure procedure(s) + +#### When you report a security issue, we will act according to the following: + +* You will receive a confirmation of receipt from us within 4 working days after the report is made +* You will receive a response with the assessment of the security issue and an expected date of resolution within 4 working days after the confirmation of receipt is sent +* We will take no legal steps against you in relation to the report if you have kept to the conditions as set out above +* We will handle your report confidentially, and we will not share your details with third parties without your permission unless that is necessary in order to fulfill a legal obligation + +#### This responsible disclosure scheme is not intended for: + +* Complaints +* Website unavailable reports +* Phishing reports +* Fraud reports + +For these complaints or reports, please post a **high level description of your issue and contact information (so someone can reach out) on Github:** [**https://github.com/Xahau/xahaud/issues**](https://github.com/Xahau/xahaud/issues) + +### Bug bounty program + +Xahau encourages the reporting of security issues or vulnerabilities. We may make an appropriate reward for confidential disclosure of any design or implementation issue that could be used to compromise the confidentiality or integrity of our users' data that was not yet known to us. We decide whether the report is eligible and the amount of the reward. + +### Exclusions + +#### The following types of security problems are excluded + +* (D)DOS attacks +* Error messages or error pages without sensitive data +* Tests & sample data as publicly available in our repositories on Github +* Common issues like browser header warnings or DNS configuration, identified by vulnerability scans +* Vulnerability scan reports for the software we publicly use +* Security issues related to outdated OS's, browsers, or plugins +* Reports for security problems that we have been notified of before + +Please note: Reports that lack any proof (such as screenshots or other data), detailed information, or details on how to reproduce any unexpected result will be investigated but will not be eligible for any reward. + +This policy is based on the National Cyber Security Centre’s Responsible Disclosure Guidelines and an [example by Floor Terra](https://responsibledisclosure.nl/). diff --git a/src/content/docs/docs/compliance/security-audit.mdx b/src/content/docs/docs/compliance/security-audit.mdx new file mode 100644 index 0000000..feff545 --- /dev/null +++ b/src/content/docs/docs/compliance/security-audit.mdx @@ -0,0 +1,24 @@ +--- +title: Security Audits +--- +import { Aside } from '@astrojs/starlight/components'; + +The Hooks amendment, integral to XRPL's smart contract infrastructure, has passed a detailed security audit by FYEO. The audit examined the Hooks framework implementation, including the Hook API, helper functions, and execution environment. + +With no severe security issues detected and all minor issues resolved, this audit serves as a testament to our commitment to security and the robustness of Hooks. + +By enabling smart transaction logic directly on XRPL's Layer 1, Hooks bring increased flexibility to tailor applications to their unique needs, inspiring further innovation within the XRPL ecosystem. + +Developers now have robust tools for creating and deploying custom logic, accessible on our testnet. + +### **Assurance of Ongoing Security** + +The audit's successful completion is not just a milestone but a cornerstone for the ongoing security and sustainability of the Hooks network. + +With all identified vulnerabilities addressed, the Hooks amendment is set to drive innovation securely on Xahau. + + + +To a brighter, more innovative future with Xahau! diff --git a/src/content/docs/docs/data-apis/index.mdx b/src/content/docs/docs/data-apis/index.mdx new file mode 100644 index 0000000..db1bb05 --- /dev/null +++ b/src/content/docs/docs/data-apis/index.mdx @@ -0,0 +1,5 @@ +--- +title: "Data APIs" +--- + +The primary Data API is located at https://data.xahau.network/ \ No newline at end of file diff --git a/src/content/docs/docs/features/amendments.mdx b/src/content/docs/docs/features/amendments.mdx new file mode 100644 index 0000000..db7cf5b --- /dev/null +++ b/src/content/docs/docs/features/amendments.mdx @@ -0,0 +1,56 @@ +--- +title: Amendments +--- +Amendments represent new features or other changes to transaction processing. + +The amendment system uses the consensus process to approve any changes that affect transaction processing on Xahau. Fully-functional, transaction process changes are introduced as amendments; validators then vote on these changes. If an amendment receives more than 80% support for five days, the amendment passes and the change applies permanently to all subsequent ledger versions. Disabling a passed amendment requires a new amendment to do so. + +**Note:** Bug fixes that change transaction processes also require amendments. + +### Amendment Process + +The Contributing Code to Xahau topic walks through the workflow to develop an amendment from an idea to activation on Xahau. + +After the code for an amendment is built into a software release, the process to enable it happens within the Xahau network, which checks the status of amendments every _flag_ ledger (typically about 15 minutes apart). + +Every 256th ledger is called a **flag** ledger. The flag ledger doesn't have special contents, but the amendment process happens around it. + +1. **Flag Ledger -1:** When `xahaud` validators send validation messages, they also submit their amendment votes. +2. **Flag Ledger:** Servers interpret the votes from trusted validators. +3. **Flag Ledger +1:** Servers insert an `EnableAmendment` pseudo-transaction and flag based on what they think happened: + + * The `tfGotMajority` flag means the amendment has more than 80% support. + * The `tfLostMajority` flag means support for the amendment has decreased to 80% or less. + * No flag means the amendment is enabled. + + **Note:** It's possible for an amendment to lose 80% support on the same ledger it reaches the required five day period to be enabled. In these cases, an `EnableAmendment` pseudo-transactions is added for both scenarios, but the amendment is ultimately enabled. +4. **Flag Ledger +2:** Enabled amendments apply to transactions on this ledger onwards. + +### Amendment Voting + +Each version of `xahaud` is compiled with a list of known amendments and the code to implement those amendments. Operators of `xahaud` validators configure their servers to vote on each amendment and can change it at any time. If the operator doesn't choose a vote, the server uses a default vote defined by the source code. + +**Note:** The default vote can change between software releases. \[Updated in: rippled 1.8.1]\[] + +Amendments must maintain five days of support from more than 80% of trusted validators to be enabled. If support drops below 80%, the amendment is temporarily rejected, and the two week period restarts. Amendments can gain and lose a majority any number of times before they become permanently enabled. + +Amendments that have had their source code removed without being enabled are considered **Vetoed** by the network. + +### Amendment Blocked Servers + +Amendment blocking is a security feature to protect the accuracy of Xahau's data. When an amendment is enabled, servers running earlier versions of `xahaud` without the amendment's source code no longer understand the rules of the network. Rather than guess and misinterpret ledger data, these servers become **amendment blocked** and can't: + +* Determine the validity of a ledger. +* Submit or process transactions. +* Participate in the consensus process. +* Vote on future amendments. + +The voting configuration of a `xahaud` server has no impact on it becoming amendment blocked. A `xahaud` server always follows the amendments enabled by the rest of the network, so blockages are based solely on having the code to understand rule changes. This means you can also become amendment blocked if you connect your server to a parallel network with different amendments enabled. For example, the Xahau Testnet typically has experimental amendments enabled. If you are using the latest production release, your server likely won't have the code for those experimental amendments. + +You can unblock amendment blocked servers by upgrading to the newest version of `xahaud`. + +### Retiring Amendments + +When amendments are enabled, the source code for pre-amendment behaviors remain in `xahaud`. While there are use-cases for keeping old code, such as reconstructing ledger outcomes for verification, tracking amendments and legacy code adds complexity over time. + +The [XRP Ledger Standard 11d](https://github.com/XRPLF/XRPL-Standards/discussions/19) defines a process for retiring old amendments and associated pre-amendment code. After an amendment has been enabled on the Mainnet for two years, it can be retired. Retiring an amendment makes it part of the core protocol unconditionally; it's no longer tracked or treated as an amendment, and all pre-amendment code is removed. diff --git a/src/content/docs/docs/features/balance-adjustments.mdx b/src/content/docs/docs/features/balance-adjustments.mdx new file mode 100644 index 0000000..125c4eb --- /dev/null +++ b/src/content/docs/docs/features/balance-adjustments.mdx @@ -0,0 +1,71 @@ +--- +title: Balance Adjustments +description: How to claim a Balance Adjustment on Xahau +--- +### Opt-in + Claim + +Opting into Balance Adjustments is the same transaction as claiming an adjustment. You must do this first to kick off the ability to claim later. + +```json +{ + "Account": "", + "TransactionType": "ClaimReward", + "Issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "NetworkID": 21337 +} +``` + +### Opt-out + +To opt-out of Balance Adjustments, omit the Issuer field and set Flags to 1. Doing this will delete your average balance statistics. These will not be restored. If you opt-in again, they will be reset to a starting position. + +```json +{ + "Account": "", + "TransactionType": "ClaimReward", + "NetworkID": 21337, + "Flags" 1 +} +``` + +### Technical Details + +Balance Adjustments are implemented as a combination of two pieces of code: + +1. BalanceRewards Amendment (native code) +2. Genesis Account's Reward Hook (hook code). + +BalanceRewards collect average balance statistics about the accounts they are activated on. These statistics are then passed to a target Hook when the user wishes to claim. + +All interactions with this amendment are via the ClaimReward transaction: + +```json +{ + "Account": "<rAddr...>", + "TransactionType": "ClaimReward", + "Issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "NetworkID": 21337 +} +``` + +When a ClaimReward transaction is successfully submitted with a **tesSUCCESS** error code, the account's average balance statistics are reset. The only other thing the amendment does is invoke the Hooks on the specified Issuer's account. + +The _Issuer_ field is the account responsible for fulfilling the claim. Depending on what's installed on the Issuer account, several things can happen: + +* If no Hook is installed on the Issuer's account, then nothing is done, and the BalanceRewards statistics are simply reset. +* If a Hook is installed on the Issuer's account and the Hook performs a rollback, then the transaction fails, and the statistics are _not_ reset. +* If a Hook is installed on the Issuer's account and the Hook performs accept, then the transaction succeeds, and the statistics are reset. In this case, the Hook should also emit a transaction back to the user's account containing their reward. + +In practice, on Xahau, the Issuer will probably always be the genesis account **rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh**. + +Unless: + +* Network Governance results in a different account being used for BalanceAdjustments. +* A non-Governance party runs its own BalanceRewards giveaway that the user wants to be involved with. Note that successful claims result in the average balance statistics being reset, so only one type of reward can be claimed per reset. + +The average balance statistics exist as a collection of three new fields on the AccountRoot object. These are: + +
FieldTypeExplanation
sfRewardAccumulatorUINT64The area under of the balance-time graph for your account since last ClaimReward transaction.
sfRewardLgrFirstUINT32The ledger number of the last ClaimReward transaction.
sfRewardLgrLastUINT32The ledger sequence number of the last transaction in or out of your account.
sfRewardTimeUINT32The ledger time the last reward was claimed.
+ + + diff --git a/src/content/docs/docs/features/burn-2-mint.mdx b/src/content/docs/docs/features/burn-2-mint.mdx new file mode 100644 index 0000000..746d3c4 --- /dev/null +++ b/src/content/docs/docs/features/burn-2-mint.mdx @@ -0,0 +1,291 @@ +--- +title: Burn 2 Mint (B2M) +description: >- + Burn2Mint is a low-level inter-chain primitive and is intended for enterprise + users to self-supply their own liquidity as needed for their own purposes. +--- +import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; + + + +## Burn2Mint Technical Manual (Xahau Testnet) + + + +Burn2Mint is a low-level inter-chain primitive intended for enterprise users to self-supply their liquidity as needed for their purposes. Running your own nodes and performing this operation yourself on your nodes means you and you alone bear responsibility for the outcome of the procedure. + +The generation & collection of XPOPs fundamentally relies on collecting validation messages on the overlay network, which are ephemeral by nature. If your nodes are not reliably connected, or if your hardware, network connection, or operating system fails at the wrong point in time, then the XPOP for a Burn Transaction might not be generated or might not be generated correctly. This can lead to loss of funds as the Burn Transaction's XPOP was not captured in time, and it’s possible the validation messages are lost forever, making a Mint Transaction impossible despite a successful Burn Transaction. + +If you are not comfortable with taking these technical risks or do not understand what you are doing, or are not an enterprise user, then please source your liquidity via other friendly alternatives. + +### Setup + +To perform B2M, _two_ XRPL protocol nodes should be operated by the user: + +1. **Obtain xPOP from burn** + + + +Run this (e.g., using Docker Compose; see repo Docs)\ +[**https://github.com/Xahau/Validation-Ledger-Tx-Store-to-xPOP**](https://github.com/Xahau/Validation-Ledger-Tx-Store-to-xPOP) + +* The service listens for XRPL validation messages, closed ledgers, and transactions. +* It stores this data in an organized file system. +* It is essential for generating xPOPs, as XRPL validation messages are ephemeral; without storing them, a transaction burn can't be turned into a mint. +* **How it Works**: + * A watcher connects to multiple XRPL nodes and listens for specific data. + * The captured data is then saved, organized, and used to generate xPOPs + +Simply fetch the xPOP now from:\ +`http[s]://{your-host}:{your-port}/xpop/{tx-hash}` + +You can easily fetch/create xPOPs from a node using the repo above using this NPM package: + +[**https://www.npmjs.com/package/xpop**](https://www.npmjs.com/package/xpop) + + + +**Burn Node**, comprising: + +* A modified Rippled instance (modified to record XPOPs) +* Universal linux binary here: [https://tvntezq.dlvr.cloud/rippled_with_xpop](https://tvntezq.dlvr.cloud/rippled_with_xpop) +* [https://github.com/RichardAH/rippled/tree/proof-of-burn](https://github.com/RichardAH/rippled/tree/proof-of-burn) +* Running a with a rippled.cfg that has: + * an **\[xpop_dir]** stanza specifying an output directory for generated XPOPs. + * a **\[network_id]** stanza specifying network_id: 1 + * (in production this would be network 0) + * a `validators.txt` containing:\\ + + ``` + [validator_list_sites] + https://vl.altnet.rippletest.net + [validator_list_keys] + ED264807102805220DA0F312E71FC2C69E1552C9C5790F6C25E3729DEB573D5860 + ``` + + + +2. **Mint** + +* In this test scenario, you will connect directly to the Xahau. You do not need to run your own node. In the production scenario, you will need to run a Mint node, which is just a stock node for the target network. This is because public nodes will probably opt out of accepting Import transactions due to legal risk. + * Connect to **wss://xahau-test.net** + * Or download download/run: [**https://github.com/Xahau/Xahau-Testnet-Docker**](https://github.com/Xahau/Xahau-Testnet-Docker) + +## Sample (nodejs) + +This example creates a testnet account, burns 10 XRP & then imports this on Xahau Testnet, using the xPOP fetched using the tools mentioned above. + +```js +import { derive, utils, signAndSubmit } from 'xrpl-accountlib' +import { TxData } from 'xrpl-txdata' +import { XrplClient } from 'xrpl-client' +import { xpop, setEndpoints as xpopEndpoints } from 'xpop' +import fetch from 'node-fetch' + +// The above needs: +// npm install xrpl-accountlib xrpl-txdata xrpl-client xpop node-fetch + +console.log('Obtaining XRPL Testnet account (faucet)') +const faucet = await (await fetch('https://faucet.altnet.rippletest.net/accounts', { method: 'POST' })).json() +console.log(' -->', faucet.account.address) +const account = derive.familySeed(faucet.account.secret) + +xpopEndpoints((await (await fetch('https://xrpl.ws-stats.com/xpop/list?json=true')).json()).bestguess) + +const nodes = { + testnet: [ + new XrplClient('wss://s.altnet.rippletest.net:51233'), + new XrplClient('wss://testnet.xrpl-labs.com'), + ], + xahau: [ + new XrplClient('wss://xahau-test.net'), + ] +} + +console.log('Waiting for network connections to be ready') +await Promise.all(Object.keys(nodes).map(k => Promise.race(nodes[k].map(n => n.ready())))) + +console.log('Waiting for faucet account funding & obtaining network values...') +await new Promise(resolve => setTimeout(resolve, 4000)) // Wait till ledger is closed + +const [ + testnetParams, + xahauParams, +] = await Promise.all([ + Promise.race(nodes.testnet.map(n => utils.accountAndLedgerSequence(n, account))), + Promise.race(nodes.xahau.map(n => utils.accountAndLedgerSequence(n, account))), +]) + +const testnetTx = { + ...testnetParams.txValues, + TransactionType: 'AccountSet', + Fee: String(10_000_000), + OperationLimit: xahauParams.txValues.NetworkID, + NetworkID: undefined, // Testnet has a NetworkID < 1024, so none should be provided +} + +console.log('Submitting burn...', testnetTx) +const testnetSubmitted = await Promise.race(nodes.testnet.map(n => signAndSubmit(testnetTx, n, account))) +console.log('Submitted burn to testnet') +console.log(' -->', 'https://testnet.xrpl.org/transactions/' + testnetSubmitted.tx_id) + +console.log('Obtaining burn tx data...') + +const txdata = new TxData(nodes.testnet.map(n => n.getState().server.uri), { + AllowNoFullHistory: true, + EndpointTimeoutMs: 2_000, + OverallTimeoutMs: 10_000, +}) + +const appliedtx = await txdata.getOne(testnetSubmitted.tx_id) +console.log(' -->', 'Burn validated in ledger', appliedtx?.result?.ledger_index) + +console.log('Waiting for closed ledger before fetching xPOP...') +await new Promise(resolve => setTimeout(resolve, 4000)) // Wait till ledger is closed + +console.log('Fetching xPOP...') + +const Blob = await xpop(testnetSubmitted.tx_id, appliedtx?.result?.ledger_index, 1) + +console.log(' -->', 'xPOP fetched, hex strlen:', Blob.length) + +const hooksTx = { + ...xahauParams.txValues, + TransactionType: 'Import', + Fee: '0', + Blob, +} + +console.log('Submitting for mint of xPOP...') + +const b2mSubmitted = await Promise.race(nodes.xahau.map(n => signAndSubmit(hooksTx, n, account))) + +console.log(' -->', 'B2M submitted! TX on Xahau Testnet:') +console.log(' -->', 'https://test.xahauexplorer.com/explorer/' + b2mSubmitted?.tx_id) +console.log(' -->', b2mSubmitted.response.engine_result, b2mSubmitted.response.engine_result_message) + +// Closing connections +Object.keys(nodes).map(k => nodes[k].map(n => n.close())) +``` +[Source](https://gist.github.com/WietseWind/cd8a7a8c88f218fe7b768f59a665685d) + +## Technical Summary of B2M's procedure + +#### New Transaction Type: `Import` + +Xahau Testnet (_network_id=21338_) introduces a new transaction type called _**Import**_, which accepts an XPOP from the Ripple testnet chain (_network_id=1_) and provides for a “burn-to-mint” unidirectional value transfer and key / account synchronization. + +### Burn Transaction + +A _**Burn Transaction**_ is a transaction that burns XRP on a source XRPL chain, which would be used as proof (XPOP) to mint on a destination XRPL chain. + +The following are supported transaction types: + +* AccountSet +* SetRegularKey +* SignerListSet. + + + +Note that other transaction types are not currently supported and cannot be used to mint on Xahau Testnet. (However, this may change). + +All three transaction types can be used for minting. This means the _**Fee**_ burned by the Burn Transaction is subsequently minted on Xahau Testnet after a successful `Import`. + +If `SetRegularKey` or `SignerListSet` is used, then key synchronization occurs according to the standard rules of the transaction type. If `AccountSet` it is used, then no key synchronization occurs on the destination XRPL chain (Xahau Testnet). + +A field called _**OperationLimit**_ must be present on the Burn Transaction to be the destination chain’s Network ID. This field is to prevent replay attacks on other B2M-integrated chains. + +The Burn Transaction may be used for Minting if it has either a **tesSUCCESS** transaction code or _any_ of the **tec** transaction codes. Meaning _if_ the fee was burnt, then the transaction can be used for minting. However, key synchronization _only_ occurs when the Burn Transaction result was tesSUCCESS. + +Example Burn Transaction: + +```json +{ + "TransactionType": "AccountSet", + "Fee": 10000000, + "OperationLimit": 21338 +} +``` + +### XPOP Collection + +Before submitting the Burn Transaction, ensure your Burn Node is synchronized with the testnet chain (Network ID: `1`). + +After checking your Burn Node's state, submit the signed Burn Transaction to the Burn Node. + +The Burn Node watches closed ledgers for transactions containing the **OperationLimit** field and uses collected validation messages to generate an XPOP (Proof Of Burn). These are written to a file under the directory specified in **\[xpop_dir]** stanza in the Burn Node’s `rippled.cfg`. + +Wait for the ledger to close, then browse through the xpop_dir for the Burn Transaction's XPOP according to its TXID. The file contains a JSON document, which is the XPOP that you'll be relaying to the destination XRPL chain (HooksV3). + +Take the raw contents of this file and encode it as HEX. This will become the contents of the \*_Blob_ field in the `Import` transaction. + +### Mint Transaction + +Your binary codec will be missing the necessary fields to construct the `Import` (Mint) transaction. If you are using ripple-binary-codec, you can update its `definitions.json` file in the following way: + +1. Change directory into `node_modules` +2. Run `find . | grep 'dist/enums/definitions.json'` to locate the relevant file to update +3. Connect to **wss://hooks-testnet-v3.xrpl-labs.com** +4. Request: `{"command":"server_definitions"}` +5. Dump the contents of the `"result"` key into `definitions.json` from step 2. + +The `Import` transaction type takes only one non-common field _**Blob.**_. This must contain the HEX-encoded XPOP from the XPOP Collection phase. + +* You can do this with `cat xpopjsonfile | xxd -p | tr -d '\n'` + +The `Account` and `SigningPubKey` field (or Signers array) must match exactly between the Burn Transaction and the Mint Transaction. Users can only mint to the same account, which they burned from. + +If the `Account` field specifies an account that does not yet exist on Xahau Testnet, and it will be created. In this case, use 0 for the `Sequence` field on the Mint Transaction. If the account already exists on Xahau Testnet, then use the next available Sequence number on the account on Xahau Testnet. + +Example Import: + +```json +{ + "Account": "", + "TransactionType": "Import", + "Blob": "", + "Sequence": 0 +} +``` + +IMPORTANT: **The Mint Transaction must be signed exactly the same way and by the same account as the Burn Transaction!** + +Encode and sign the transaction appropriately, yielding a signed transaction blob (hex). + +If you are not running your own Mint node: + +* Connect to **wss://xahau-testn.et** +* Submit the transaction to the node: + +```json +{ + "command": "submit", + "tx_blob": "" +} +``` + +Or, if you are running your own Mint node: + +* Ensure the Mint Node is running and synchronised to Network ID 21338. +* Use the `submit` RPC call to submit the Mint Transaction. + * You can do this from command line using `./hooksv3d submit ` + +### Considerations + +If the Account is to be created on Xahau Testnet but the keying for the account is unclear from the context of the Burn Transaction, then the Account is created in a blackholed mode. It can be subsequently rekeyed using either keying transaction type. + +If the Burn Transaction is either a `SignerListSet` or a `SetRegularKey` transaction, then provided it had a tesSUCCESS transaction result on the source XRPL chain (testnet), that same keying operation is now applied to that same account on the destination XRPL chain (Xahau Testnet). + +During testing, Accounts on Xahau Testnet _can_ be deleted, however, on the production Hooks-enabled chain, they will not be able to be deleted. + +Accounts on Xahau Testnet have an optional _**ImportSequence**_ field in the AccountRoot. If **Import** has ever been used on that account on Xahau Testnet, this field is present and is populated with the most recently imported Burn Transaction’s Sequence number. This is to prevent replay attacks, but it also means that you should never submit your Burn2Mints out of sequence, otherwise the skipped transactions will never be accepted for Minting. diff --git a/src/content/docs/docs/features/developer-tooling/client-libraries.mdx b/src/content/docs/docs/features/developer-tooling/client-libraries.mdx new file mode 100644 index 0000000..0905d15 --- /dev/null +++ b/src/content/docs/docs/features/developer-tooling/client-libraries.mdx @@ -0,0 +1,10 @@ +--- +title: Client Libraries +--- +These client libraries simplify some of the common work of accessing and processing XAH Ledger data and present it in a form that matches the native conventions of their respective programming languages. + +For other programming languages, you can access the XAH Ledger through the HTTP APIs. + +
LanguageLibrary NameGet StartedProtocolSource Code
Pythonxahau-pyGet StartedXAH / XRPRepo
JavaScript / TypeScriptxahau.jsGet StartedXAH / XRPRepo
JavaScript / TypeScriptxrpl-accountlibGet started
Sample
XAH / XRPRepo
+ +**Tip:** To add a client library not listed here, please suggest changes to this page! diff --git a/src/content/docs/docs/features/developer-tooling/curated-tooling.mdx b/src/content/docs/docs/features/developer-tooling/curated-tooling.mdx new file mode 100644 index 0000000..8bc5433 --- /dev/null +++ b/src/content/docs/docs/features/developer-tooling/curated-tooling.mdx @@ -0,0 +1,18 @@ +--- +title: Curated Tooling +--- +These tools simplify some of the common work of accessing and processing Hooks. + +| Tool | Reference Link | +| ----------------------- | ---------------------------------------------------------------- | +| **Hooks Builder** | [Builder Link](https://hooks-builder.xrpl.org/develop) | +| **Hooks Documentation** | [Reference Link](https://xrpl-hooks.readme.io/) | +| **Hooks Toolkit** | [Toolkit Link](https://hooks-toolkit.com/) | +| **Xpop Toolkit** | [Toolkit Link](https://github.com/Transia-RnD/xpop-toolkit) | +| **Hooks Blog** | [Blog Link](https://dev.to/t/xrplhooks/top/infinity) | +| **XFL Tools** | [Tool Link](https://richardah.github.io/xfl-tools/) | +| **Binary Visualizer** | [Tool Link](https://richardah.github.io/xrpl-binary-visualizer/) | +| **Keylet Tools** | [Tool Link](https://richardah.github.io/xrpl-keylet-tools/) | +| **CTID Visualizer** | [Tool Link](https://transia-rnd.github.io/xrpl-ctid-visualizer/) | +| **C Hook Tx Builder** | [Tool Link](https://transia-rnd.github.io/xrpl-tt-visualizer/) | + diff --git a/src/content/docs/docs/features/developer-tooling/developer-tricks.mdx b/src/content/docs/docs/features/developer-tooling/developer-tricks.mdx new file mode 100644 index 0000000..fb68899 --- /dev/null +++ b/src/content/docs/docs/features/developer-tooling/developer-tricks.mdx @@ -0,0 +1,12 @@ +--- +title: Developer Tricks +--- +## Wildcard signing + +To easily test & replay, use `NetworkID` with value `65535` (config: `[network_id]`) to disable signature verification. + +Added: [https://github.com/Xahau/xahaud/pull/201](https://github.com/Xahau/xahaud/pull/201) + +## Server Definitions + +Server definitions can eas diff --git a/src/content/docs/docs/features/faucet-and-explorer.mdx b/src/content/docs/docs/features/faucet-and-explorer.mdx new file mode 100644 index 0000000..1492485 --- /dev/null +++ b/src/content/docs/docs/features/faucet-and-explorer.mdx @@ -0,0 +1,27 @@ +--- +title: Faucet & Explorers +--- +The Xahau Faucet & Explorers can be found here: + +## Testnet + +* **Faucet:** [**https://xahau-test.net**](https://xahau-test.net) + * To automate funding accounts on testnet, HTTP POST to:\ + [https://xahau-test.net/accounts](https://xahau-test.net/accounts)\ + Empty body: new account (prefunded)\ + JSON body with `destination` property: fund the mentioned `destination` account. +* **Explorers:** + * **Xahauexplorer:** [**https://test.xahauexplorer.com**](https://test.xahauexplorer.com) + * **XRPLF:** [**https://explorer.xahau-test.net**](https://explorer.xahau-test.net) + * **XRPL.org:** [**https://xahau-testnet.xrpl.org**](https://xahau-testnet.xrpl.org) + * **XRPLWin:** [**https://xahau-testnet.xrplwin.com**](https://xahau-testnet.xrplwin.com/) + +## Mainnet + +* **Homepage:** [**https://xahau.network**](https://xahau.network/) +* **Explorers:** + * **Xahauexplorer:** [**https://xahauexplorer.com**](https://xahauexplorer.com/) + * **Xahscan:** [**https://xahscan.com/**](https://xahscan.com/) + * **XRPLF:** [**https://explorer.xahau.network**](https://explorer.xahau.network/) + * **XRPL.org:** [**https://xahau.xrpl.org**](https://xahau.xrpl.org) + * **XRPLWin:** [**https://xahau.xrplwin.com**](https://xahau.xrplwin.com/) diff --git a/src/content/docs/docs/features/governance-game.mdx b/src/content/docs/docs/features/governance-game.mdx new file mode 100644 index 0000000..38b730f --- /dev/null +++ b/src/content/docs/docs/features/governance-game.mdx @@ -0,0 +1,199 @@ +--- +title: Governance Game +description: >- + The Governance Game is an innovative governance mechanism within the Xahau + ecosystem to ensure a community-centric approach towards decision-making. +--- + +### Overview + +The Xahau Governance Game allows up to 400 stakeholders to democratically participate in the management of the Xahau network via the Governance Hook installed on the Genesis Account. + +### Layer 1 + +The game consists of a "Layer 1" table at which there are 20 seats. A Xahau account (r-address) may fill each seat, or it may be empty. When a seat is filled, it is said that a member of the table sits there. + +To play the game, the members of the table cast votes. The votes are for one of three types of topics: + +* Seat topics +* Hook topics +* Reward topics. + +Seat topics are S00 through S19 and represent a vote for who (if anyone) currently sits in that seat. A vote of 80% is sufficient to make a change. The voting process is continuous, with the final vote that crosses the threshold actioning the change. + +Hook topics are H0 through H9 and represent which Hooks, including the Governance Hook itself, are installed on the table's account. These topics require 100% of the members seated at that table to agree before a change can be made. This allows the Governance Game to be updated and for more Genesis account features to be added over time. + +Reward topics are RR and RD, which stand for Reward-Rate and Reward-Delay, respectively. These topics also require 100% of the members at the table to agree in order to make a change. These parameters affect the BalanceAdjustments system: how much each active user on the network can claim and how often. + +### Layer 2 + +The members who fill seats on the Layer 1 table are Xahau accounts (r-addresses). The governance game is designed to be structurally recursive, such that one of these accounts may itself be a table consisting of another 20 seats. This is called a Layer 2 table, and the seats are Layer 2 seats. + +Within a Layer 2 table, the same seat voting and hook voting topics exist, with the same voting rules as the Layer 1 table. This allows a table to govern its own membership and the hooks that run there. + +In addition to these topics, a Layer 2 table may also, by a 51% vote, raise a vote to the Layer 1 table. This is a vote on behalf of the r-address that the Layer 2 table exists on and counts as a single vote at the Layer 1 table. + +The Layer 2 table vote may fall below 51%, in which case the vote originally raised to the Layer 1 table is **not** retracted. Only a new (different) vote attaining 51% can change the table's vote at Layer 1. + +Layer 2 tables can only vote on Reward topics via a vote raised to Layer 1. + +In summary, Layer 2 members can vote for: + +* Seats and Hooks for their own table, and +* Seats, Hooks, and Reward topics for the L1 table via the Layer 1 seat their Layer 2 table resides in. + +### Game Constraints + +* Any table may have at least 2 members and at most 20 members. +* A single r-address can only occupy one seat at a given table but may occupy one seat at each of many different tables. +* The Governance Game is not designed to recurse beyond two layers. There's no technical infeasibility in implementing a Layer 3 table, but the current Governance Hook does not support it. + +### Validator Rewards + +Validator rewards are an incentive for running a validator on the network. The rewards are generated by the network and granted to the intersection of Layer 1 members and active UNL validators. To qualify for validator rewards within a given block of 256 ledgers, the following must be true: + +* The validator is on the Xahau UNL. +* The validator validates successfully in the eyes of other UNL validators. +* When the validator's master public key is converted to an r-address, that account sits at the L1 Table. + +Rewards are ad-hoc and based on Xahau users' Balance Adjustments. When a user performs a Balance Adjustment, an amount equal to their adjustment divided by 20 is sent to the r-address of each of the active validators that meet the above criteria. + +## Technical Specification + +The Governance Hook is installed on the genesis account by the XahauGenesis amendment several ledgers after ledger 1 on a new network. This is the L1 table. To create an L2 table, install the Hook on a different account, then seat that account at the L1 table. + +### Governance Hook Parameters + +When the Governance Hook is installed, it is installed with a set of HookParameters. These specify the initial composition of the table. + +Each HookParameter has a 3-byte name consisting of either 3 Ascii characters or 2 Ascii characters and an identifier as below. LE = Little Endian. + +``` +Parameter Name: {'I', 'R', 'R'} +Parameter Value: Initial Reward Rate <8 byte XFL fraction between 0 and 1, LE> +Parameter Name: {'I', 'R', 'D'} +Parameter Value: Initial Reward Delay <8 byte LE XFL seconds between rewards> +Parameter Name: {'I', 'M', 'C'} +Parameter Value: Initial Member Count <1 byte> +Parameter Name: {'I', 'S', 0x00} +Parameter Value: Initial seat #0's member's 20 byte Account ID. +Parameter Name: {'I', 'S', 0x01} +Parameter Value: Initial seat #1's member's 20 byte Account ID. +... etc ... up to at most Seat 19. + +``` + +To kick-off the game, an Invoke transaction must be sent to the Hook. This may be sent by any account. No Blob or HookParameters are required. This Invoke transaction triggers the Hook for the first time and prompts it to create state entries for each initial seat, reward rate, and reward delay. + +### Governance Hook State + +The Hook State of the Governance Hook is stored in the zero namespace: `0000000000000000000000000000000000000000000000000000000000000000.` + +There are several types of state entry. The first is what are referred to as forward and reverse member keys. These map each seat number to the member who sits there and each member to the seat they sit at. + +``` +Key: 0x0000000000000000000000000000000000000000000000000000000000000005 +Val: <20 byte AccountID of the member at seat 5 or all 0's or absent.> + +Key: <20 byte AccountID of the member at seat 3> +Val: 0x03 +``` + +Next, there are some singleton state entries. Member Count, Reward Rate, and Reward Delay, respectively: + +``` +Key in Ascii: MC +Key: 0x0000000000000000000000000000000000000000000000000000000000004D43 +Val: <1 byte member count (how many seats are occupied)> + +Key in Ascii: RR +Key: 0x0000000000000000000000000000000000000000000000000000000000005252 +Val: <8 byte LE XFL reward rate (between 0 and 1 (1 being 100%))> + +Key in Ascii: RD +Key: 0x0000000000000000000000000000000000000000000000000000000000005244 +Val: <8 byte LE XFL reward delay in seconds> +``` + +Finally, votes and vote counters are also stored in Hook state. When a vote is cast by a seat it is recorded in Hook state as follows: + +``` +Vote key is 32 bytes comprising: + 'V' (0x56) - vote + 'H' (0x48) or 'R' (0x52) or 'S' (0x53) - topic type + 'R' (0x52) or 'D' (0x44) or 0 (0x00) to 19 (0x13) - topic detail + 1 (0x01) or 2 (0x02) - target layer for this vote + 0x00 00 00 00 00 00 00 00 - 8 bytes of padding + 20 byte Account ID - the voter +Vote data: + 20 byte Account ID or 8 byte XFL +``` + +When a vote is cast, it increments a vote counter-state entry. This counter keeps track of how many votes there currently are for this topic-data pair and allows the Hook to action the vote when voting crosses the required threshold. The counter state is as follows: + +``` +Counter key is 32 bytes comprising: + 'C' (0x43) - count + 'H' (0x48) or 'R' (0x52) or 'S' (0x53) - topic type + 'R' (0x52) or 'D' (0x44) or 0 (0x00) to 19 (0x13) - topic detail + 1 (0x01) or 2 (0x02) - target layer for this vote + 0's for padding + vote data or left-truncated vote data +``` + +### Governance Hook Transactions + +The Governance Hook is interacted with by its members using ttINVOKE transactions. In addition to this, the Hook may also emit its own ttINVOKE transactions if it is an L2 table raising a vote to the L1 table. + +A vote transaction contains a HookParameters array at the top level of the transaction: + +``` +{ + Account: , + TransactionType: Invoke, + NetworkID: 21337, + Destination: , + HookParameters: + [ + { + HookParameter: + { + HookParameterName: "4C", // L - the target layer + HookParameterValue: "01", // 01 for L1 table, 02 for L2 table + // note: this is the table the vote is + // intended for, not the table you're at + // i.e. for a L2 table you can vote on + // your own membership or on L1's + } + }, + { + HookParameter: + { + HookParameterName: "54", // T - topic type + HookParameterValue: "4801", // H [0x00-0x09] or + // S [0x00-0x13] or + // RR or RD + } + }, + { + HookParameter: + { + HookParameterName: "56", // V - vote data + HookParameterValue: <32 or 20 or 8 bytes of vote data> + } + } + ] +} + +``` + +### Clearing a Vote + +There is no way to "delete a vote" per se. You can change your vote back to reflect the current position instead. + +So, for example, if no one sits at seat 8 and you have voted for account A to sit there, and then you change your mind, you can make a vote to vacate seat 8 (even though it's already vacant) thus aligning your vote with the current state of the seat. + +To do this, you vote with all 0's in the vote data, to the same length as the vote topic normally requires. So, for a seat vote, this is 20 bytes of 0. + + + diff --git a/src/content/docs/docs/features/http-websocket-apis/admin-api-methods.mdx b/src/content/docs/docs/features/http-websocket-apis/admin-api-methods.mdx new file mode 100644 index 0000000..c51e498 --- /dev/null +++ b/src/content/docs/docs/features/http-websocket-apis/admin-api-methods.mdx @@ -0,0 +1,67 @@ +--- +title: Admin API Methods +--- +These methods are intended exclusively for trusted personnel responsible for maintaining xahaud server operations. + +### Key Generation Methods + + + +| Method | Description | +| ------------------ | --------------------------------------------------------------------------------------------------------------- | +| validation_create | Generate a formatted key pair for xhaud nodes. (Validators should use tokens instead of keys from this method.) | +| wallet_propose | Generate keys for a new account. | + +### Logging and Data Management Methods + + + +| Method | Description | +| --------------- | --------------------------------------------------------------- | +| can_delete | Enable online deletion of ledgers up to a specified ledger. | +| download_shard | Download a specific shard of ledger history. | +| ledger_cleaner | Set up the ledger cleaner to detect and resolve corrupted data. | +| ledger_request | Query a peer server for a specific ledger version. | +| log_level | View or change log verbosity levels. | +| logrotate | Reopen the log file. | +| node_to_shard | Transfer data from the ledger store to the shard store. | + +### Server Control Methods + +| Method | Description | +| -------------- | ------------------------------------------------- | +| ledger_accept | Close and advance the ledger in stand-alone mode. | +| stop | Shut down the xahaud server. | + +### Signing Methods + +| Method | Description | +| --------- | ------------------------------------- | +| sign | Cryptographically sign a transaction. | +| sign_for | Contribute to a multi-signature. | + +### Peer Management Methods + +| Method | Description | +| ------------------------ | -------------------------------------------------- | +| connect | Force the server to connect to a specific peer. | +| peer_reservations_add | Add or update a reserved slot for a specific peer. | +| peer_reservations_del | Remove a reserved slot for a specific peer. | +| peer_reservations_list | View all reserved peer slots. | +| peers | Retrieve information about connected peers | + +### Status/Debugging Methods + + + +| Method | Description | +| ---------------------- | ----------------------------------------------------------- | +| consensus_info | View the current state of the consensus process. | +| feature | Retrieve information about protocol amendments. | +| fetch_info | Check the server’s synchronization status with the network. | +| get_counts | View statistics about server internals and memory usage. | +| manifest | Retrieve public key details for a known validator. | +| print | Access information about internal subsystems. | +| validator_info | Get the server's validator configuration details. | +| validator_list_sites | View sites that publish validator lists. | +| validators | Retrieve information about the current validators. | diff --git a/src/content/docs/docs/features/http-websocket-apis/considerations.mdx b/src/content/docs/docs/features/http-websocket-apis/considerations.mdx new file mode 100644 index 0000000..d72a6c5 --- /dev/null +++ b/src/content/docs/docs/features/http-websocket-apis/considerations.mdx @@ -0,0 +1,16 @@ +--- +title: Considerations +--- +## Markers + +Some methods return more data than can fit efficiently into a single response. When the results exceed the response limit, a `marker` field is included in the response. This field allows you to retrieve additional pages of data through subsequent requests. To continue fetching data, include the `marker` value from the previous response in your next request. If a response does not include a `marker`, it means you have reached the end of the data set. + +The format of the `marker` field is intentionally unspecified. Each server can define the `marker` as needed, meaning it could be a string, a nested object, or another type. The `marker` format may vary between servers and even between methods on the same server. Each `marker` is temporary and may become invalid after approximately 10 minutes. + +## Rate Limit + +The `xahaud` server enforces rate limits on API clients using public APIs to prevent excessive requests. Rate limiting is applied based on the client’s IP address, meaning multiple clients sharing a [network address translation (NAT)](https://en.wikipedia.org/wiki/Network_address_translation) will share the same rate limit associated with their public IP. + +When a client is nearing the rate limit, the server includes a `"warning": "load"` field at the top level of an API response. This warning does not appear on every response but may be sent several times before the server disconnects the client. Clients connected as an admin are exempt from rate limiting. + +If a client exceeds the rate limit, the server disconnects the client and temporarily blocks further requests from that IP address. The WebSocket and JSON-RPC APIs handle disconnects differently, as described below. diff --git a/src/content/docs/docs/features/http-websocket-apis/public-api-methods.mdx b/src/content/docs/docs/features/http-websocket-apis/public-api-methods.mdx new file mode 100644 index 0000000..8c2e416 --- /dev/null +++ b/src/content/docs/docs/features/http-websocket-apis/public-api-methods.mdx @@ -0,0 +1,89 @@ +--- +title: Public API Methods +--- +Interact directly with an xahaud server using public API methods. These methods are not necessarily intended for general public use but are accessible to any client connected to the server. + +### Account Methods + + + +| Method | Description | +| ------------------- | ---------------------------------------------------------------------- | +| account_channels | List payment channels where the account is the channel source. | +| account_currencies | List currencies the account can send or receive. | +| account_info | Retrieve basic information about an account. | +| account_lines | Access trust line information for an account. | +| account_objects | Retrieve all ledger objects owned by an account. | +| account_offers | View an account’s currency exchange offers. | +| account_tx | Retrieve transaction history for an account. | +| gateway_balances | Calculate total issued amounts for an account. | +| noripple_check | Suggest changes to an account's Default Ripple and No Ripple settings. | + +### Ledger Methods + + + +| Method | Description | +| --------------- | -------------------------------------------------- | +| ledger | Get information about a specific ledger version. | +| ledger_closed | Retrieve the most recently closed ledger version. | +| ledger_current | Retrieve the current working ledger version. | +| ledger_data | Access raw ledger content. | +| ledger_entry | Retrieve a specific element from a ledger version. | + +### Transaction Methods + + + +| Method | Description | +| ------------------- | ---------------------------------------------------------- | +| submit | Submit a transaction to the network. | +| submit_multisigned | Submit a multi-signed transaction. | +| transaction_entry | Retrieve details about a transaction in a specific ledger. | +| tx | Retrieve transaction information across all ledgers. | +| sign | (Admin) Cryptographically sign a transaction. | +| sign_for | (Admin) Contribute to a multi-signature. | + +### Order Book Methods + +| Method | Description | +| ------------------- | ----------------------------------------------------------- | +| book_offers | View offers for exchanging two currencies. | +| deposit_authorized | Check if one account can send payments directly to another. | + +### Payment Channel Methods + + + +| Method | Description | +| ------------------ | ----------------------------------------- | +| channel_authorize | Sign a claim for a payment channel | +| channel_verify | Verify a payment channel claim signature. | + +### Subscription Methods + + + +| Method | Description | +| ----------- | ------------------------------- | +| subscribe | Listen for updates on a subject | +| unsubscribe | Stop receiving updates | + +### Server Info Methods + +| Method | Description | +| ------------- | --------------------------------------------- | +| fee | Retrieve information about transaction costs. | +| server_info | Get server status in human-readable format. | +| server_state | Get server status in machine-readable format. | +| manifest | Retrieve public key details for a validator. | + +### Utility Methods + + + +| Method | Description | +| ------ | ---------------------------------------------------------------------- | +| json | Proxy for running commands with JSON parameters. _(Commandline only.)_ | +| ping | Verify server connectivity. | +| random | Generate random numbers. | diff --git a/src/content/docs/docs/features/http-websocket-apis/request-formatting-guide.mdx b/src/content/docs/docs/features/http-websocket-apis/request-formatting-guide.mdx new file mode 100644 index 0000000..5033b3a --- /dev/null +++ b/src/content/docs/docs/features/http-websocket-apis/request-formatting-guide.mdx @@ -0,0 +1,63 @@ +--- +title: Request Formatting Guide +--- +### Public Servers + +* wss://xahau.network or https://xahau.network (Mainnet) +* wss://xahau-test.net or https://xahau-test.net (Testnet) + +### Sample Requests + +To send a sample request to the API, use the following commands. + +### Websocket + +``` +{ + "id": 3, + "command": "account_info", + "account": "rhBDFMmr3jSjgsWMqBAYaATLy3PuXy395y", + "strict": true, + "ledger_index": "validated", + "api_version": 1 +} +``` + +### WebSocket Request Structure + +Once you establish a WebSocket connection to the `xahaud` server, you can send commands as JSON objects with these fields: + +
FieldTypeDescription
commandStringThe name of the API method
id(Multiple)(Optional) Unique identifier for the request.
api_versionNumber(Optional) Specifies the API version.
+ +### JSON-RPC + +``` +POST https://xahau.network/ +Content-Type: application/json + +{ + "method": "account_info", + "params": [ + { + "account": "rhBDFMmr3jSjgsWMqBAYaATLy3PuXy395y", + "strict": true, + "ledger_index": "validated", + "api_version": 1 + } + ] +} +``` + +### JSON-RPC Request Structure + +
FieldTypeDescription
methodStringThe name of the API method
paramsArray(Optional) A one-item array containing a JSON object with the parameters of the method.
+ +### Comandline + +``` +xahaud account_info rhBDFMmr3jSjgsWMqBAYaATLy3PuXy395y validated strict +``` + +### Commandline Request Structure + +
FieldDescription
xahaudStart calling the service xahaud
methodThe name of the API method
params(Optional)
diff --git a/src/content/docs/docs/features/http-websocket-apis/response-formatting-guide.mdx b/src/content/docs/docs/features/http-websocket-apis/response-formatting-guide.mdx new file mode 100644 index 0000000..14b3475 --- /dev/null +++ b/src/content/docs/docs/features/http-websocket-apis/response-formatting-guide.mdx @@ -0,0 +1,29 @@ +--- +title: Response Formatting Guide +--- +Responses are structured differently based on whether the request is made through the WebSocket, JSON-RPC, or Commandline interfaces. The JSON-RPC and Commandline interfaces share the same format, as the Commandline interface internally uses JSON-RPC. + +### Fields + +| Field | Type | Description | +| ------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id | (Varies) | (For WebSocket) The ID from the original request. | +| status | String | (For WebSocket) Indicates `success` when the request was received and processed correctly. | +| result.status | String | (For JSON-RPC and Commandline) Indicates `success` when the request was successfully processed. | +| type | String | (For WebSocket) The value `response` is used for direct replies to API requests. Asynchronous notifications use other values, such as `ledgerClosed` or `transaction`. | +| result | Object | Contains the query result, with content that varies by command. | +| warning | String | _(Optional)_ If present, the value is `load`, indicating the client is nearing the rate limit threshold where the server may disconnect. | +| warnings | Array | _(Optional)_ A list of **Warning Objects** with important server warnings. For more details, see API Warnings. | +| forwarded | Boolean | _(Optional)_ `true` indicates the request was forwarded from a Reporting Mode server to a P2P server to fulfill the request. Default is `false`. | + +API Warnings + +When a response contains a `warnings` array, each entry represents a specific warning from the server. Each **Warning Object** includes the following fields: + + + +| Field | Type | Description | +| ------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id | Number | A unique numeric code identifying this warning message. | +| message | String | A human-readable explanation of the warning. Avoid writing code that relies on the content of this field; use the `id` (and `details`, if available) to interpret the warning instead. | +| details | Object | _(Optional)_ Additional context about the warning. The content varies by warning type. | diff --git a/src/content/docs/docs/features/network-features/account-managment.mdx b/src/content/docs/docs/features/network-features/account-managment.mdx new file mode 100644 index 0000000..7f7b473 --- /dev/null +++ b/src/content/docs/docs/features/network-features/account-managment.mdx @@ -0,0 +1,44 @@ +--- +title: Account Managment +--- +import { Aside } from '@astrojs/starlight/components'; + +The Account Management features in the Xahau network are a crucial component for users to manage their accounts effectively. + +This includes several transaction types that enable users to perform various operations on their accounts. + +### Transaction Types + +#### AccountSet + +The `AccountSet` transaction type allows users to modify the properties of their accounts. This includes settings such as transfer rate, account flags, and more. + +[accountset.md](/docs/protocol-reference/transactions/transaction-types/accountset.md) + +#### AccountDelete + +The `AccountDelete` transaction type enables users to delete their accounts from the Xahau network. This operation is irreversible and should be used with caution. + +[accountdelete.md](/docs/protocol-reference/transactions/transaction-types/accountdelete.md) + +#### SetRegularKey + +The `SetRegularKey` transaction type allows users to set a regular key pair for their account. This key pair can be used as an alternative to the master key pair for signing transactions. + +[setregularkey.md](/docs/protocol-reference/transactions/transaction-types/setregularkey.md) + +#### SignersListSet + +The `SignersListSet` transaction type enables users to set a list of signers for their account. This is particularly useful for multi-signature accounts where multiple parties are required to sign off on transactions. + +[signerlistset.md](/docs/protocol-reference/transactions/transaction-types/signerlistset.md) + +#### Import + +The `Import` transaction type is used to import transactions from other networks. This feature is especially useful for issuers who need to import transactions for their asset holders. It's recommended to key your accounts first before attempting to import transactions. + +Please note that the process of importing for the issuer involves specific transaction types and requires careful configuration. Always ensure that the hooks are correctly set up and that the transactions are valid for the intended operations. + +[import.md](/docs/protocol-reference/transactions/transaction-types/import.md) + +These transaction types provide users with a comprehensive set of tools for managing their accounts on the Xahau network. As with all operations, users should ensure they understand the implications of each transaction type before use. diff --git a/src/content/docs/docs/features/network-features/balance-rewards.mdx b/src/content/docs/docs/features/network-features/balance-rewards.mdx new file mode 100644 index 0000000..db51803 --- /dev/null +++ b/src/content/docs/docs/features/network-features/balance-rewards.mdx @@ -0,0 +1,20 @@ +--- +title: Balance Rewards +--- +import { LinkCard } from '@astrojs/starlight/components'; + +The Balance Rewards feature is a unique aspect of the Xahau network that allows users to accumulate and claim rewards based on their account balance. This feature is implemented through a combination of native code (BalanceRewards Amendment) and hook code (Genesis Account's Reward Hook). + +### Transaction Types + +#### ClaimReward + +A `ClaimReward` transaction allows an account to claim the rewards it has accumulated. The rewards can be claimed by the account owner or by a specified issuer. The account can also opt-out of rewards by setting the Flags field to 1. + + + +#### GenesisMint + +The `GenesisMint` transaction type is also associated with the Balance Rewards feature. This is an Emitted transaction that is executed through the Reward Hook every time a user claims balance rewards. + + diff --git a/src/content/docs/docs/features/network-features/check.mdx b/src/content/docs/docs/features/network-features/check.mdx new file mode 100644 index 0000000..3357a9a --- /dev/null +++ b/src/content/docs/docs/features/network-features/check.mdx @@ -0,0 +1,26 @@ +--- +title: Check +--- +import { LinkCard } from '@astrojs/starlight/components'; + +The Check feature in the Xahau network is a deferred payment system that allows for the creation, cancellation, and cashing of checks within the ledger. This feature is designed to facilitate secure and efficient transactions between parties. + +### Transaction Types + +#### CheckCreate + +The `CheckCreate` transaction is used to create a Check object in the ledger. This represents a deferred payment that can be cashed by its intended destination. + + + +#### CheckCancel + +The `CheckCancel` transaction is used to cancel a Check that has been created but not yet cashed. This allows the sender to stop the payment from being processed if necessary. + + + +#### CheckCash + +The `CheckCash` transaction is used to cash a Check that has been created. This allows the recipient to receive the funds that have been deferred. + + diff --git a/src/content/docs/docs/features/network-features/escrow.mdx b/src/content/docs/docs/features/network-features/escrow.mdx new file mode 100644 index 0000000..e091d33 --- /dev/null +++ b/src/content/docs/docs/features/network-features/escrow.mdx @@ -0,0 +1,28 @@ +--- +title: Escrow +--- +import { LinkCard } from '@astrojs/starlight/components'; + +The Escrow feature is a crucial part of the Xahau network. It provides a secure and trustless method for transactions between parties. The Escrow feature ensures that the assets involved in a transaction are held securely until all the conditions of the transaction are met. + +### Transaction Types + +The Escrow feature includes three types of transactions: + +#### EscrowCreate + +The `EscrowCreate` transaction is used to create a new escrow agreement. This transaction specifies the terms of the escrow, including the parties involved, the assets to be held in escrow, and the conditions under which the assets will be released. + + + +#### EscrowFinish + +The `EscrowFinish` transaction is used to complete an escrow agreement. This transaction is executed when all the conditions of the escrow are met. Upon execution, the assets held in escrow are released to the appropriate party. + + + +#### EscrowCancel + +The `EscrowCancel` transaction is used to cancel an escrow agreement. This transaction can be executed if the conditions of the escrow are not met within a specified time frame. Upon cancellation, the assets held in escrow are returned to the party that initiated the escrow. + + diff --git a/src/content/docs/docs/features/network-features/hooks.mdx b/src/content/docs/docs/features/network-features/hooks.mdx new file mode 100644 index 0000000..ab2a1b1 --- /dev/null +++ b/src/content/docs/docs/features/network-features/hooks.mdx @@ -0,0 +1,22 @@ +--- +title: Hooks +--- +import { LinkCard } from '@astrojs/starlight/components'; + +Hooks are a powerful feature of the XRPL network, providing robust smart contract functionality. They are small, efficient WebAssembly modules designed specifically for the XRPL, and can be referred to as Smart Contracts for the XRP Ledger Protocol. Hooks can be written in any language that is compilable with WebAssembly, allowing for a wide range of business logic and smart contract concepts to be implemented. + +### Transaction Types + +The Hooks feature includes two types of transactions: + +**SetHook** + +This transaction type is used to set up a hook on an account. + + + +**Invoke** + +This transaction type is used to call or invoke the functionality of a hook. + + diff --git a/src/content/docs/docs/features/network-features/offer.mdx b/src/content/docs/docs/features/network-features/offer.mdx new file mode 100644 index 0000000..c218594 --- /dev/null +++ b/src/content/docs/docs/features/network-features/offer.mdx @@ -0,0 +1,20 @@ +--- +title: Offer +--- +import { LinkCard } from '@astrojs/starlight/components'; + +The Offer feature in the Xahau network is a crucial component of the decentralized exchange system. It allows users to create and cancel offers, facilitating a dynamic and responsive trading environment. + +### Transaction Types + +#### OfferCreate + +The `OfferCreate` transaction is used to place an offer in the decentralized exchange. + + + +#### OfferCancel + +The `OfferCancel` transaction is used to cancel an existing offer. The documentation for this transaction type is referenced in the Xahau Documentation but not provided in the given context. + + diff --git a/src/content/docs/docs/features/network-features/payments.mdx b/src/content/docs/docs/features/network-features/payments.mdx new file mode 100644 index 0000000..4fc70f7 --- /dev/null +++ b/src/content/docs/docs/features/network-features/payments.mdx @@ -0,0 +1,46 @@ +--- +title: Payments +--- +import { LinkCard } from '@astrojs/starlight/components'; + +The Payments feature in the Xahau network is a crucial component that enables the transfer of assets and funds within the network. This feature is designed to facilitate seamless transactions, ensuring a smooth and efficient operation of the network. + +### Transaction Types + +The Payments feature comprises several transaction types, each serving a unique purpose in the network. Here's a brief overview of each transaction type: + +**DepositPreauth** + +This transaction type allows an account to preauthorize incoming transactions from a specified source. It's a way to whitelist accounts, ensuring that only authorized transactions are processed. + + + +**TrustSet** + +This transaction type allows users to create a trust line with another account. It's a way to establish trust between two accounts, enabling them to transact with each other. + + + +**Payment** + +This is the basic transaction type that allows the transfer of assets between accounts. It's the fundamental transaction type for any payment operation in the network. + + + +**PaymentChannelCreate** + +This transaction type allows the creation of a payment channel between two accounts. Payment channels are off-ledger scalability solutions that enable high-frequency, low-cost transactions between two parties. + + + +**PaymentChannelFund** + +This transaction type allows an account to fund an existing payment channel. It's a way to add more assets to a payment channel, enabling more transactions to take place. + + + +**PaymentChannelClaim** + +This transaction type allows an account to claim the funds from a payment channel. It's a way to close a payment channel and retrieve the remaining assets. + + diff --git a/src/content/docs/docs/features/network-features/uritoken.mdx b/src/content/docs/docs/features/network-features/uritoken.mdx new file mode 100644 index 0000000..070d511 --- /dev/null +++ b/src/content/docs/docs/features/network-features/uritoken.mdx @@ -0,0 +1,32 @@ +--- +title: URIToken +--- +import { LinkCard } from '@astrojs/starlight/components'; + +URITokens are the Non-Fungible Token (NFT) implementation native to the Xahau network. They exist as first-class on-ledger objects, uniquely identified by the hash of their issuer and Uniform Resource Identifier (URI). URITokens can point to any digital content, with only one object per URI per account existing on the ledger. + +The issuer has the ability to set a flag to enable the burning of the object in the future. Each owner's reserve is locked up as well upon ownership of the URIToken. + +### Transaction Types + +#### URITokenMint + +The URITokenMint transaction mints a new URIToken and assigns ownership to the specified account. The minted URIToken represents a unique digital asset that can be used in various applications. The issuer can choose to allow the minted URIToken to be destroyed in the future. + + + +#### URITokenBurn + +The URITokenBurn transaction is used to burn a URIToken in Xahau. Burning a URIToken permanently removes it from circulation. The transaction does not have any special transaction cost requirements. The account that owns the URIToken to be burned is required for this transaction. + + + +#### URITokenBuy + +The URITokenBuy transaction allows a user to buy a URIToken from the issuer. This transaction is used to transfer ownership of a URIToken from the issuer to the buyer. The buyer's account, the unique identifier of the URIToken to be bought, and the amount of currency to pay for the URIToken are required for this transaction. + + + + + + diff --git a/src/content/docs/docs/features/public-nodes-rpc.mdx b/src/content/docs/docs/features/public-nodes-rpc.mdx new file mode 100644 index 0000000..798b885 --- /dev/null +++ b/src/content/docs/docs/features/public-nodes-rpc.mdx @@ -0,0 +1,34 @@ +--- +title: Public Nodes (RPC) +description: >- + Running your own node: amazing. Hit the ground running? Use the public Xahau + RPC nodes. +--- +## Mainnet (network 21337) + +* Websocket + * `wss://xahau.network` + * `wss://xahau.org` (alias, some ad-blockers block .network) +* HTTP POST RPC + * `https://xahau.network` + * `https://xahau.org` (alias, some ad-blockers block .network) +* Network Definitions (Binary Codec, ...) + * [`https://xahau.network/server_definitions.json`](https://xahau.network/server_definitions.json) + +## Testnet (network 21338) + +* Websocket + * `wss://xahau-test.net` +* HTTP POST RPC + * `https://xahau-test.net` +* Network Definitions (Binary Codec, ...) + * [`https://xahau-test.net/server_definitions.json`](https://xahau-test.net/server_definitions.json) + +## JSHooks-Testnet (network 31338) + +* Websocket + * `wss://jshooks.xahau-test.net` +* HTTP POST RPC + * `https://jshooks.xahau-test.net` +* Network Definitions (Binary Codec, ...) + * [`https://jshooks.xahau-test.net/server_definitions.json`](https://jshooks.xahau-test.net/server_definitions.json) diff --git a/src/content/docs/docs/features/transaction-signing/index.mdx b/src/content/docs/docs/features/transaction-signing/index.mdx new file mode 100644 index 0000000..9ba33e5 --- /dev/null +++ b/src/content/docs/docs/features/transaction-signing/index.mdx @@ -0,0 +1,64 @@ +--- +title: Transaction Signing +description: >- + As Hooks-enabled networks require specific transaction fields & offer more + transaction types, not all clients will work out of the box. `xrpl-accountlib` +--- +## Main differences + +1. Hooks-enabled networks allow getting network definitions dynamically. Allowing clients to adapt available transaction types, ledger objects, properties, and value types. When implemented correctly, signing and encoding libraries don't have to be updated when the network adds transaction/object types/properties. **The libraries below implement this and will handle this for you.** +2. Hooks-enabled networks require a **NetworkID** with every transaction to prevent transaction replay on another chain. The **NetworkID** will also be returned by a `server_info` RPC command in the `network_id` field (e.g. **`21338`** for Hooks V3 testnet) +3. Transactions on a Hooks-enabled network may need higher fees to deliver a transaction to another account, based on the Hooks that will be executed sending out of the sending account and receiving on the destination account. A reasonable fee to satisfy the Hooks execution can be dynamically fetched from a node by issuing the `fee` command while providing a transaction as `tx_blob`. **The libraries below implement this and will handle this for you.** + +## JavaScript/Typescript + +The [**npm package `xrpl-accountlib`**](https://www.npmjs.com/package/xrpl-accountlib) can sign transactions for Hooks-enabled networks, as it offers full dynamic network feature support fetching network definitions at runtime. + +The [**npm package `xrpl-client`**](https://www.npmjs.com/package/xrpl-client) integrates nicely with `xrpl-accountlib` (and comes as a dependency) to dynamically fetch the aforementioned network definitions and account values, helping submit the transaction. + +### Code Sample + +```javascript +import { + derive, + utils, + signAndSubmit, +} from "xrpl-accountlib" + +const wss = 'wss://xahau-test.net' +const account = derive.familySeed("s...") + +const networkInfo = await utils.txNetworkAndAccountValues(wss, account) + +const tx = { + TransactionType: "SetHook", + Hooks: [ { Hook: { + CreateCode: "0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22", + Flags: 1, + HookApiVersion: 0, + HookNamespace: "F".repeat(64), + HookOn: "F".repeat(58) + "BFFFFE", + } + }], + ...networkInfo.txValues, + // ^^ This adds autmatically fetched values for you: + // Sequence, Account, LastLedgerSequence, + // Fee (Hooks enabled: autodetect (from ledger)) +} + +/** + * Note: the code above and `signAndSubmit` results in automatically + * fetching and setting a fee for you. If you want to check the fee + * for min/max/..., get your own fee (string in drops) using: + * utils.networkTxFee(wss, tx) + * + * e.g. + * const Fee = await utils.networkTxFee(wss, tx) + * assert(Number(Fee) < 50_000, "Auto fee above 50k drops, abort") + * Object.assign(tx, { Fee, }) + */ + +const submitted = await signAndSubmit(tx, wss, account) + +console.log(submitted) +``` diff --git a/src/content/docs/docs/features/transaction-signing/transaction-fees.mdx b/src/content/docs/docs/features/transaction-signing/transaction-fees.mdx new file mode 100644 index 0000000..a3c4bbc --- /dev/null +++ b/src/content/docs/docs/features/transaction-signing/transaction-fees.mdx @@ -0,0 +1,56 @@ +--- +title: Transaction Fees +description: >- + Xahau smart contracts (Hooks) need transaction & destination specific fees. + You can easily get the required fee from the `fee` RPC command. +--- +import { Aside } from '@astrojs/starlight/components'; + +While libraries may deal with fee determination for you (see [.](./ "mention")), when building your own integrations with the Xahauy ledger, you may have to implement dynamic fee determination based on the transaction, source & destination account. + +As the sender of a transaction will have to pay for the fees required for the invoked Hooks for the specific transaction type, where Hooks can live both on the source & destination account, you can send a TX Blob (signed with a dummy account) to the `fee` command, after which Xahau will return the specific fees required for the specific transaction. + +### Fee RPC Helper + +Transaction fees on a ledger with the Hooks Amendment enabled become non-trivial to compute for end-users and/or wallet applications. This is because strong hooks must be paid for by the originator of a transaction, and there may be as many as 4 strong hooks on the sending account and 4 on the receiving account, as well as any other strong transactional stakeholders involved (as can be the case with some exotic transaction types). Further, if the transaction is a SetHook then the size of the parameters, the size of the code and whether it is a _create_ operation or an _install_ operation all determine the size of the fee. + +Therefore it is highly recommended that **all** transactions be run through the updated fee RPC call before they are submitted to the ledger. + +#### To invoke the RPC call: + +1. Open a websocket connection to the Hooks node you will be working with. +2. Compose the serialized transaction you wish to know the fee for with the following: + +* `Fee: 0` +* `SigningPubKey: ""` (That is: 0 byte VL of type 0x73. In hex:`0x7300`.) +* Do **not** sign the transaction. + +3. Submit it as a hex blob to the RPC as follows: + +```json +{"command":"fee", "tx_blob":""} +``` + +For HTTP POST RPC submit it as follows: + +```json +{"method":"fee", "params": [{"tx_blob":""}] } +``` + +The response should look something like + +```json +{ + result: { + drops: { + base_fee: '130520', + }, + //... + }, + type: 'response' +} +``` + +Take the base fee and set it as the `Fee` field in the transaction. Now sign and submit it as per the normal transaction submission process. + +If there is an invalid value for `tx_blob` or `tx_blob` is missing, a regular JSON result will be returned with a `base_fee` of 10. diff --git a/src/content/docs/docs/features/versioning-process.mdx b/src/content/docs/docs/features/versioning-process.mdx new file mode 100644 index 0000000..388eb5d --- /dev/null +++ b/src/content/docs/docs/features/versioning-process.mdx @@ -0,0 +1,64 @@ +--- +title: Versioning Process +description: >- + This document outlines our versioning workflow on GitHub, to streamline the + development, testing, and deployment of new features and fixes. +--- +import { Aside } from '@astrojs/starlight/components'; + +This document outlines the versioning process we use in our GitHub repository. We use a three-branch workflow: `dev`, `candidate`, and `release`. This process ensures that all new features and fixes are thoroughly tested before release. + +### Dev Branch + +The dev branch is the main branch for ongoing development. All new features, bug fixes, and improvements are merged into this branch. This is the most active branch, and it's where developers should base their work. + +To contribute to the dev branch, follow these steps: + +1. Fork the repository to your own GitHub account. +2. Clone the forked repository to your local machine. +3. Create a new branch for your feature or bug fix. +4. Make your changes and commit them to your branch. +5. Push your branch to your forked repository on GitHub. +6. Create a pull request from your branch to the dev branch in the main repository. + + + +Code maintainers will review your pull request and provide feedback. Once the code is approved, it will be merged into the dev branch. + +### Candidate Branches + +Once the features in the `dev` branch are ready for testing, they are merged into a `candidate` branch. This branch serves as a staging area for code that is almost ready for release. + +The code in the `candidate` branch is thoroughly tested. Any bugs or issues found are fixed in the `dev` branch and then merged back into the `candidate` branch. + +The `candidate` branch is typically in this testing phase for about 2 weeks. However, this period can be longer or shorter, depending on the urgency of the fixes or the size of the new features. + +1. Create a new branch `candidate` from `dev`. +2. Create a PR from the `candidate` branch to the `release` branch with a name like "Proposed." +3. Update the "High Level Overview of Change" to include the Pull Requests from `candidate`. Update the "Context of Change" to include any additional notes about the PR's + +### Release Branch + +After the code in the `candidate` branch has been thoroughly tested and all issues have been addressed, it is merged into the `release` branch. This is the final step before the code is released. + +The `release` branch contains the code that is currently in production or is about to be released. Only fully tested and stable code should be in this branch. + +Once the code is in the `release` branch, it is tagged with a version number. This version number is used to track the release and is also used when creating release notes. + +In the `release` branch, a binary is built and published at https://build.xahau.tech/. This binary is the final product that is delivered to the end users. + +To release the code, follow these steps: + +1. Merge the `candidate` pull request into the release branch. +2. Delete the `candidate` branch. + + + +### Summary + +This three-branch workflow ensures that all code is thoroughly tested before release. It allows us to catch and fix issues before they reach production, and it provides a clear path for moving code from development to release. The use of a custom LAN for testing and profiling metrics ensures that our code is not only functional but also efficient and performant. + diff --git a/src/content/docs/docs/hooks/concepts/chaining.mdx b/src/content/docs/docs/hooks/concepts/chaining.mdx new file mode 100644 index 0000000..b85660a --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/chaining.mdx @@ -0,0 +1,47 @@ +--- +title: Chaining +description: Chain multiple hooks together to do more useful tasks +--- +import { Aside } from '@astrojs/starlight/components'; + + + +### History + +In the early days of Hooks it was only possible to install one Hook per account. This meant users were forced to produce omnibus Hooks if they wanted to do more than one thing: for example offset carbon and firewall at the same time. + +This was counter to the Hook Design Philosophy, so Hook Chaining was introduced. + +### Chaining + +A Hook Chain is a sequence of up to **10** Hooks installed on an Xahau account. + +* A Hook Chain executes successfully when every Hook in the chain has been individually executed and subsequently calls [accept](../technical/hooks-functions/control/accept.md). +* Each chain's execution starts at chain position 0 and ends at chain position 9. If a position is blank (because it was never filled or because the hook that was installed there has been removed) then that position is skipped and treated as successful. +* In order for a transaction to succeed, both ends of the transaction (sending side and receiving side) must have executed successfully. This means if there is a Hook Chain installed on both sides, then both Hook Chains must execute successfully for the transaction to succeed. + +Hooks are installed into the chain using the [SetHook Transaction](sethook-transaction.md). When they are installed, the installer may specify install-time [Parameters](parameters.md) which may change the behaviour of the installed Hook. + +
+![Example: Execution flow for a transaction passing through two Hook Chains](../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_0OucxySTRinbe13SITJT_5561b32-sethook-Page-3.png) +
*Example: Execution flow for a transaction passing through two Hook Chains*
+
+ +### Chain Manipulation + +In addition to the _install-time_ operations specified in the [SetHook Transaction](sethook-transaction.md), Hooks have some runtime control over chain execution: + +* A Hook may determine its own `HookHash` by calling [hook_hash](../technical/hooks-functions/hook-context/hook_hash.md). +* A Hook may determine its location in the Hook Chain using [hook_pos](../technical/hooks-functions/hook-context/hook_pos.md). +* A Hook may skip (or re-enable) another Hook further down the chain using [hook_skip](../technical/hooks-functions/hook-context/hook_skip.md). +* A Hook may modify the [Parameters](parameters.md) of a Hook further down the chain using [hook_param_set](../technical/hooks-functions/hook-context/hook_param_set.md). + +### Weak Executions + +Hook Chains are [Strongly Executed](weak-and-strong.md). However any Hook in any chain may flag that it requires a second, Weak Execution by calling [hook_again](../technical/hooks-functions/hook-context/hook_again.md). If all Hook Chains execute successfully then the originating transaction is applied. Once the originating transaction has been applied any Weak Executions may happen, in the following order: + +1. `cbak` execution if this was an Emitted Transaction. +2. Weak Transactional Stake Holders who have opted in to allow a [Collect Call](collect-call.md). Execution order is first-come first-serve according to the event that caused the TSH to be flagged (such as pathing). +3. Any _Again as Weak_ (AAW) Hooks. Execution order for AAW is first numerically according to Account ID then numerically according to Hook position. diff --git a/src/content/docs/docs/hooks/concepts/collect-call.mdx b/src/content/docs/docs/hooks/concepts/collect-call.mdx new file mode 100644 index 0000000..8eb02d4 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/collect-call.mdx @@ -0,0 +1,27 @@ +--- +title: Collect Call +--- +import { Card, Aside } from '@astrojs/starlight/components'; + + +_Every party affected by a transaction should have the opportunity to have their hooks executed._ + + +When hooks are not Strongly Executed it is unfair to bill the originating transaction for their execution. For example an _OfferCreate_ which crosses 20 offers on the DEX should not be forced to pay for the execution of each of those account's Hooks. + +Therefore during typical Weak execution the fee for the execution is collected from the owner of the Hook. To enable this: + +* The Hook owner must have set `asfTshCollect` on their Xahau account using the AccountSet transaction. +* The Hook owner must have set `hsfCollect` on the specific Hook they wish to be called as a Weak TSH. + +### Fee Responsibility Table + +| Type of Weak Execution | Fee | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +|

Again As Weak
- Happens when a Strongly Executed Hook calls hook_again

| Free (already paid by the Strong Execution). | +|

Callback
- Happens when an emitted transaction either makes it into a ledger or is flagged as being impossible to ever make it into a ledger.

| Free (already paid during Emission). | +|

Weak Transactional Stakeholder
- Happens if a transaction in some way mildly affects your account.

| Paid for by your account (not by the originating transaction) if and only if both your account is marked with `asfTshCollect` flag and your Hook is marked with the `hsfCollect` flag. | + + diff --git a/src/content/docs/docs/hooks/concepts/compiling-hooks.mdx b/src/content/docs/docs/hooks/concepts/compiling-hooks.mdx new file mode 100644 index 0000000..1e3507c --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/compiling-hooks.mdx @@ -0,0 +1,228 @@ +--- +title: Compiling Hooks +--- +import { Aside } from '@astrojs/starlight/components'; + +### Constraints + +All Hooks are compiled to a single [webassembly module](https://webassembly.github.io/spec/core/syntax/modules.html) before they can be set onto an [Xahau account](https://xrpl.org/accounts.html). + +A Hook always implements and exports exactly one or both of the following functions: + +`int64_t hook(uint32_t ctx) { ... }` _required_ + +* Executed whenever a transaction comes into or leaves from the account the Hook is set on (`ctx = 0`) or +* Executed when executed as a [Weak Transactional Stakeholder](weak-and-strong.md) (`ctx > 0`). + +`int64_t cbak(uint32_t ctx) { ... }` _optional_ + +* Executed when an emitted transaction is successfully accepted into a ledger (`ctx = 0`) or +* Executed when an emitted transaction cannot be accepted into any ledger (`ctx = 1`). + +Hooks are not allowed to specify other functions. Instead they must make clever use of macros to do all their computation within these two functions. This is part of a computational restriction on hooks to keep their runtime predictable. + +Additionally Hooks are afforded no _heap_ memory. All required memory must be reserved and used on the stack. + +### Example + +Here is an example Hook written in C. The Hook prints 0...3 to the trace log before accepting the originating transaction. + +```c +#include +#define GUARD(maxiter) _g(__LINE__, (maxiter)+1) +extern int32_t _g (uint32_t id, uint32_t maxiter); +extern int64_t accept (uint32_t read_ptr, uint32_t read_len, int64_t error_code); +extern int64_t trace_num (uint32_t read_ptr, uint32_t read_len, int64_t number); + +int64_t hook(uint32_t ctx) +{ + for (int i = 0; GUARD(3), i < 3; ++i) + { + trace_num("test", 4, i); + } + accept (0,0,0); + return 0; +} +``` + + + +### Compilation + +A [variety of compilers](https://www.google.com/search?q=webassembly+compiler+C) will generate valid webassembly from a C source file. Once compiled, a Hook exists as a binary `.wasm` file. This contains a webassembly module. Using `wasmcc` to compile and the `wasm2wat` tool to convert to human readable webassembly this binary form can be rendered to the human readable form. Below appears the compilation result of the above example. + +``` +(module + (type (;0;) (func (param i32 i32) (result i32))) + (type (;1;) (func (param i32 i32 i64) (result i64))) + (type (;2;) (func)) + (type (;3;) (func (param i32) (result i64))) + (import "env" "_g" (func $_g (type 0))) + (import "env" "trace_num" (func $trace_num (type 1))) + (import "env" "accept" (func $accept (type 1))) + (func $__wasm_call_ctors (type 2)) + (func $cbak (type 3) (param i32) (result i64) + (local i32 i32 i32 i64) + global.get 0 + local.set 1 + i32.const 16 + local.set 2 + local.get 1 + local.get 2 + i32.sub + local.set 3 + i64.const 0 + local.set 4 + local.get 3 + local.get 0 + i64.store offset=8 + local.get 4 + return) + (func $hook (type 3) (param i32) (result i64) + (local i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i64 i32 i32 i32 i64 i32 i32 i32) + global.get 0 + local.set 1 + i32.const 16 + local.set 2 + local.get 1 + local.get 2 + i32.sub + local.set 3 + local.get 3 + global.set 0 + i32.const 0 + local.set 4 + local.get 3 + local.get 0 + i64.store offset=8 + local.get 3 + local.get 4 + i32.store offset=4 + block ;; label = @1 + loop ;; label = @2 + i32.const 3 + local.set 5 + i32.const 14 + local.set 6 + i32.const 4 + local.set 7 + local.get 6 + local.get 7 + call $_g + drop + local.get 3 + i32.load offset=4 + local.set 8 + local.get 8 + local.set 9 + local.get 5 + local.set 10 + local.get 9 + local.get 10 + i32.lt_s + local.set 11 + i32.const 1 + local.set 12 + local.get 11 + local.get 12 + i32.and + local.set 13 + local.get 13 + i32.eqz + br_if 1 (;@1;) + i32.const 1024 + local.set 14 + i32.const 4 + local.set 15 + local.get 3 + i32.load offset=4 + local.set 16 + local.get 16 + local.set 17 + local.get 17 + i64.extend_i32_s + local.set 18 + local.get 14 + local.get 15 + local.get 18 + call $trace_num + drop + local.get 3 + i32.load offset=4 + local.set 19 + i32.const 1 + local.set 20 + local.get 19 + local.get 20 + i32.add + local.set 21 + local.get 3 + local.get 21 + i32.store offset=4 + br 0 (;@2;) + end + end + i64.const 0 + local.set 22 + i32.const 0 + local.set 23 + local.get 23 + local.get 23 + local.get 22 + call $accept + drop + i32.const 16 + local.set 24 + local.get 3 + local.get 24 + i32.add + local.set 25 + local.get 25 + global.set 0 + local.get 22 + return) + (table (;0;) 1 1 funcref) + (memory (;0;) 2) + (global (;0;) (mut i32) (i32.const 66576)) + (global (;1;) i32 (i32.const 1029)) + (global (;2;) i32 (i32.const 1024)) + (global (;3;) i32 (i32.const 66576)) + (global (;4;) i32 (i32.const 1024)) + (export "memory" (memory 0)) + (export "__wasm_call_ctors" (func $__wasm_call_ctors)) + (export "__data_end" (global 1)) + (export "__global_base" (global 2)) + (export "__heap_base" (global 3)) + (export "__dso_handle" (global 4)) + (export "cbak" (func $cbak)) + (export "hook" (func $hook)) + (data (;0;) (i32.const 1024) "test\00")) +``` + +The average Hook developer will never need to examine webassembly directly. However it is a useful conceptual exercise to review the contents of the sample Hook. + +Above we can see: + +* Three functions are imported from the Hooks API (`_g`, `accept`, `trace_num`) +* Two functions are defined by the hook (`cbak`, `hook`) +* Two functions are exported by the hook (again: `cbak`, `hook`) +* Some static (constant) data is recorded in the hook (see `data` at the bottom). + +It is very important to note that a Hook _must only_ import functions available to it from the Hooks API and _must_ only export the `cbak` and `hook` functions. In additional all hooks must import `_g` from the Hooks API, which is the `guard` function. + + + +### Unwanted Exports + +Most webassembly compilers (including the one above) produce additional exports for their own linking purposes. In many cases the generation of these is difficult or impossible to disable. + +Unwanted exports will lead to an otherwise valid Hook being rejected. Therefore after compilation developers should use the [Hook Cleaner Utility](https://github.com/XRPLF/hook-cleaner-c) to strip out these out. Failure to do so will lead to your Hook being rejected. + + + diff --git a/src/content/docs/docs/hooks/concepts/debugging-hooks.mdx b/src/content/docs/docs/hooks/concepts/debugging-hooks.mdx new file mode 100644 index 0000000..8c5c917 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/debugging-hooks.mdx @@ -0,0 +1,71 @@ +--- +title: Debugging Hooks +description: How to print "hello world" from your Hook! +--- +import { Aside } from '@astrojs/starlight/components'; + +### How can I debug a Hook? + +The Hook API provides a set of functions in the namespace `trace` which write output to the `xrpld` log file when xrpld is configured with the _trace_ log-level. These functions, generally speaking, allow you to see the value of variables, buffers and otherwise trace the execution and state of a Hook at runtime. + + + +### Trace APIs + +The following `trace` functions are available in the Hooks API + +| Hook API | What it does | +| ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | +| [trace](../technical/hooks-functions/trace-debug/trace.md) | Print a utf-8 message, followed by a user-specified buffer (this last optionally as hex.) | +| [trace_num](../technical/hooks-functions/trace-debug/trace_num.md) | Print a utf-8 message, followed by an integer. | +| [trace_float](../technical/hooks-functions/trace-debug/trace_float.md) | Print a utf-8 message, followed by an XFL Floating point number. | +| trace_slot | Print a utf-8 message, followed by the serialized contents of a slot. | + +### Example + +The following code will print a single trace line then accept the Originating Transaction. + +```c +#include "../hookapi.h" +int64_t hook(int64_t reserved) +{ + trace_num(SBUF("A number"), 10); + accept(0,0,0); + return 0; +} +``` + +An example of the log-line produced by `xahaud` when a payment is sent out of or into the Hook Account: + +``` +2021-Apr-13 13:59:11.083700726 UTC View:TRC + HookTrace[rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh-rE3SfnjwfzZFL3JK9cLVfJuy8Ar1XnCqPw]: + A number 10 +``` + +The above appears in the log as all-one-line, but split here for visibility. + + + +### Log format + +A breakdown of the log format appears in the table below + +| Part | Description | # | +| ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | - | +| 2021-Apr-13 13:59:11.083700726 UTC View:TRC | `xahaud`'s prefix to the log line | 1 | +| HookTrace | This is a trace initiated by the Hook itself not some other information about the Hook. Other information is available on tags `HookError`, `HookEmit` and `HookInfo`. | 2 | +| \[rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh | The first account in the square brackets is the Hook Account. | 3 | +| -rE3SfnjwfzZFL3JK9cLVfJuy8Ar1XnCqPw]: | The second account in the square brackets is the Originating Account. | 4 | +| A number | This is the message the Hook was told to deliver before the trace payload | 5 | +| 10 | This is the trace payload | 6 | + + diff --git a/src/content/docs/docs/hooks/concepts/emitted-transactions.mdx b/src/content/docs/docs/hooks/concepts/emitted-transactions.mdx new file mode 100644 index 0000000..2744c17 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/emitted-transactions.mdx @@ -0,0 +1,64 @@ +--- +title: Emitted Transactions +description: Your Hook can do a lot more than just block or allow transactions! +--- +import { Aside } from '@astrojs/starlight/components'; + +### Background + +**All** changes made to Xahau _must_ be the result of applying a valid transaction to the ledger. Thus if some change _X_ is made then some transaction _Y_ is responsible. + +When designing the Hooks API we needed a way for Hooks to make changes to the ledger _beyond_ simply accepting or rejecting a transaction. However attaching these changes to the Originating Transaction was confusing and resulted in a large increase in the general complexity of the system. + +Suppose for example that a Hook needs to send you some funds... the send operation would be effectively enacted onto the ledger by the Originating Transaction which might have been something completely unrelated such as an Account Set transaction. Additionally this send operation would need to be able to potentially trigger another Hook on the receiving end of a payment. + +The solution: **Emitted Transactions**. We allow the Originating Transaction to do exactly what the contents of the Transaction say it will do. If our Hook needs to make an additional change to the ledger such as sending a payment, it creates and then _emits_ a brand new transaction. + +### What are Emitted Transactions? + +Emitted Transactions are _new_ transactions created by the execution of a Hook and entered into consensus for processing in the next ledger. The transaction may be of any Transaction Type but must follow strict emission rules. + +To emit a transaction the Hook first prepares the serialized transaction then calls [emit](../technical/hooks-functions/emitted-transaction/emit-1.md). + +Because emitted transactions can trigger Hooks in the next ledger which in turn may emit more transactions, all emitted transactions carry a `burden` and a `generation` field in their `EmitDetails` block. The `EmitDetails` block replaces the signature field in a traditional transaction. + +The `burden` and `generation` fields collectively prevent [Fork bomb](https://en.wikipedia.org/wiki/Fork_bomb) attacks on the ledger by exponentially increasing the cost of exponentially expanding emtited transactions. + +It is important to note that the Hooks API follows the strict rule of _no rewriting_. You _must_ present an emitted transaction in full, valid and canonically formed to xahaud for emission or it will be rejected. It is not xahaud's job to build your transaction for you. The Hook must do this itself. + +### Callbacks + +As introduced in [Introduction and Terminology](terminology.md) emitted transactions trigger callbacks when they are accepted into a ledger. Due to the decentralised nature of consensus acceptance into a ledger of an emitted transaction is **not a guarantee**, although it is usually all-but guaranteed. + +If an emitted transaction expires before it can be accepted into a ledger (for any number of reasons: the ledgers may be full, the fee may be too high for the emitted transaction or the emitted transaction may be somehow invalid) then a _pseudo transaction_ is created in the ledger to clean up the emitted transaction. This pseudo transaction also calls the callback of your hook, with `parameter = 1` to indicate the emitted transaction indeed failed. + +### Emission Rules + +The [emit](../technical/hooks-functions/emitted-transaction/emit-1.md) Hook API will enforce the following rules on a proposed (to be emitted) transaction. + +| # | Emission Rule | Explanation | +| - | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | `sfSequence` = 0 | Emitted Transactions _do not_ increase the sequence number of the Hook Account. This must always be set to zero. | +| 2 | `sfPubSigningKey` = 0 | Emitted Transactions are not signed but this is a required field for xrpld processing. It must be set to all zeros. | +| 3 | `sfEmitDetails` present and valid | Emitted Transactions require an `sfEmitDetails` block and this must be correctly filled. See EmitDetails section below. | +| 4 | `sfSignature` absent | This field must be absent in the emitted transaction because if it were not then the transaction would be ambiguous. | +| 5 | `LastLedgerSequence` valid and in the future | All emitted transactions must have a last ledger sequence set so that the Hook knows if the emitted transaction failed (since it did not get a callback in time). This is currently set to a maximum of 5 ledgers after the current ledger. | +| 6 | `FirstLedgerSequence` valid and set to the next ledger | All emitted transactions must have a first ledger sequence set to the next ledger (after the current ledger) so that Hooks do not recursively cascade within a single ledger. This is currently enforced to be the next ledger after the current ledger. | +| 7 | Fee appropirately computed and set | The fee is dependent on the size of the emtited transaction and the burden on the network (i.e. whether this emitted transaction was the result of another emitted transaction.) | +| 8 | Generation cap not exceeded | An emitted transaction can produce other emitted transactions, and these can form a chain. The length of the chain is the `sfEmitGeneration`. This is currently capped at 10. | + +### EmitDetails block + +All emitted transactions must contain an `sfEmitDetails` object correctly populated with the fields in the table below. + +| Field | Required Value | Description | +| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| sfEmitGeneration |

If the Originating Transaction was itself an emitted transaction then one more than the sfEmitGeneration of that transaction.

If the Originating Transaction was not an emitted transaction then 1.

This should be populated using etxn_generation.

| This field keeps track of a chain of emitted transactions that in turn cause other transactions to be emitted. | +| sfEmitBurden |

If the Originating Transaction was itself an emitted transaction then the burden of the Originating Transaction multiplied by the maximum number of transactions the Hook has declared it will emit using etxn_reserve.

If the Originating Transaction was not an emitted transaction then 1.

This should be populated using etxn_burden.

| This field is a heuristic for detecting forkbombs. Fees are based on burden and will increase exponentially when a chain reaction is started to prevent the network becoming overun by self-reinforcing emitted transactions. | +| sfEmitParentTxnID | The transaction ID of the Originating Transaction | The Hook Execution that emitted the transaction is connected to the Originating Transaction. Therefore this field is always required for the efficient tracing of behaviour. | +| sfEmitNonce | A special deterministic nonce produced by a call to [nonce](../technical/hooks-functions/emitted-transaction/etxn_nonce.md) | Emitted Transactions would be identical with the same fields and therefore have identical transaction hashes if a nonce were not used. However every node on the network needs to agree on the nonce, so a special Hook API to produce a deterministic nonce is made available. | +| sfEmitCallback | The 20 byte Hook Account ID | This field is used by xahaud when it needs to intitate a callback, such that it knows which Hook and account to initate the callback on. Callbacks happen when an emitted transaction is accepted into a ledger. | + + \ No newline at end of file diff --git a/src/content/docs/docs/hooks/concepts/execution-metadata.mdx b/src/content/docs/docs/hooks/concepts/execution-metadata.mdx new file mode 100644 index 0000000..4bb29e1 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/execution-metadata.mdx @@ -0,0 +1,20 @@ +--- +title: Execution Metadata +description: What to expect when your Hook runs. +--- + +When Hooks execute they leave behind information about the status of that execution. This appears in the Originating Transaction metadata as an `sfHookExecutions` block. This block contains the following fields: + + + +| Field | Description | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| sfHookResult |

Hooks can end in three ways: accept, rollback and error.
This is not the same as sfHookReturnCode!

| +| sfHookHash | The SHA512H of the Hook at the time it was executed. | +| sfHookAccount | The account the Hook ran on. | +| sfHookReturnCode | The integer returned as the third parameter of `accept` or `rollback`. | +| sfHookReturnString | The string returned in the first two parameters of `accept` or `rollback`, if any. | +| sfHookInstructionCount | The total number of webassembly instructions that were executed when the Hook ran. | +| sfHookEmitCount | The total number of [Emitted Transactions](emitted-transactions.md) produced by the Hook. | +| sfHookExecutionIndex | The order in which the Hook was executed (as distinct from other Hook Executions on the same Originating Transaction.) | +| sfHookStateChangeCount | The number of [Hook State](state-management.md) changes the Hook made during execution. | diff --git a/src/content/docs/docs/hooks/concepts/floating-point-numbers-xfl.mdx b/src/content/docs/docs/hooks/concepts/floating-point-numbers-xfl.mdx new file mode 100644 index 0000000..7fa203b --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/floating-point-numbers-xfl.mdx @@ -0,0 +1,97 @@ +--- +title: Floating Point Numbers (XFL) +description: High precision calculations are native to Hooks. +--- +import { Aside } from '@astrojs/starlight/components'; + +### Background + +[Floating point numbers](https://en.wikipedia.org/wiki/Floating-point_arithmetic) are widely used in computer science to do calculation of finite precision but arbitrary scale numbers. + +Most modern CPUs are capable of performing fast floating point operations using the [IEEE binary floating point standard](https://en.wikipedia.org/wiki/Double-precision_floating-point_format) however `xahaud` does **not** use this format. Instead Xahau uses a [bespoke decimal floating point standard](https://xrpl.org/serialization.html#issued-currency-amount-format). + +This custom format has three basic properties: + +1. The format is inherently decimal, expressed as a decimal `mantissa` multipled by `10` to the power of an `exponent`. +2. All values expressed have 16 significant (decimal) figures. +3. The range of exponents is `-96` to `+80` + +When serialized the mantissa is 54 bits, and the exponent is 8 bits, with a final sign bit bringing the total size of the serialized floating point to 63 bits. + +### What is XFL? + +[XLS-17d](https://github.com/XRPLF/XRPL-Standards/discussions/39) is an XRPL standards proposal that defines an efficient way to pack and store xrpld floating point numbers (as described above). + +XFLs store the bits of the floating point number within an _enclosing number_. This is always an `int64_t`. Negative enclosing numbers represent invalid XFLs (for example as a result of division by zero.) + + + +Some example XFLs follow + +| loating Point Value | Enclosing Number | Representation | +| ------------------- | ------------------- | ----------------------------- | +| -1 | 1478180677777522688 | -1000000000000000 \* 10^(-15) | +| 0 | 0 | 0 (_canonical zero_) | +| 1 | 6089866696204910592 | +1000000000000000 \* 10^(-15) | +| _PI_ | 6092008288858500385 | +3141592653589793 \* 10^(-15) | +| -_PI_ | 1480322270431112481 | -3141592653589793 \* 10^(-15) | + +This format is very convenient for Hooks, as Hooks can only exchange _integer_ values with xrpld. By enclosing the floating point inside an integer in a well defined way it becomes possible to do complex floating point computations from a Hook. This is useful for computing exchange rates. + +### Canonical Zero + +Floating point regimes typically have a number of different ways to express zero, which can be a problem for testing for zero. For example `0 x 10 ^ 1` is zero and `0 x 10 ^ 2` is also zero. For this reason there is a canonical zero enforced by the standard and the Hook API. The canonical zero is also enclosing number zero (`0`). + +### Hook Float API + +Once you have an XFL you can use the Float API to do various computations. The Float API appears in the table below. Each API takes one or more XFL enclosing numbers and returns an XFL enclosing number. Negative return values _always_ represent a computational error (such as division by zero). There are no valid negative enclosing numbers. + +| Hook API | What it does | +| ----------------------------------------------------------------------- | --------------------------------------------------------------------- | +| [float_set](../technical/hooks-functions/float/float_set.md) | Create a float from an exponent and mantissa | +| [float_multiply](../technical/hooks-functions/float/float_multiply.md) | Multiply two XFL numbers together | +| [float_mulratio](../technical/hooks-functions/float/float_mulratio.md) | Multiply an XFL floating point by a non-XFL numerator and denominator | +| [float_negate](../technical/hooks-functions/float/float_negate.md) | Negate an XFL floating point number | +| [float_compare](../technical/hooks-functions/float/float_compare.md) | Perform a comparison on two XFL floating point numbers | +| [float_sum](../technical/hooks-functions/float/float_sum.md) | Add two XFL numbers together | +| [float_sto](../technical/hooks-functions/float/float_sto.md) | Output an XFL as a serialized object | +| [float_sto_set](../technical/hooks-functions/float/float_sto_set.md) | Read a serialized amount into an XFL | +| [float_invert](../technical/hooks-functions/float/float_invert.md) | Divide one by an XFL floating point number | +| [float_divide](../technical/hooks-functions/float/float_divide.md) | Divide an XFL by another XFL floating point number | +| [float_one](../technical/hooks-functions/float/float_one.md) | Return the number 1 represented in an XFL enclosing number | +| [float_exponent](../technical/hooks-functions/float/float_exponent.md) | Get the exponent of an XFL enclosing number | +| [float_mantissa](../technical/hooks-functions/float/float_mantissa.md) | Get the mantissa of an XFL enclosing number | +| [float_sign](../technical/hooks-functions/float/float_sign.md) | Get the sign of an XFL enclosing number | +| float_exponent_set | Set the exponent of an XFL enclosing number | +| float_mantissa_set | Set the mantissa of an XFL enclosing number | +| float_sign_set | Set the sign of an XFL enclosing number | +| [float_int](../technical/hooks-functions/float/float_int.md) | Convert an XFL floating point into an integer (floor) | +| [float_root](../technical/hooks-functions/float/float_root.md) | Compute the nth root of an XFL | +| [float_log](../technical/hooks-functions/float/float_log.md) | Compute the decimal log of an XFL | + + + +### Example + +In the below example an exchange rate conversion is performed, followed by a high precision fraction multiplication. + +```c +int64_t max_vault_pusd = + float_multiply(vault_xrp, exchange_rate); + +max_vault_pusd = + float_mulratio(max_vault_pusd, 0, + NEW_COLLATERALIZATION_NUMERATOR, NEW_COLLATERALIZATION_DENOMINATOR); +``` + + diff --git a/src/content/docs/docs/hooks/concepts/grants.mdx b/src/content/docs/docs/hooks/concepts/grants.mdx new file mode 100644 index 0000000..f941615 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/grants.mdx @@ -0,0 +1,91 @@ +--- +title: Grants +description: Hook Grants +--- +import { Aside } from '@astrojs/starlight/components'; + + + +### Grants + +Grants provide a way for a Hook Installer to assign [State Management](state-management.md) permissions to a _foreign_ Hook on other Xahau accounts. + +A [SetHook Transaction](sethook-transaction.md) may specify a `HookGrants` array within any `Hook` object in its `Hooks` array. The `HookGrants` array contains one or more `HookGrant` objects (up to 8). + +Unlike [Parameters](parameters.md), the `HookGrants` array is always set exactly as specified in the [SetHook Transaction](sethook-transaction.md). Therefore if you wish to update a particular `HookGrant` whilst retaining multiple other `HookGrant` entires that were previously set, you must first obtain the old `HookGrants` array, modify it, and then resubmit the entire array in an [_Update_ Operation](sethook-transaction.md). + +To delete all Grants submit an empty `HookGrants` array. + + + +A Grant permits a foreign XRPL account or Hook to modify the Hook State within the namespace of the specific Hook for which the Grant is defined. + +The HookGrant must specify at least: + +* `HookHash`\ + And may also specify an account: +* `Authorize` + +Only the Hook specified by HookHash may modify the Hook State within the namespace of the Hook for which the HookGrant is specified. If `Authorize` is specified then this permission is tightened further to only the Hook specified by the HookHash when it is installed on the account specified by `Authorize`. + + + +### Example + +```json +Account: "rALicebv3hMYNBWtu1VEEWkToArgYsYERs", +TransactionType: "SetHook", +Hooks: +[ + { + Hook: { + ..., + HookNamespace: "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + HookGrants: + [ + { + HookGrant: // first grant + { + HookHash: "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + }, + HookGrant: // second grant + { + Authorize: "rCLairev2ma2gNZdcHJeTk7fCQ1ki84vr9", + HookHash: "A5B8D62154DA1C329BE13582086B52612476720CEBD097EB85CEE1455E1C70A6" + } + }, + ] + } + } +], +... +``` + +The _first grant_ above allows: + +* any instance of the Hook whose code that hashes to `78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8` +* executing on **any account** +* to modify the Hook State of account `rALicebv3hMYNBWtu1VEEWkToArgYsYERs` +* inside the Namespace `3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8` + +The _second grant_ above allows: + +* any instance of the Hook whose code that hashes to `A5B8D62154DA1C329BE13582086B52612476720CEBD097EB85CEE1455E1C70A6` +* but only when executed on account `rCLairev2ma2gNZdcHJeTk7fCQ1ki84vr9` +* to modify the Hook State of account `rALicebv3hMYNBWtu1VEEWkToArgYsYERs` +* inside the Namespace `3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8` + +### Using the Grant + +To make use of a grant, a Hook modifies State objects on a foreign account by calling [state_foreign_set](../technical/hooks-functions/state/state_foreign_set.md). diff --git a/src/content/docs/docs/hooks/concepts/hook-fees.mdx b/src/content/docs/docs/hooks/concepts/hook-fees.mdx new file mode 100644 index 0000000..7b9db3a --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/hook-fees.mdx @@ -0,0 +1,64 @@ +--- +title: Hook Fees +description: What to expect when your Hook runs. +--- +### Hook Creation Fees + +SetHook transactions are charged per byte of created webassembly. The rate is 500 drops per byte. Thus a 1kib Hook will cost 0.5 XAH to create. + +### Hook Execution Fees + +When Hooks are [Strongly Executed](weak-and-strong.md) the originating transaction must pay for the Strong Executions in the originating transaction's fee. + +Hook Execution fees are charged at a rate of 1 drop per web assembly instruction in the worst-case execution of the function `hook` (or `cbak` in the case of a callback). Thus a small Hook with a lot of looping may end up attracting high runtime fees. + +### Fee RPC Helper + +Transaction fees on a ledger with the Hooks Amendment enabled become non-trivial to compute for end-users and/or wallet applications. This is because strong hooks must be paid for by the originator of a transaction, and there may be as many as 4 strong hooks on the sending account and 4 on the receiving account, as well as any other strong transactional stakeholders involved (as can be the case with some exotic transaction types). Further, if the transaction is a SetHook then the size of the parameters, the size of the code and whether it is a _create_ operation or an _install_ operation all determine the size of the fee. + +Therefore it is highly recommended that **all** transactions be run through the updated fee RPC call before they are submitted to the ledger. + +To invoke the RPC call: + +1. Open a websocket connection to the Hooks node you will be working with. +2. Compose the serialized transaction you wish to know the fee for with the following: + +* `Fee: "0"` +* `SigningPubKey: ""` (That is: 0 byte VL of type 0x73. In hex:`0x7300`.) +* Do **not** sign the transaction. + +3. Submit it as a hex blob to the RPC as follows: + +```json +{"command":"fee", "tx_blob":""} +``` + +For HTTP POST RPC submit it as follows: + +```json +{"method":"fee", "params": [{"tx_blob":""}] } +``` + +The response should look something like + +```json +{ + result: { + drops: { + base_fee: '130520', + }, + //... + }, + type: 'response' +} +``` + +Take the base fee and set it as the `Fee` field in the transaction. Now sign and submit it as per the normal transaction submission process. + +If there is an invalid value for `tx_blob` or `tx_blob` is missing, a regular JSON result will be returned with a `base_fee` of 10. + +### Emission Fees + +Hooks have access to the same computation the _Fee RPC Helper_ does. To use this simply call [etxn_fee_base](../technical/hooks-functions/emitted-transaction/etxn_fee_base.md) with a buffer containing the serialised transaction as the arguments. As with the RPC call, you must ensure that the `Fee` field is present in the serialised transaction. The value is irrelevant. + +When `etxn_fee_base` returns the recommended fee you may use [sto_emplace](../technical/hooks-functions/serialization/sto_emplace.md) to emplace it into the serialised transaction before emission. The relevant field is `sfFee`. diff --git a/src/content/docs/docs/hooks/concepts/hookon-field.mdx b/src/content/docs/docs/hooks/concepts/hookon-field.mdx new file mode 100644 index 0000000..eca806e --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/hookon-field.mdx @@ -0,0 +1,44 @@ +--- +title: HookOn Field +description: Specify which transaction types a Hook should be triggered on +--- +import { LinkCard } from '@astrojs/starlight/components'; + +### Understanding the HookOn field + +Each bit in this unsigned 256-bit integer indicates whether the Hook should execute on a particular transaction type. All bits are _active low_ **except** bit 22 which is _active high_. Since 22 is ttHOOK_SET this means the default value of all 0's will not fire on a SetHook transaction but will fire on every other transaction type. This is a deliberate design choice to help people avoid bricking their Xahau account with a misbehaving hook. + +Bits are numbered from right to left: + +* bit 0 - right most, i.e. the least significant bit. +* bit 63 - the left-most, i.e. the most significant bit. + +Examples (assuming a 256-bit unsigned integer type): + +1. If we want to completely disable the hook: + +```c +~(1ULL << 22) /* every bit is 1 except bit 22 which is 0 */ +``` + +2. If we want to disable the hook on everything except ttPAYMENT: + +```c +~(1ULL << 22) & ~(1ULL) +``` + +3. If we want to enable the hook on everything except ttHOOK_SET + +```c +0 +``` + +4. If we want to enable hook firing on ttHOOK_SET (dangerous) and every other transaction type: + +```c +(1ULL << 22) +``` + +### HookOn Calculator + + diff --git a/src/content/docs/docs/hooks/concepts/introduction/example-usage.mdx b/src/content/docs/docs/hooks/concepts/introduction/example-usage.mdx new file mode 100644 index 0000000..1513d4c --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/introduction/example-usage.mdx @@ -0,0 +1,24 @@ +--- +title: Example Usage +--- +Please read [the introduction of Hooks in this blog](https://coil.com/p/XUMM/XRPL-Labs-is-working-on-the-transaction-HOOKS-amendment-for-the-XRP-Ledger-Supporting-business-logic/kEmqhoqMW). + +While working on Hooks we published a number of blogs on our progress, insights & Hooks concepts. You can [read all about that in our blogs on Dev.to](https://dev.to/t/xrplhooks/top/infinity) + +### Examples (scenarios) + +#### 1. Receiving Hook executes additional logic + +![](../../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_XJgZhbZv8VsmtWVy9H73_d404753-1.png) + +#### 2. Receiving Hook blocks incoming transaction + +![](../../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_VXmzY1NcJIEjMtFsdj5y_08dee14-2.png) + +#### 3. Sending Hook blocks outgoing transaction + +![](../../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_FvVVFLYOs9skdbzL2PbX_468e0b5-3.png) + +#### 4. Hook controls an institutional account + +![](../../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_6S9mLMliCrlQ5JqjDld6_909b3a9-4.png) diff --git a/src/content/docs/docs/hooks/concepts/introduction/index.mdx b/src/content/docs/docs/hooks/concepts/introduction/index.mdx new file mode 100644 index 0000000..4d01184 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/introduction/index.mdx @@ -0,0 +1,33 @@ +--- +title: Introduction +--- + +import { Aside } from '@astrojs/starlight/components'; + +Hooks add smart contract functionality to the Xahau: _layer one_ custom code to influence the behaviour and flow of transactions. Hooks are small, efficient pieces of code being defined on an Xahau account, allowing logic to be executed before and/or after Xahau transactions. + + + +Xahau is known and is being appreciated for its transaction throughput, speed and the low fees. Combined with available advanced transaction types like multi sign, escrows, payment channels and even a decentralized exchange (all on ledger, out of the box, without requiring smart contracts) Xahau has a lot to offer businesses and (creative) developers. + +Hooks add smart contract functionality to Xahau: _layer one_ custom code to influence the behaviour and flow of transactions. Hooks are small, efficient pieces of code being defined on an Xahau account, allowing logic to be executed before and/or after Xahau transactions. These Hooks can be really simple, like: “reject payments < 10 XAH”, or “for all outgoing payments, send 10% to my savings account” or more advanced. + +
+![Hooks high level concept](../../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_sEBiInWuRskTqxB29Xgd_7359187-Hooks_High_Level2x_1.png) +
*Hooks high level concept*
+
+ +By allowing Hooks to not only execute efficient logic but also to store small, simple data objects, one could define a Hook like: “for incoming payments transactions, check if the sending account is in a list maintained by another Hook, and if present: reject the transaction”. + +Hooks are deliberately not Turing-Complete. While often touted as the holy grail of smart contracts, Turing-Completeness is actually inappropriate for smart contracts. (See [Blog 2](https://dev.to/wietse/hooked-2-hooks-security-smart-contracts-on-the-xrp-ledger-83e).) + +Hooks are currently live on a public testnet. It's time for testing, coding, having fun & breaking things, so a future amendment to add Hooks to Xahau livenet can be drafted with confidence. + +### Resources + +* [Xahau Testnet](https://xahau-test.net/) +* [Xahau Testnet Explorer](https://explorer.xahau-test.net/) +* [Examples (source code)](https://github.com/XRPL-Labs/xrpld-hooks/tree/hooks-ssvm/hook-api-examples) +* [Blogs (concepts)](https://dev.to/t/xrplhooks/top/infinity) diff --git a/src/content/docs/docs/hooks/concepts/loops-and-guarding.mdx b/src/content/docs/docs/hooks/concepts/loops-and-guarding.mdx new file mode 100644 index 0000000..300b032 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/loops-and-guarding.mdx @@ -0,0 +1,90 @@ +--- +title: Loops and Guarding +description: Guards are needed to perform loops in a Hook. +--- +import { Aside } from '@astrojs/starlight/components'; + +### What are guards? + +Hooks are deliberately not [Turing Complete](https://en.wikipedia.org/wiki/Turing_completeness). This means arbitrary looping is forbidden. Instead you must _guard_ your loops against a hard "maximum iteration" boundary. + +A guard is a marker placed in your code at the top of each loop. The marker informs the Xahau what the upper bound of your loop will be _in every possible scenario_. Thus if your loop usually executes twice but sometimes executes _500_ times, then your guard will say 500. + +Guards are used by the Xahau to determine the _worst case execution time_ (in instructions) of your Hook before execution. This is the basis for the fee the Xahau charges for the execution of a Hook and makes execution times predictable and controllable. + + + +### The guard function + +The guard function tells the ledger the **maximum number of iterations** a loop will make. Specifically the function takes two arguments: + +```c +int32_t _g (uint32_t id, uint32_t maxiter); +``` + +The first argument `id` is the identifier for this guard. This is a unique constant chosen by the developer, typically the line number in the source file is used. + +The second argument `maxiter` is a promise the developer makes to the ledger that this guard will not be _hit_ more than `maxiter` times during the execution of the Hook. If the guard call is executed more than this many times the Hook will automatically rollback with a `GUARD_VIOLATION` ([Hook API return codes](ref:negative-return-codes)). Because the guard will be hit _before_ the loop condition is checked, it is important to add one to the total number of expected iterations. (Note: The GUARD() macro already adds one). + + + +### Guard enforcement + +Consider the following for-loop in C: + +```c +#define GUARD(maxiter) _g(__LINE__, (maxiter)+1) +for (int i = 0; GUARD(3), i < 3; ++i) +{ + ... +} +``` + +In C, the comma operator executes each expression in a list of expressions (e.g. `A, B, C`) and returns the last expression (e.g. `C`). Thus the condition above is still `i < 3`, but the guard is called before the condition is checked. This is the only way to satisify the _guard rule_ when using a for-loop in C. + + + +Below appears the webassembly output when the above is compiled. Note the guard function being called at the start of the loop. The only instructions allowed before this call are non-branch instructions (typically manipulating constants.) + +``` + block ;; label = @1 + loop ;; label = @2 + i32.const 3 + i32.const 14 +=====> call $_g <===== + drop + ... +``` + +### Nested Loops + +When using nested loops the `maxiter` argument must reflect the total number of times the guard will be _hit_. This means you must multiply the nestings together. + +Consider the example below: + +```c +#define GUARD(maxiter) _g(__LINE__, (maxiter)+1) +for (int i = 0; GUARD(3), i < 3; ++i) +{ + for (int j = 0; GUARD(15), j < 5; ++j) + { + ... + } +} +``` + +Notice the inner-loop's guard is set to **15**. You must multiply the loops together to compute the maximum number of times an inner guard will be hit during Hook execution. + +### No recursion + +Calls to non-Hook API functions are disallowed in the Hooks ammendment. All user code must fit within the two allowed Hook functions `cbak` and `hook`. + + diff --git a/src/content/docs/docs/hooks/concepts/namespaces.mdx b/src/content/docs/docs/hooks/concepts/namespaces.mdx new file mode 100644 index 0000000..c84a895 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/namespaces.mdx @@ -0,0 +1,41 @@ +--- +title: Namespaces +description: Prevent state clobbering by using the correct namespace +--- +### Namespaces + +To avoid two or more Hooks installed on the same account unintentionally clobbering each-other's [Hook State](state-management.md), a 32 byte namespace must be provided when creating or installing each Hook. + +The namespace may be any arbitrary 32 byte value the developer chooses. Provided the namespace is unique in the Hook chain no state clobbering will occur. + +We strongly recommended using `SHA256` over the developer's working name for the Hook. SHA256 is one of the two hashing algorithms used in the derivation of Xahau addresses (from an account master key), and, as such, it should be readily available to the developer. + +The `HookNamespace` field is supplied as a 32 byte _hex_ blob inside each `Hook` object in a `Hooks` array when [executing a SetHook transaction](sethook-transaction.md). + +The configured Namespace a Hook operates under alters the [Keylets](slots-and-keylets.md) its [State](state-management.md) is stored under. Therefore two Hooks under two different Namespaces installed on the same Xahau account may use the same state key to refer to different state objects. Conversely, two different Hooks using the same Namespace on the same Xahau account can access and modify eachother's state objects using the same state keys. + +### Example + +In javascript, importing the `ripple-address-codec` yields access to SHA256.\ +(It is also possible to use `crypto.subtle` in browser, or `crypto.createHash` in node to access this hash algorithm.) + +```js +HookNamespace: addr.codec.sha256('carbon').toString('hex') +``` + +### Default Namespace + +The first user to [set a novel Hook](sethook-transaction.md) defines a `HookNamespace` which becomes the _Default Namespace_ for that Hook. This means any subsequent users who [reference the same _HookDefinition_](reference-counted-hook-definitions.md) will receive this originally set Namespace by default. + +The subsequent user may specify their own Namespace, overriding the Default Namespace for their installation only. + +### Hook APIs Affected + +Choice of HookNamespace affects the behaviour of the following Hook APIs: + +* [state](../technical/hooks-functions/state/) +* [state_set](../technical/hooks-functions/state/state_set.md) + +### Namespace API Helper + +See [account_info](../technical/hooks-functions/websocket-apis/account_info.md) and [account_namespace](../technical/hooks-functions/websocket-apis/account_namespace.md) for information about how to query the ledger regarding namespaces. diff --git a/src/content/docs/docs/hooks/concepts/parameters.mdx b/src/content/docs/docs/hooks/concepts/parameters.mdx new file mode 100644 index 0000000..b21a6b0 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/parameters.mdx @@ -0,0 +1,57 @@ +--- +title: Parameters +description: Install-time parameters allow Hooks to be generic and flexible +--- +### Parameters + +Hook developers may opt to use _install-time_ parameters (called Hook Parameters) in their Hook. This allows subsequent installers of the Hook to change certain behaviours the programmer defines without recompiling or re-uploading the Hook (assuming at least one account still [references](reference-counted-hook-definitions.md) the existing Hook Definition.) + +Hook Parameters are a set of Key-Value pairs set during the [SetHook Transaction](sethook-transaction.md) and retrievable by the Hook during runtime. Both the `ParameterName` (key) and the `ParameterValue` are set as _hex_ blobs, and have a maximum length of 32 bytes and 256 bytes respectively. + +A [SetHook Transaction](sethook-transaction.md) may define up to _16_ Hook Parameters per installed Hook. + +### Setting Parameters + +The `HookParameters` array is optionally defined inside each `Hook` in the `Hooks` array as shown below: + +```json +TransactionType: "SetHook", +Hooks: +[ + { + Hook: { + ..., + HookParameters: + [ + { + HookParameter: + { + HookParameterName: "ABCDEF12", + HookParameterValue: "12345678" + } + }, + ... // optionally up to 15 more Hook Parameters + ] + } + } +], +... +``` + +### Default Parameters + +The first user to [set a novel Hook](sethook-transaction.md) may define Hook Parameters which then become the _Default Parameters_ for that Hook. This means any subsequent users who [references the same _HookDefinition_](reference-counted-hook-definitions.md) will receive these originally set Hook Parameters by default. + +The subsequent user may specify their own Parameters, overriding the Default Parameters for their installation. + +To erase a Parameter in a subsequent installation, specify the `ParameterName` key without specifying a `ParameterValue` key. + +### Using Parameters in Hooks + +Parameters can be read by the Hooks they are set on using [hook_param](../technical/hooks-functions/hook-context/hook_param.md). + +If more than one Hook is installed in a Hook Chain, then [hook_param_set](../technical/hooks-functions/hook-context/hook_param_set.md) can be used in limited circumstances to modify the Hook Parameters of a Hook further down the chain on the same account. + +### Runtime Parameters + +On Xahau and the Xahau testnet, HookParameters may also be included at the top level of any transaction type according to the foregoing rules and size limits. These parameters can be accessed inside a hook using the [otxn_param](../technical/hooks-functions/originating-transaction/otxn_param.md) API. diff --git a/src/content/docs/docs/hooks/concepts/reference-counted-hook-definitions.mdx b/src/content/docs/docs/hooks/concepts/reference-counted-hook-definitions.mdx new file mode 100644 index 0000000..a56b67d --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/reference-counted-hook-definitions.mdx @@ -0,0 +1,14 @@ +--- +title: Reference Counted Hook Definitions +description: Avoid re-uploading the same bytecode to the ledger +--- +When a novel Hook's web assembly byte-code is uploaded to Xahau, a significant storage burden is imposed on the network. This storage burden is reflected in the [Hook Fees](hook-fees.md) charged by the network. + +To avoid this burden (and high fees for end users) reference counting is used: + +* The first time a novel Hook is installed, the [SetHook Transaction](sethook-transaction.md) must provide a significant fee. +* The Hook's web assembly byte-code becomes an unowned and reference counted object on the ledger (called a `HookDefinition`). +* Subsequent installations by the same or other users for an identical Hook (i.e. with identical byte-code) increment the reference count. These installations point at the same object on the ledger. These transactions are billed in a similar way to setting a Trust Line, as the storage burden for the Hook was already paid for in the original Set Hook transaction. +* While the reference count on the Hook Definition is greater than zero (meaning one or more accounts still have the Hook installed) the object remains on the ledger. + +![](<../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_TlDL7tsVNYi1yU64EZQh_3ef0cee-sethook-Page-2.png>) diff --git a/src/content/docs/docs/hooks/concepts/serialized-objects.mdx b/src/content/docs/docs/hooks/concepts/serialized-objects.mdx new file mode 100644 index 0000000..99a26fa --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/serialized-objects.mdx @@ -0,0 +1,54 @@ +--- +title: Serialized Objects +description: Manipulate raw serialized xahaud objects! +--- +### What are Serialized Objects? + +The XRP Ledger has canonical [serialized](https://xrpl.org/serialization.html) forms of all objects subject to consensus. When writing a Hook it is inevitable you will come across serialized objects. These manifest as buffers containing what might appear to the developer as opaque binary blobs. In fact you can read these with the [XRPL-Binary-Visualiser](https://richardah.github.io/xrpl-binary-visualizer/). + +For example an `sfAmount` field serializes to a collection of bytes like `61D50F26109A32B7EC` + +### Serialized Object API + +To assist Hook developers in working with serialized objects the `sto` namespace was created within the Hooks API. These functions manipulate pointers within a Hook-provided buffer. See table below. + +| Hook API | at it does | +| --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | +| [sto_subfield](../technical/hooks-functions/serialization/sto_subfield.md) | Index into a xrpld serialized object and return the location and length of a subfield | +| [sto_subarray](../technical/hooks-functions/serialization/sto_subarray.md) | Index into a xrpld serialized array and return the location and length of an index | +| [sto_emplace](../technical/hooks-functions/serialization/sto_emplace.md) | Emplace a field into an existing STObject at its canonical placement | +| [sto_erase](../technical/hooks-functions/serialization/sto_erase.md) | Remove a field from an STObject | +| [sto_validate](../technical/hooks-functions/serialization/sto_validate.md) | Validate an STObject | + +Where applicable these APIs return an _offset_ and a _length_ encoded into a single int64_t. See individual documentation for details. + +### Example + +At typical scenario in which you would use the STO API is in processing memos on an Originating Transaction. Since you will likely need access to the whole memo anyway, an efficient way to process a set of memos is simply to dump the whole `sfMemos` field into a buffer then index around within it. While it is also possible to use the slot API to do this by slotting the Originating Transaction it would result in additional code and additional copying. + +```c +#define SUB_OFFSET(x) ((int32_t)(x >> 32)) +#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL)) +#define SBUF(str) (uint32_t)(str), sizeof(str) + +uint8_t memos[2048]; +int64_t memos_len = otxn_field(SBUF(memos), sfMemos); +for (int i = 0; GUARD(3), i < 3; ++i) +{ + int64_t memo_lookup = sto_subarray(memos, memos_len, i); + if (memo_lookup < 0) + rollback(SBUF("Memo lookup error"), 1); + uint8_t* memo_ptr = SUB_OFFSET(memo_lookup) + memos; + uint32_t memo_len = SUB_LENGTH(memo_lookup); + // the above now point at the memo ... do something here +} +``` + +### Overlap with slots + +You may notice some overlap between slot APIs and STO APIs. The key difference here is who _owns_ the underlying data: + +* If you are using _slots_ then xrpld owns the object you are interacting with. +* If you are using the _STO API_ then the **Hook** owns the buffer you are interacting with. + +Both sets of functions index into a Serialized Object without unnecessary copying. diff --git a/src/content/docs/docs/hooks/concepts/sethook-transaction.mdx b/src/content/docs/docs/hooks/concepts/sethook-transaction.mdx new file mode 100644 index 0000000..42e8477 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/sethook-transaction.mdx @@ -0,0 +1,314 @@ +--- +title: SetHook Transaction +--- +### SetHook Transaction + +Hook web assembly bytecode is installed onto an Xahau account using the `SetHook` transaction. + +An example appears below: + +```js +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + CreateCode: fs.readFileSync('accept.wasm').toString('hex').toUpperCase(), + HookOn: '0000000000000000', + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + HookApiVersion: 0 + } + } + ] +} +``` + +The transaction is deceptively simple, but hides significant complexity, described below. + +### Hooks Array + +The main body of the SetHook transaction is the hooks array: + +```js +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Hooks: // This is the Hooks Array + [ + { Hook: { ... } }, // HookSet Object (position 0) + { Hook: { ... } }, + { Hook: { ... } }, + { Hook: { ... } }. // HookSet Object (position 3) + ] +} +``` + +This array _mirrors_ the [Hook Chain](chaining.md) installed on the account: + +* Position 0 in the array _corresponds_ to position 0 in the Hook Chain. +* Position 3 in the array _corresponds_ to position 3 in the Hook Chain, etc. + +### HookSet Object and Corresponding Hook + +Each entry in the Hooks Array (in the SetHook Transaction) is called a _HookSet Object_, and its corresponding Hook in the account's Hook Chain is called the _Corresponding Hook_. + +
+![Example: A user performs an operation on each Hook in his/her Hook chain with a SetHook transaction.](../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_NbV5W3McCRKkL4eJeF6v_cdf692e-sethook.png) +
*Example: A user performs an operation on each Hook in his/her Hook chain with a SetHook transaction.*
+
+ +### HookDefinition + +Each Corresponding Hook is an object containing a _reference_ (pointer) to a `HookDefinition` object. + +The HookDefinition object is an unowned reference-counted ledger object that provides for de-duplication of identical web assembly bytecode. Two users using an identical hook will both point to the same HookDefinition. + +
+![Example: Hook Definitions on Xahau](../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_TlDL7tsVNYi1yU64EZQh_3ef0cee-sethook-Page-2.png) +
*Example: Hook Definitions on Xahau*
+
+ +For more information see: [Reference Counting](reference-counted-hook-definitions.md) + +### Hook Defaults + +When a `HookDefinition` is created it contains the initial [Parameters](parameters.md), [Namespace](namespaces.md) and [Grants](grants.md) supplied by the user. These become the Hook Defaults. Any Hook referencing this Hook Definition will use these defaults _unless_ the SetHook Transaction that creates that reference explicitly overrides those defaults, or a subsequent Update Operation overrides them. + +### HookSet Operations + +There are six possible operations: No Operation, Create, Update, Delete, Install and Namespace Delete + +Each operation is specified by the inclusion or omission of certain HookSet Object fields. This might seem confusing at first but by working through a few examples the reader should find it intuitive; Essentially HookSet operations are a type of **diff** between a specific Hook's _defaults_, _existing_ and newly specified fields. + +Achieving each type of operation is explained in a subsection below. + +### No Operation + +**Occurs when**: + +* The HookSet Object is empty + +**Behaviour**: + +* No change of any kind is made. + +**Example**: + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: {} + } + ] +} +``` + +### Create Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook does not exist _or_`FLAG_OVERRIDE` is specified. +* `CreateCode` field is specified and is not blank and contains the valid web assembly bytecode for a valid Hook. +* No instance of the same web assembly bytecode already exists on Xahau. (If it does and all other requirements are met then interpret as an Install Operation — see below.) + +**Behaviour**: + +* A reference counted `HookDefinition` object is created on Xahau containing the fields in the HookSet Object, with all specified fields (Namespace, Parameters, HookOn) becoming defaults (but not Grants.) +* A `Hooks` array is created on the executing account, if it doesn't already exist. (This is the structure that contains the Corresponding Hooks.) +* A `Hook` object is created at the Corresponding Hook position if one does not already exist. +* The `Hook` object points at the `HookDefinition`. +* The `Hook` object contains no fields except `HookHash` which points at the created `HookDefinition`. +* If `hsfNSDELETE` flag is specified then any HookState entires in the destination namespace are deleted if they currently exist. + +**Example**: + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + CreateCode: fs.readFileSync('accept.wasm').toString('hex').toUpperCase(), + HookOn: '0000000000000000', + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + HookApiVersion: 0 + } + } + ] +} +``` + +### Install Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook does not exist _or_`FLAG_OVERRIDE` is specified. +* `HookHash` field is specified and is not blank and contains the hash of a Hook that already exists as a `HookDefinition` on the ledger _or_ `CreateCode` field is specified and is not blank and contains the valid web assembly bytecode for a valid hook that already exists on the ledger as a `HookDefinition`. + +**Behaviour**: + +* The reference count of the `HookDefinition` object is incremented. +* A `Hooks` array is created on the executing account, if it doesn't already exist. (This is the structure that contains the Corresponding Hooks.) +* A `Hook` object is created at the Corresponding Hook position if one does not already exist. +* The `Hook` object points at the `HookDefinition`. +* The `Hook` object contains all the fields in the HookSet Object, except and unless: +* A field or key-pair within a field is identical to the Hook Defaults set on the `HookDefinition`, in which case it is omitted due to defaults. +* If `hsfNSDELETE` flag is specified then any HookState entires in the destination namespace are deleted if they currently exist. + +**Example**: + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + HookHash: "A5663784D04ED1B4408C6B97193464D27C9C3334AAF8BBB4FA5EB8E557FC4A2C", + HookOn: '0000000000000000', + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + } + } + ] +} +``` + +### Update Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook exists. +* `HookHash` is absent. +* `CreateCode` is absent. +* One or more of `HookNamespace`, `HookParameters` or `HookGrants` is present. + +**General Behaviour**: + +* The Corresponding Hook is updated in such a way that the desired changes are reflected in the Corresponding Hook. + +**Specific Behaviour**: + +If `HookNamespace` is specified and differs from the Corresponding Hook's Namespace: + +* the Corresponding Hook's `HookNamespace` is updated, and +* if the `hsfNSDELETE` flag is specified all HookState entires in the old namespace are deleted. + +If `HookParameters` is specified, then for each entry: + +* If `HookParameterName` exists but `HookParameterValue` is absent and the Corresponding Hook's Parameters (either specifically or via defaults) contains this `HookParameterName` then the parameter is marked as deleted on the Corresponding Hook. +* If `HookParameterName` exists and `HookParameterValue` exists then the Corresponding Hook's Parameters are modified to include the new or updated parameter. + +If `HookGrants` is specified then: + +* The Corresponding Hook's `HookGrants` array is replaced with the array. + +**Example**: + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + HookNamespace: addr.codec.sha256('new_accept').toString('hex').toUpperCase(), + } + } + ] +} +``` + +### Delete Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook exists. +* `hsfOVERRIDE` is specified. +* optionally `hsfNSDELETE` is also specified. +* `HookHash` is absent. +* `CreateCode` is present but empty. + +**Behaviour**: + +* The reference count of the `HookDefinition` object is decremented. +* If the reference count is now zero the `HookDefintion` is removed from the ledger. +* The `Hook` object in the Corresponding Hook position is deleted, leaving an empty position. +* If `hsfNSDELETE` is specified the namespace and all HookState entries are also deleted. + +**Example**: + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + CreateCode: "", + Flags: 1, + } + } + ] +} +``` + +### Namespace Reset + +**Occurs when**: + +_All_ of the following conditions are met: + +* `flags` is present and `hsfNSDELETE` is set. `hsfOVERRIDE` can optionally also be specified if the Hook at this position is to be deleted. +* `HookNamespace` is specified. +* `CreateCode` is absent. +* `HookHash` is absent. +* `HookGrants`, `HookParameters`, `HookOn` and `HookApiVersion` are absent. + +**Behaviour**: + +* If the Corresponding Hook exists, it remains, nothing happens to it. +* A subset of HookState objects and the HookState directory for the specified namespace are removed from the ledger, up to the defined limit of 512. Further transactions are needed to continue the deletion process until all relevant records are removed. + +**Example**: + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + Flags: 3, + } + } + ] +} +``` diff --git a/src/content/docs/docs/hooks/concepts/slots-and-keylets.mdx b/src/content/docs/docs/hooks/concepts/slots-and-keylets.mdx new file mode 100644 index 0000000..7334ee1 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/slots-and-keylets.mdx @@ -0,0 +1,62 @@ +--- +title: Slots and Keylets +description: Inspect and manipulate on-ledger objects. +--- +import { Aside } from '@astrojs/starlight/components'; + +### Background + +Xahau contains numerous heterogenous object types which a Hook has read-access to. For example: _transactions_, _accounts_, _ledgers_, and the subcomponents of each of these, to name just a few. + +It is very easy to carelessly program a computer to do a lot of needless copy operations when disciplined access to the same underlying data (i.e. through a view) would suffice. The deliberate avoidance of copy operations in programming is referred to as [Zero copy](https://en.wikipedia.org/wiki/Zero-copy) in programming. + +With Hooks the same principle applies. We want to avoid copying where possible. In particular we want to avoid as much as possible needlessly copying large objects such as whole ledgers, we also want to avoid serializaing and unserializing these where possible. + +### What are slots? + +Slots are part of the Hook API and provide a zero-copy _heterogenous_ access system for on-ledger objects and transactions. + +* Each Hook has access to 255 slots during runtime. +* Each slot may be empty or may contain a _slotted_ object. +* The slot API allows traversal into inner objects, and allows these inner objects themselves to be slotted. +* The slot API allows slotted objects to be dumped to a buffer or otherwise read by the Hook. + +The avilable slot APIs are: + +| Hook API | What it does | +| -------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| [slot](../technical/hooks-functions/slot/slot.md) | Serialize and output a slotted object | +| [slot_clear](../technical/hooks-functions/slot/slot_clear.md) | Free up a currently occupied slot | +| [slot_count](../technical/hooks-functions/slot/slot_count.md) | Count the elements of an array object in a slot | +| slot_id | Compute the canonical hash of the slotted object and return it | +| [slot_set](../technical/hooks-functions/slot/slot_set.md) | Locate an object based on its keylet and place it into a slot | +| [slot_subarray](../technical/hooks-functions/slot/slot_subarray.md) | Index into a slotted array and assign a sub-object to another slot | +| [slot_subfield](../technical/hooks-functions/slot/slot_subfield.md) | Index into a slotted object and assign a sub-object to another slot | +| [slot_type](../technical/hooks-functions/slot/slot_type.md) | Retrieve the field code of an object in a slot and, optionally, some other information | +| [slot_float](../technical/hooks-functions/slot/slot_float.md) | Parse the STI_AMOUNT in the specified slot and return it as an XFL enclosed number | +| [slot_size](../technical/hooks-functions/slot/slot_size.md) | Compute the serialized size of an object in a slot | + +### What are keylets? + +Keylets are used to locate (point to) on-ledger objects. In brief they are a _hash_ of identifying information from the object, which is the canonical _handle_ for that object. + +Hooks use a serialized 34 byte keylet format which can be derrived using the important [util_keylet](ref:util_keylet) function. Without this looking up and slotting objects would be generally impossible. + + + +### Example + +In the following example a 34 byte keylet for a `signers` object is used to slot that object. + +```c +uint8_t keylet[34]; +if (util_keylet(SBUF(keylet), KEYLET_SIGNERS, SBUF(hook_accid), 0, 0, 0, 0) != 34) + rollback(SBUF("Notary: Internal error, could not generate keylet"), 10); + +// then requesting XRPLD slot that keylet into a new slot for us +int64_t slot_no = slot_set(SBUF(keylet), 0); +if (slot_no < 0) + rollback(SBUF("Notary: Could not set keylet in slot"), 10); +``` diff --git a/src/content/docs/docs/hooks/concepts/state-management.mdx b/src/content/docs/docs/hooks/concepts/state-management.mdx new file mode 100644 index 0000000..dedce0c --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/state-management.mdx @@ -0,0 +1,65 @@ +--- +title: State Management +description: Hooks can read and save small pieces of on-ledger data 🚀 +--- +import { Aside } from '@astrojs/starlight/components'; + +### What is Hook State? + +[State](https://en.wikipedia.org/wiki/State_\(computer_science\)) in computer science describes information held by a system between executions (as distinct from inputs and outputs.) For example your browser leaves you logged in to a website even after you close and reopen it. The login cookie is held in the browser's _state_. + +**Hook State** refers to a key-value mapping that logically exists for each account on Xahau whether or not any keys are currently present. The keys are always 32 bytes (unsigned 256 bit integer) and the values are variable length with a maximum size determined by validator voting, at time of writing 256 bytes. + +State Management is achieved using + +* [state](../technical/hooks-functions/state/state.md) +* [state_set](../technical/hooks-functions/state/state_set.md) +* [state_foreign](../technical/hooks-functions/state/state_foreign.md) + +### Storing and fetching + +The below example uses the [state_set](../technical/hooks-functions/state/state_set.md) Hook API to assign the value `0xC001CAFE` to the key `0x0..000001` (uint256 = 1) in the Hook State of the Hook Account. + +```c +uint8_t key[32] = { + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U +}; +uint8_t value[4] = { 0xC0U, 0x01U, 0xCAU, 0xFEU }; +if (state_set(value, 4, key, 32) == 4) +{ + // ... state successfully saved +} +``` + +In a subsequent Hook execution this value can now be retrieved using the same key: + +```c +uint8_t value[4]; +uint8_t key[32] = { + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, + 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x01U +}; +if (state(value, 4, key, 32) < 0) +{ + // ... state fetch failed +} +``` + +After the above code has run the `value` buffer will be populated with the value found at the key. + + + +### Foreign state + +From time to time it may be advantageous for one Hook running on one account to read the Hook State of another Hook running on another account. The [state_foreign](../technical/hooks-functions/state/state_foreign.md) Hook API does exactly this. Because the ledger is public there is no reasonable expectation of privacy anyway. Any Hook may therefore _read_ (but not write) the Hook State of any other Hook. + +### Namespaces and querying + +Please see [Namespaces](namespaces.md) diff --git a/src/content/docs/docs/hooks/concepts/terminology.mdx b/src/content/docs/docs/hooks/concepts/terminology.mdx new file mode 100644 index 0000000..3eaabc1 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/terminology.mdx @@ -0,0 +1,38 @@ +--- +title: Terminology +description: Welcome to Hooks 👋 +--- +### What are Hooks? + +Hooks are small, efficient web assembly modules designed specifically for Xahau. Hooks can be written in any language (compilable to WebAssembly) and most business logic and most smart contract concepts can be implemented in a hook. Typically Hooks are written in C. + +Hooks are set onto an Xahau account using a `SetHook` transaction. Once installed on an account, a hook can: + +1. Block or allow incoming and outgoing transactions on the account, +2. Modify and maintain internal state and logic specific to the hook on that account, and +3. Emit new transactions on behalf of the account. + +### Glossary + +This Hooks documentation and the Hooks API use a set of unfamiliar terms. Use the lookup table below if you find yourself lost. + +| Term | Explanation | +| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Hook |

This term refers to a range of things depending on context
1. A webassembly binary uploadable to Xahau with the SetHook Transaction type.
2. A webassembly binary already uploaded to and set or configured onto an Xahau account.
3. The source code of such a binary.

| +| Originating Transaction | The transaction that triggered the Hook to fire. This could be either a transaction sent out of or into an account with a Hook set on it. | +| Originating Account | The account that sent an Originating Transaction. | +| Hook Account | The account where the currently executing Hook lives. This is the account that owns the Hook, the account that performed the [SetHook Transaction](sethook-transaction.md) which created the Hook and the account to whom belongs the Hook State for the currently executing Hook. | +| Installer | The account which is currently installing a Hook using the SetHook transaction. | +| Emitted Transaction | A new transaction created by a Hook during the Hook's execution that is not the Originating Transaction. These are typically used for sending funds back to the Originating Account. See: [Emitted Transactions](emitted-transactions.md). | +| State | A per-account key-value map of 32 byte keys to arbitrary data. All Hooks present on an account have access to the same Hook State and can modify it. Note that the Hook State lives on the Hook Account **not** on the Originating Account. See: [State Management](state-management.md). | +| SetHook | A new Transaction Type introduced in the Hooks ammendment which sets a Hook onto an Xahau account. See: [SetHook Transaction](sethook-transaction.md). | +| Guards | A special control mechanism you need to use if you write a loop into in a Hook. See: [Loops and Guarding](loops-and-guarding.md). | +| Grants | Special permission a Hook Installer can give another account or a specific Hook (regardless of where it is installed) to modify Hook State on the Installer's account. | +| Namespace | A unique 32 byte code delineating one set of state keys from another. The same state key may be used by two different Hooks without interfering with each-other if the namespaces set on the Hooks are different. | +| Parameters | Install-time parameters that can be optionally set on a Hook. | +| Reference Counting | An unowned object on the ledger may be reference counted, meaning it is deleted when the final account which referenced (used) it removes their reference to it. | +| XFL or Floating Point | A way to do high precision math in Hooks such as for exchange rate computation. See: [Floating Point Numbers (XFL)](floating-point-numbers-xfl.md). | +| Serialized Objects (STO) | The way xahaud transmits and stores ledger objects. See: [Serialized Objects](serialized-objects.md). | +| Slots and Keylets | Slots can contain ledger objects and keylets identify those objects. See: [Slots and Keylets](slots-and-keylets.md). | +| Trace | A way to print a log line to the xrpld output from a Hook. See: [Debugging Hooks](debugging-hooks.md). | + diff --git a/src/content/docs/docs/hooks/concepts/weak-and-strong.mdx b/src/content/docs/docs/hooks/concepts/weak-and-strong.mdx new file mode 100644 index 0000000..4f549f9 --- /dev/null +++ b/src/content/docs/docs/hooks/concepts/weak-and-strong.mdx @@ -0,0 +1,241 @@ +--- +title: Weak and Strong +description: Which Hooks are allowed to run and when? +--- +import { Aside } from '@astrojs/starlight/components'; + + + +Transactional Stake Holders (TSH) are parties that somehow have a stake in or are otherwise affected by a transaction. Their particular stake may be a _weak_ or _strong_. The degree of connection with the transaction dictates whether the party has the right to have their Hooks executed and who has to pay for that execution. + +For example: + +* In a conventional direct XAH **Payment** transaction the two TSH are the _originating account_ and the _destination account_. +* In a **SetSignerList** transaction the TSH are the _originating account_ and each account whose address appears in the signer list, where such accounts are active on the ledger. +* In an **OfferCreate** transaction, other account's offers which are crossed by the originating transaction are all weak TSH and may opt for weak execution. + +Due to the heterogenous nature of transactions on Xahau, TSH come in all shapes and sizes and can be exotic and non-intuitive. This becomes more true as time passes and more transaction types are added to the Ledger. + +### Weak and Strong + +Each TSH has either a weak or a strong connection to the transaction. + +A **Strong** connection means: + +1. The originating transaction must pay the fee for the execution of the TSH Hook Chain +2. The TSH has the right to rollback the whole transaction by calling `rollback()` from their Hook during execution. + +A **Weak** connection means: + +1. The originating transaction **does not** pay for the execution of the TSH Hook Chain. +2. The TSH pays for the execution of their own Hook Chain through a feature called [Collect Call Hooks](collect-call.md). +3. The TSH must have set an account flag `asfTshCollect` prior to the execution of the originating transaction. +4. The TSH **does not** have the right to rollback the whole transaction by calling `rollback()` from their Hook during execution (but can still modify their own Hook state and Emit transactions.) + +### Before or After + +Strong TSHes have their hooks executed _before_ the originating transaction is applied to the ledger. This means they have the ability to [rollback](../technical/hooks-functions/control/rollback.md) the transaction (because it hasn't yet been applied.) This gives strongly executed hooks the ability to completely block a transaction from occurring. + +Weak TSHes have their hooks executed _after_ the originating transaction has been applied to the ledger. This means they have access to the [transaction metadata](../technical/hooks-functions/originating-transaction/meta_slot.md) but cannot prevent the transaction from occurring. + + + +### Execution Context + +The `uint32_t` parameter in `hook(uint32_t)` and `cbak(uint32_t)` carries important context information from the Hooks Amendment to your Hook. + +During the execution of `hook`: + +* 0 means the Hook is being executed _strongly_ +* 1 means the Hook is being executed _weakly_ +* 2 means the Hook is being executed _weakly_ after being executed _strongly_ due to a [hook_again](../technical/hooks-functions/hook-context/hook_again.md) call. + +During the execution of `cbak`: + +* 0 means the Hook is being called back after a transaction it emitted was successfully accepted into a ledger. +* 1 means the Hook is being called back after a transaction it emitted was marked as never able to be applied to any ledger (EmitFailure). + +### Reference Table + +If a Transaction Type does not appear in the table then it has no TSHes **other than its originating account.** + + + +| Transaction Type | TSH Type | Who is the TSH | +| ----------------------- | ------------- | -------------------------------------------------------------------------------------------- | +| AccountDelete | Strong | Destination account funds are paid out to after deletion | +| AccountSet | None | N/A | +| CheckCancel | Weak | Destination account | +| CheckCash | None | N/A | +| CheckCreate | Strong | Destination account | +| ClaimReward | Strong | Issuer Account | +| DepositPreauth | Strong | Authorized account | +| EscrowCancel | Weak | Destination account | +| EscrowCreate | Strong | Destination account | +| EscrowFinish | Strong | Destination account | +| GenesisMint | Weak | Each Destination in the GenesisMints Array | +| Import | Strong | Issuer Account | +| Invoke | Strong | Destination account | +| OfferCancel | None | N/A | +| OfferCreate | Weak | Accounts whose offers were crossed by this action. | +| Payment | Strong + Weak | Strong: Destination account. Weak: Any non-issuer the payment is rippled through. | +| PaymentChannelClaim | Weak | Destination account | +| PaymentChannelCreate | Strong | Destination account | +| PaymentChannelFund | Weak | Destination account | +| SetHook | None | N/A | +| SetRegularKey | Strong | The account whose address is being set as the key. | +| SignerListSet | Strong | Accounts whose addresses are set as signing keys (if they exist and have Hooks set on them). | +| TicketCreate | None | N/A | +| TrustSet | Weak | Issuer account | +| URITokenCancelSellOffer | None | N/A | +| URITokenCreateSellOffer | Strong | Destination account, Issuer if tfBurnable Flag is set | +| URITokenBurn | Strong | Issuer if tfBurnable Flag is set | +| URITokenBuy | Strong | Owner account, Issuer if tfBurnable Flag is set | +| URITokenMint | None | N/A | + +**AccountSet** + +| OTXN | TSH | AccountSet | +| ------- | ------- | ---------- | +| Account | Account | Strong | + +**AccountDelete** + +| OTXN | TSH | AccountDelete | +| ------- | ----------- | ------------- | +| Account | Account | None | +| Account | Beneficiary | Strong | + +**Check** + +| OTXN | TSH | CheckCancel | CheckCreate | CheckCash | +| ----------- | ----------- | ----------- | ----------- | --------- | +| Account | Account | Strong | Strong | None | +| Account | Destination | Weak | Strong | None | +| Destination | Destination | Strong | None | Strong | +| Destination | Account | Weak | None | Weak | + +**ClaimReward** + +| OTXN | TSH | ClaimReward | +| ------- | ------- | ----------- | +| Account | Account | Strong | +| Account | Issuer | Strong | + +**DepositPreauth** + +| OTXN | TSH | DepositPreauth | +| ------- | ---------- | -------------- | +| Account | Account | Strong | +| Account | Authorized | Strong | + +**Escrow** + +| OTXN | TSH | EscrowCancel | EscrowCreate | EscrowFinish | +| ----------- | ----------- | ------------ | ------------ | ------------ | +| Account | Account | Strong | Strong | Strong | +| Account | Destination | Weak | Strong | Weak | +| Destination | Destination | Strong | None | Strong | +| Destination | Account | Weak | None | Weak | + +**GenesisMint** + +| OTXN | TSH | GenesisMint | +| ------- | ----------- | ----------- | +| Account | Account | Strong | +| Account | Destination | Strong | +| Account | Beneficiary | Weak | + +**Import** + +| OTXN | TSH | Import | +| ------- | ------- | ------ | +| Account | Account | Strong | +| Account | Issuer | Strong | + +**Invoke** + +| OTXN | TSH | Invoke | +| ------- | ----------- | ------ | +| Account | Account | Strong | +| Account | Destination | Weak | + +**Offer** + +| OTXN | TSH | OfferCancel | OfferCreate | +| ------- | ------- | ----------- | ----------- | +| Account | Account | Strong | Strong | +| Account | Crossed | None | Weak | + +**Payment** + +| OTXN | TSH | Payment | +| ------- | ----------- | ------- | +| Account | Account | Strong | +| Account | Destination | Strong | +| Account | Crossed | Weak | + +**PaymentChannel** + +| OTXN | TSH | PaymentChannelClaim | PaymentChannelCreate | PaymentChannelFund | +| ----------- | ----------- | ------------------- | -------------------- | ------------------ | +| Account | Account | Strong | Strong | Strong | +| Account | Destination | Weak | Strong | Weak | +| Destination | Destination | Strong | None | None | +| Destination | Account | Weak | None | None | + +**SetHook** + +| OTXN | TSH | SetHook | +| ------- | ------- | ------- | +| Account | Account | Strong | + +**SetRegularKey** + +| OTXN | TSH | SetRegularKey | +| ------- | ---------- | ------------- | +| Account | Account | Strong | +| Account | RegularKey | Strong | + +**SignersListSet** + +| OTXN | TSH | SignerListSet | +| ------- | ------- | ------------- | +| Account | Account | Strong | +| Account | Signer | Strong | + +**Ticket** + +| OTXN | TSH | TicketCreate | +| ------- | ------- | ------------ | +| Account | Account | Strong | + +**TrustSet** + +| OTXN | TSH | TrustSet | +| ------- | ------- | -------- | +| Account | Account | Strong | +| Account | Issuer | Weak | + +**URIToken** + +| OTXN | Burnable | TSH | Mint | Burn | Buy | Sell | Cancel | +| ------ | -------- | ------ | ------ | ------ | ------ | ------ | ------ | +| Owner | False | Owner | None | Strong | Strong | Strong | Strong | +| Owner | False | Issuer | None | Weak | Weak | Weak | None | +| Owner | False | Buyer | None | None | None | Strong | Weak | +| Owner | True | Buyer | None | None | None | Strong | Weak | +| Owner | True | Owner | None | Strong | Strong | Strong | Strong | +| Owner | True | Issuer | None | Weak | Strong | Strong | None | +| Issuer | False | Owner | None | None | None | None | None | +| Issuer | False | Issuer | Strong | None | None | None | None | +| Issuer | False | Buyer | Weak | None | None | None | None | +| Issuer | True | Owner | None | Weak | None | None | None | +| Issuer | True | Issuer | Strong | Strong | None | None | None | +| Issuer | True | Buyer | Weak | None | None | None | None | +| Buyer | True | Buyer | None | None | Strong | None | None | +| Buyer | True | Owner | None | None | Weak | None | None | diff --git a/src/content/docs/docs/hooks/functions/control/accept.mdx b/src/content/docs/docs/hooks/functions/control/accept.mdx new file mode 100644 index 0000000..6d6996a --- /dev/null +++ b/src/content/docs/docs/hooks/functions/control/accept.mdx @@ -0,0 +1,101 @@ +--- +title: accept +description: Accept the originating transaction and commit any changes the hook made. +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Introduction +Execution Metadata + +### Behaviour + +End the execution of the hook with status: success. + +* Record a return string and return code in transaction metadata. +* Commit all state changes. +* Submit all `emit()` transactions. +* Allow originating transaction to continue. + + + +### Definition + + + +```c +int64_t accept ( + uint32_t read_ptr, + uint32_t read_len, + uint64_t error_code +); +``` + + + +```javascript +function accept(msg: string, code: number): number +``` + + + + + +### Example + + + +```c +accept("Success", 7, 100); +``` + + + +```javascript +accept('Success', 100) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| read_ptr | uint32_t |

Pointer to a return string to be stored in execution metadata.
This is any string the hook-developer wishes to return with the acceptance. May be null.

| +| read_len | uint32_t | The length of the return string. At most 32. _May be null._ | +| error_code | uint64_t |

A return code specific to this hook to be stored in execution metadata.

Similar to the return code of an application on a *nix system. By convention success is zero.

| +
+ + +| Name | Type | Description | +| ---- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| msg | string |

String to be stored in execution metadata.
This is any string the hook-developer wishes to return with the acceptance. May be null.

| +| code | number |

A return code specific to this hook to be stored in execution metadata.

Similar to the return code of an application on a *nix system. By convention success is zero.

| +
+
+ + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t | Accept ends the hook, therefore no value is returned to the caller. By convention all Hook APIs return `int64_t`, but in this case nothing is returned. | + + + +| Type | Description | +| ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| number | Accept ends the hook, therefore no value is returned to the caller. By convention all Hook APIs return `a number`, but in this case nothing is returned. | + + + diff --git a/src/content/docs/docs/hooks/functions/control/rollback.mdx b/src/content/docs/docs/hooks/functions/control/rollback.mdx new file mode 100644 index 0000000..8ebef4c --- /dev/null +++ b/src/content/docs/docs/hooks/functions/control/rollback.mdx @@ -0,0 +1,80 @@ +--- +title: rollback +--- +import { Aside, Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Introduction +Execution Metadata + +### Behaviour + +End the execution of the hook with status: reject. + +* Record a return string and return code in transaction metadata. +* Discard all state changes. +* Discard all `emit()` transactions. +* Disallow originating transaction to continue. + + + +### Definition + + + +```c +int64_t rollback ( + uint32_t read_ptr, + uint32_t read_len, + uint64_t error_code +); +``` + + +```javascript +function rollback(error_msg: string, error_code: number): number +``` + + + +### Example + + + +```c +rollback("Rejected!", 9, 100); +``` + + +```javascript +rollback('Rejected!', 100) +``` + + + +### Parameters + + + + +
NameTypeDescription
read_ptruint32_tPointer to a return string to be stored in execution metadata.
This is any string the hook-developer wishes to return with the acceptance. May be null.
read_lenuint32_tThe length of the return string. At most 32. May be null.
error_codeuint64_tA return code specific to this hook to be stored in execution metadata.

Similar to the return code of an application on a *nix system. By convention non-success is non-zero.
+
+ + +
NameTypeDescription
error_msgstringString to be stored in execution metadata.
This is any string the hook-developer wishes to return with the acceptance. May be null.
error_codenumberA return code specific to this hook to be stored in execution metadata.

Similar to the return code of an application on a *nix system. By convention non-success is non-zero.
+
+
+ +### Return Code + + + +
TypeDescription
int64_tRollback ends the hook, therefore no value is returned to the caller. By convention all Hook APIs return int64_t, but in this case nothing is returned.
+
+ +
TypeDescription
numberRollback ends the hook, therefore no value is returned to the caller. By convention all Hook APIs return number, but in this case nothing is returned.
+
+
diff --git a/src/content/docs/docs/hooks/functions/developer-defined/cbak-callback.mdx b/src/content/docs/docs/hooks/functions/developer-defined/cbak-callback.mdx new file mode 100644 index 0000000..72ee204 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/developer-defined/cbak-callback.mdx @@ -0,0 +1,91 @@ +--- +title: cbak / Callback +description: The callback function of your hook +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Compiling Hooks + +### Behaviour + +* `cbak` is a user defined function called by `xahaud` in order to inform your hook about the status of a previously emitted transaction +* State changes and further emit calls can be made from cbak but it cannot `rollback` a transaction. +* When cbak is executed the emitted transaction to which the callback relates is now the originating transaction. + +### Definition + + + +```c +int64_t cbak ( + uint32_t what +) +``` + + + +```javascript +type Callback = (reserved: number) => number +``` + + + +### Example + + + + + +```c +int64_t cbak(uint32_t reserved) +{ + return 0; +} +``` + + + + + +```javascript +const Callback = (reserved: number) => { + return 0 +} +``` + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| reserved | uint32_t |

if 0:
- the emittted transaction to which this callback relates was successfully accepted into a ledger.

If 1
- the emitted transaction to which the callback relates was NOT successfully accepted into a ledger before it expired.

| +
+ + +| Name | Type | Description | +| -------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| reserved | number |

if 0:
- the emittted transaction to which this callback relates was successfully accepted into a ledger.

If 1
- the emitted transaction to which the callback relates was NOT successfully accepted into a ledger before it expired.

| +
+
+ +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------- | +| int64_t | An arbitrary return code you wish to return from your hook. This will be present in the metadata of the originating transaction. | + + + +| Type | Description | +| ------ | -------------------------------------------------------------------------------------------------------------------------------- | +| number | An arbitrary return code you wish to return from your hook. This will be present in the metadata of the originating transaction. | + + + diff --git a/src/content/docs/docs/hooks/functions/developer-defined/hook.mdx b/src/content/docs/docs/hooks/functions/developer-defined/hook.mdx new file mode 100644 index 0000000..ab031e3 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/developer-defined/hook.mdx @@ -0,0 +1,95 @@ +--- +title: hook +description: The main function of your hook +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Compiling Hooks + +### Behaviour + +* `hook` is a user defined function called by `xahaud` in order to fire your hook. +* Your `hook` function calls either `accept` or `reject` to pass or reject the originating transaction. +* If execution reaches the end of the function it is implicitly an `accept`. + +### Definition + + + +```c +int64_t hook ( + uint32_t reserved +) +``` + + + + + +```javascript +type Hook = (reserved: number) => number +``` + + + + + + + +### Example + + + +```c +int64_t hook(uint32_t reserved) +{ + return 0; +} +``` + + + + + +```javascript +const Hook = (reserved: number) => { + return 0 +} +``` + + + +### Parameters + + + +
NameTypeDescription
reserveduint32_tReserved for future use.
+ + +
+ + +
NameTypeDescription
reservednumberReserved for future use.
+
+
+ +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------- | +| int64_t | An arbitrary return code you wish to return from your hook. This will be present in the metadata of the originating transaction. | + + + + + +| Type | Description | +| ------ | -------------------------------------------------------------------------------------------------------------------------------- | +| number | An arbitrary return code you wish to return from your hook. This will be present in the metadata of the originating transaction. | + + + diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/emit-1.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/emit-1.mdx new file mode 100644 index 0000000..9db8215 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/emit-1.mdx @@ -0,0 +1,111 @@ +--- +title: emit +description: Emit a new transaction from the hook +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Emitted Transactions + +### Behaviour + + + +* Read a transaction from `read_ptr` +* Validate the transaction against the emission rules +* Emit the transaction into consensus when valid +* Write canonical transaction hash to `write_ptr` + + + +* This function emits the provided transaction JSON. +* On success, it returns the number of emitted transaction hashes. +* If there is an error, it returns an error code. + + + +### Definition + + + +```c +int64_t emit ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len +); +``` + + + + + +```javascript +function emit( + txJson: Record | Transaction + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +if (emit(tx, tx_len) < 0) + rollback("Failed to emit!", 15, 1); +``` + + + + + +```javascript +const emitResult = emit(txJson) +if(typeof emitResult === 'number') + rollback("Failed to emit!", 1) +``` + + + + + +### Parameters + + + +
NameTypeDescription
write_ptruint32_tPointer to a buffer to write the transaction hash to
write_lenuint32_tThe size of the buffer to write the transaction hash to (should be 32.)
read_ptruint32_tPointer to the transaction to emit
read_lenuint32_tThe length of the transaction
+ + +
+ + + + +
NameTypeDescription
txJsonRecord<string, any> | TransactionThe TX JSON to emit.
+
+
+ + + +### Return Code + + + +
TypeDescription
int64_tOn success, the number of bytes of transaction hash written (32), or:

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

PREREQUISITE_NOT_MET
- emit_reserve must be called first

TOO_MANY_EMITTED_TXN
- the number of emitted transactions is now greater than the promise made when emit_reserve was called earlier

EMISSION_FAILURE
- the transaction was malformed according to the emission rules.
+ + +
+ + + + +
TypeDescription
ErrorCode | ByteArrayReturns an ErrorCode if there is an error, or an array of emitted transaction hashes on success.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/emit.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/emit.mdx new file mode 100644 index 0000000..0ca6859 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/emit.mdx @@ -0,0 +1,71 @@ +--- +title: prepare +description: Prepares a JSON transaction for emission. +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Transactions + +### Behaviour + + + +* This function takes a transaction JSON object and prepares it for emission. +* The transaction must be complete except for the Account field, which should always be the Hook account. + + + +### Definition + + + +```javascript +function prepare( + txJson: Record | Transaction + ): ErrorCode | Record | Transaction +``` + + + + + +### Example + + + +```javascript +const prepared_txn = prepare({ + TransactionType: "Payment", + Destination: util_raddr(p1address_ns), + Amount: parseFloat(drops_sent)*2 + }) +``` + + + + + +### Parameters + + + + + +
NameTypeDescription
txJsonRecord<string, any> | TransactionThe transaction JSON, must be a complete transaction except for Account (always the Hook account).
+
+
+ + + +### Return Code + + + + + +
TypeDescription
ErrorCode | Record<string, any> | TransactionReturns an ErrorCode if there is an error, or the prepared transaction JSON or Transaction object.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_burden.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_burden.mdx new file mode 100644 index 0000000..7c7fcdb --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_burden.mdx @@ -0,0 +1,70 @@ +--- +title: etxn_burden +description: Get the burden of a hypothetically emitted transaction +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Emitted Transactions + +### Behaviour + +* Return the burden an emitted transaction will carry. + +### Definition + + + +```c +int64_t etxn_burden ( + void +); +``` + + + +```javascript +function etxn_burden(): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t burden = etxn_burden(); +``` + + + + + +```javascript +const burden = etxn_burden() +``` + + + + + +### Parameters + +None + +### Return Code + + + +
TypeDescription
int64_tThe burden an emitted transaction will need in order to be successfully passed to emit()
+
+ + +
TypeDescription
numberAn ErrorCode if there is an error, or the current burden value on success.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_details.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_details.mdx new file mode 100644 index 0000000..2180d66 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_details.mdx @@ -0,0 +1,114 @@ +--- +title: etxn_details +description: Produce an sfEmitDetails suitable for a soon-to-be emitted transaction +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Emitted Transactions + +### Behaviour + + + +* Generate and write a 105 byte sfEmitDetails object into the `write_ptr` if cbak is not defined +* Generate and write a 127 byte sfEmitDetails object into the `write_ptr` if cbak is defined. + + + +* This function provides detailed information about the transaction. +* Returns an ErrorCode if there is an error, or an array of transaction details on success. + + + + + +### Definition + + + +```c +int64_t etxn_details ( + uint32_t write_ptr, + uint32_t write_len +); +``` + + + + + +```javascript +function etxn_details(): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t emitdet[105]; +int64_t result = + etxn_details(emitdet, 105); +if (result != 105) + rollback("Etxndetails failed.", 19, 1); +``` + + + + + +```javascript +const emitdet = etxn_details() +if (typeof emitdet === 'string || emitdet.length != 105) + rollback("Etxndetails failed.", 1) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | -------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to the buffer receiving the sfEmitDetails record | +| write_len | uint32_t | Length of the buffer | + + + + + +No parameters for JavaScript + + + + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- Buffer isn't large enough to receive record

PREREQUISITE_NOT_MET
- The hook failed to call etxn_reserve(n) first

FEE_TOO_LARGE
- The burden would be too high for the network to allow.

INTERNAL_ERROR
- A generic error in which rippled had trouble generating the required field.

| + + +
+ + + + +| Type | Description | +| ---------------------- | --------------------------------------------------------------------------------- | +| ErrorCode | ByteArray | An ErrorCode if there is an error, or an array of transaction details on success. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_fee_base.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_fee_base.mdx new file mode 100644 index 0000000..44ed4e8 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_fee_base.mdx @@ -0,0 +1,99 @@ +--- +title: etxn_fee_base +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + + + +### Concepts + +Emitted Transactions + +### Behaviour + +* Return the amount of the fee in drops recommended for a to-be emitted transaction. + +### Definition + + + +```c +int64_t etxn_fee_base ( + uint32_t read_ptr, + uint32_t read_len +); +``` + + + + + +```javascript +function etxn_fee_base(txblob: ByteArray | HexString): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t fee_to_pay = + etxn_fee_base(tx_blob, tx_blob_len); +``` + + + + + +```javascript +const fee_to_pay = etxn_fee_base(tx_blob) +``` + + + + + +### Parameters + + + +
NameTypeDescription
read_ptruint32_tPointer to the buffer containing the serialized transaction you intend to emit. The fee field is required but ignored (you may use zero). Use the output of this function to populate the fee field correctly.
read_lenuint32_tThe length of the tx blob.
+ + +
+ + + + +
NameTypeDescription
txblobByteArray | HexStringThe transaction blob, which can be an array of numbers or a string.
+
+
+ + + +### Return Code + + + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The smallest number of drops that an emitted txn would need to be accepted.

If negative, an error:
OUT_OF_BOUNDS
- The provided buffer is not validly within the hook memory.

PREREQUISITE_NOT_MET
- etxn_reserve has not been called first.

INVALID_TXN
- The provided buffer did not contain a valid serialized transaction. (Deserialization failed, or a required field was missing.)

| +
+ + + + +| Type | Description | +| ------ | ------------------------------------------------------------------------- | +| number | An ErrorCode if there is an error, or the calculated base fee on success. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_generation.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_generation.mdx new file mode 100644 index 0000000..5486c11 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_generation.mdx @@ -0,0 +1,79 @@ +--- +title: etxn_generation +description: Get the generation of a hypothetically emitted transaction +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Emitted Transactions + +### Behaviour + +* Return the generation an emitted transaction will carry. + +### Definition + + + +```c +int64_t etxn_generation ( + void +); +``` + + + + + +```javascript +function etxn_generation(): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t generation = + etxn_generation(); +``` + + + +```javascript +const generation = etxn_generation() +``` + + + + + +### Parameters + +None + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------- | +| int64_t | The generation an emitted transaction will need in order to be successfully passed to `emit()` | + + + + + + + +| Type | Description | +| ------ | --------------------------------------------------------------------------------------------------- | +| number | Returns An ErrorCode if there is an error, or a number indicating the generation result on success. | + + + diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_nonce.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_nonce.mdx new file mode 100644 index 0000000..5f58266 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_nonce.mdx @@ -0,0 +1,100 @@ +--- +title: etxn_nonce +description: Generate a 32 byte nonce for use in an emitted transaction +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Emitted Transactions + +### Behaviour + + + +* Write the 32 byte Hash to the write_ptr + + + +* Returns an ErrorCode if there is an error, or an array containing the nonce value on success. + + + + + +### Definition + + + +```c +int64_t etxn_nonce ( + uint32_t write_ptr, + uint32_t write_len +); +``` + + + + + +```javascript +function etxn_nonce(): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t n[32]; +int64_t bytes_written = + etxn_nonce(n, 32); +``` + + + + + +```javascript +const nonce = etxn_nonce() +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 32 bytes. | +| write_len | uint32_t | Length of the output buffer. | + + + +No parameters + + + + + +### Return Code + + + +
TypeDescription
int64_tThe number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.
+
+ + +
TypeDescription
ErrorCode | ByteArrayReturns an ErrorCode if there is an error, or an array containing the nonce value on success.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_reserve.mdx b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_reserve.mdx new file mode 100644 index 0000000..ea569ef --- /dev/null +++ b/src/content/docs/docs/hooks/functions/emitted-transaction/etxn_reserve.mdx @@ -0,0 +1,98 @@ +--- +title: etxn_reserve +description: Estimate the required fee for a txn to be emitted successfully +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Emitted Transactions + +### Behaviour + +* Specifies a number of emitted transactions this hook might emit during execution. + +### Definition + + + +```c +int64_t etxn_fee_base ( + uint32_t count +); +``` + + + + + +```javascript +function etxn_reserve(count: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +etxn_reserve(2); +``` + + + + + +```javascript +etxn_reserve(2) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ----- | --------- | ------------------------------------------------------------------------------------------- | +| count | uint32_t | The largest number of transactions this hook might emit during the course of one execution. | + + + + + + + +| Name | Type | Description | +| ----- | ------ | ---------------------------------------------------------------- | +| count | number | The maximum amount of transactions this Hook is allowed to emit. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The maximum number of emitted transactions this hook may emit. This will always be the same as the count parameter or an error as below.

If negative, an error:
ALREADY_SET
- The hook already called this function earlier.

TOO_BIG
- The specified number of emitted transactions is too large.

| + + +
+ + + + +| Type | Description | +| ------ | ---------------------------------------------------------------------------------- | +| number | An ErrorCode if there is an error, or the configured transaction count on success. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_compare.mdx b/src/content/docs/docs/hooks/functions/float/float_compare.mdx new file mode 100644 index 0000000..912545c --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_compare.mdx @@ -0,0 +1,128 @@ +--- +title: float_compare +description: Perform a comparison on two XFL floating point numbers +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Evaluate a comparison of two XFL floating point numbers +* Return the result of the comparison as a boolean encoded in an int64_t. + + + +* Evaluate a comparison of two XFL floating point numbers +* Returns an error code or the comparison result as a number. + + + + + +### Definition + + + +```c +int64_t float_compare ( + int64_t float1, + int64_t float2, + uint32_t mode +); +``` + + + +```javascript +function float_compare( + f1: bigint, + f2: bigint, + mode: number + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +if (float_compare(pusd_to_send, 0, COMPARE_LESS) == 1) +{ + // pusd_to_send is less than 0 +} +``` + + + + + +```javascript +if (float_compare(pusd_to_send, 0n, COMPARE_LESS) == 1) +{ + // pusd_to_send is less than 0 +} +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ------ | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| float1 | int64_t | An XFL floating point enclosing number representing the first operand to the comparison | +| float2 | int64_t | An XFL floating point enclosing number representing the second operand to the comparison | +| mode | uint32_t | A bit-flag field consisting of any of (or any logically valid combination of) the following flags:
COMPARE_LESS
COMPARE_EQUAL
COMPARE_GREATER

Valid combinations are:
COMPARE_LESS | COMPARE_GREATER
- Not equal

COMPARE_LESS | COMPARE_EQUAL
- Less than or equal to

COMPARE_GREATER | COMPARE_EQUAL
- Greater than or equal to | + + +
+ + + + +| Name | Type | Description | +| ---- | ------ | -------------------------------------------------------------- | +| f1 | bigint | The first float to compare. | +| f2 | bigint | The second float to compare. | +| mode | number | The comparison mode (e.g., less than, equal to, greater than). | + +
+ + + +### Return Code + + + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t | 0 if the comparison was logically false.
1 if the comparison was logically true.

If negative, an error:
INVALID_FLOAT
- one of the supplied parameters was not a valid XFL enclosing number

INVALID_ARGUMENT
- invalid combination of supplied comparison flags. | +
+ + + + +| Type | Description | +| ------------------- | ----------------------------------------------------------- | +| ErrorCode or number | Returns an error code or the comparison result as a number. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_divide.mdx b/src/content/docs/docs/hooks/functions/float/float_divide.mdx new file mode 100644 index 0000000..06e9ae7 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_divide.mdx @@ -0,0 +1,103 @@ +--- +title: float_divide +description: Divide an XFL by another XFL floating point number +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Divide an XFL by another XFL +* Return a new XFL as an int64_t + + + +* Divides one float representation by another. +* An error code or the quotient as a bigint. + + + + + +### Definition + + + +```c +int64_t float_divide ( + int64_t float1, + int64_t float2 +); +``` + + + +```javascript + function float_divide(f1: bigint, f2: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t still_one = + float_divide(float_one(), float_one()); +``` + + + +```javascript +const still_one = + float_divide(float_one(), float_one()) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------ | -------- | ------------------------------------------------------------ | +| float1 | int64_t | An XFL floating point enclosing number to act as numerator | +| float2 | int64_t | An XFL floating point enclosing number to act as denominator | + + + +| Name | Type | Description | +| ---- | ------ | ------------------- | +| f1 | bigint | The dividend float. | +| f2 | bigint | The divisor float. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- the supplied parameter was not a valid XFL enclosing number or the division resulted in an XFL that cannot be represented.

DIVISION_BY_ZERO
- the supplied parameter was zero.

| +
+ + +| Type | Description | +| ------------------- | ------------------------------------------ | +| bigint or ErrorCode | An error code or the quotient as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_exponent.mdx b/src/content/docs/docs/hooks/functions/float/float_exponent.mdx new file mode 100644 index 0000000..872595a --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_exponent.mdx @@ -0,0 +1,77 @@ +--- +title: float_exponent +description: Get the exponent of an XFL enclosing number +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + + + + + + + + + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Return the exponent part of an XFL as a signed integer + + + + + + + +### Definition + + + +Because exponents can be negative, and because negatives are reserved for error states, exponents cannot be returned from functions. Therefore this function has become a macro as shown below. + +```c +#define float_exponent(f)\ + (((int32_t)(((f) >> 54U) & 0xFFU)) - 97) +``` + + + +```javascript +const float_exponent = (f) => (Number(((f) >> 54n) & 0xFFn) - 97) +``` + + + + + +### Example + + + +```c +int64_t exponent = + float_exponent(float_one()); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number | + + + diff --git a/src/content/docs/docs/hooks/functions/float/float_int.mdx b/src/content/docs/docs/hooks/functions/float/float_int.mdx new file mode 100644 index 0000000..1a40437 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_int.mdx @@ -0,0 +1,117 @@ +--- +title: float_int +description: Convert an XFL floating point into an integer (floor) +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Left shift (multiply by 10) the XFL by the number of specified decimal places +* Convert the resulting XFL to an integer, discarding any remainder +* Return the integer + + + +* Converts a float representation to an integer with specified decimal places. +* An error code or the resulting integer as a number. + + + +### Definition + + + +```c +int64_t float_int ( + int64_t float1, + uint32_t decimal_places, + uint32_t absolute +); +``` + + + +```javascript +function float_int( + f1: bigint, + decimal_places: number, + abs: number + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t drops = + float_int(xahbalance, 6, 0); +``` + + + +```javascript +const drops = + float_int(xahbalance, 6, 0); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| --------------- | --------- | -------------------------------------------------------------------------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number representing the first operand to the addition | +| decimal_places | uint32_t | The number of places to shift the decimal to the right before computing the floor of the floating point. | +| absolute | uint32_t | If `1` also take the absolute of the value before returning it. | + + + + + + + +| Name | Type | Description | +| --------------- | ------ | --------------------------------------------- | +| f1 | bigint | The float to convert | +| decimal_places | number | The number of decimal places to consider. | +| abs | number | Indicates whether to take the absolute value. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The computed positive integer

If negative, an error:
INVALID_FLOAT
- one of the supplied parameters was not a valid XFL enclosing number

INVALID_ARGUMENT
- attempted to specify more than 15 decimal places.

CANT_RETURN_NEGATIVE
- attempted to return a negative integer but this is not allowed, use absolute = 1

| +
+ + + + +| Type | Description | +| ------------------- | ----------------------------------------------------------- | +| number or ErrorCode | Returns an error code or the resulting integer as a number. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_invert.mdx b/src/content/docs/docs/hooks/functions/float/float_invert.mdx new file mode 100644 index 0000000..4b8f61e --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_invert.mdx @@ -0,0 +1,102 @@ +--- +title: float_invert +description: Divide one by an XFL floating point number +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Inverts a float representation. +* Return a inverted float as a bigint or an ErrorCode + + + +* Divide `1` by an XFL +* Return a new XFL as an int64_t + + + + + +### Definition + + + +```c +int64_t float_invert ( + int64_t float1 +); +``` + + + + + +```javascript +function float_invert(f1: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t still_one = + float_invert(float_one()); +``` + + + +```javascript +const still_one = + float_invert(float_one()) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number | + + + +| Name | Type | Description | +| ---- | ----- | ------------------- | +| f1 | float | The float to invert | + + + + + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- the supplied parameter was not a valid XFL enclosing number or the division resulted in an XFL that cannot be represented.

DIVISION_BY_ZERO
- the supplied parameter was zero.

| +
+ + +| Type | Description | +| ------------------- | ------------------------------------------------ | +| ErrorCode \| bigint | An error code or the inverted float as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_log.mdx b/src/content/docs/docs/hooks/functions/float/float_log.mdx new file mode 100644 index 0000000..35b47dd --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_log.mdx @@ -0,0 +1,112 @@ +--- +title: float_log +description: Compute the decimal log of an XFL +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Compute a the decimal logarithm of an XFL number +* Return the new XFL + + + + + +* Calculates the logarithm of a float representation. +* Returns an error code or the logarithm as a bigint. + + + + + + + +### Definition + + + +```c +int64_t float_log ( + int64_t float1 +); +``` + + + +```javascript +function float_log(f1: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t zero = + float_log(float_one()); +``` + + + + + +```javascript +const zero = + float_log(float_one()) +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ------ | -------- | ------------------------------------------------------------------------------------------------------ | +| float1 | int64_t | An XFL floating point enclosing number representing the floating point number to take the logarithm of | + + + + + +| Name | Type | Description | +| ---- | ------ | ---------------------------------------- | +| f1 | bigint | The float to calculate the logarithm of. | + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The computed logarithm

If negative, an error:
INVALID_FLOAT
- the supplied parameter was not a valid XFL enclosing number

COMPLEX_NOT_SUPPORTED
- the supplied parameter was a negative number which would result in a complex return value.

| +
+ + +| Type | Description | +| ------------------- | --------------------------------------------------- | +| bigint or ErrorCode | Returns an error code or the logarithm as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_mantissa.mdx b/src/content/docs/docs/hooks/functions/float/float_mantissa.mdx new file mode 100644 index 0000000..ebd392c --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_mantissa.mdx @@ -0,0 +1,103 @@ +--- +title: float_mantissa +description: Get the mantissa of an XFL enclosing number +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Return the mantissa part of an XFL as an unsigned integer + + + +* Retrieves the mantissa of a float representation. +* An error code or the mantissa as a bigint. + + + + + +### Definition + + + +```c +int64_t float_mantissa ( + int64_t float1 +); +``` + + + +```javascript +function float_mantissa(f1: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t mantissa = + float_mantissa(float_one()); +``` + + + + + +```javascript +const mantissa = + float_mantissa(float_one()); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---- | ------ | ---------------------------------------- | +| f1 | bigint | The float to retrieve the mantissa from. | + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The mantissa of the XFL

If negative, an error:
INVALID_FLOAT
- the supplied parameter was not a valid XFL enclosing number

| +
+ + +| Type | Description | +| ------------------- | ------------------------------------------ | +| bigint or ErrorCode | An error code or the mantissa as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_mulratio.mdx b/src/content/docs/docs/hooks/functions/float/float_mulratio.mdx new file mode 100644 index 0000000..215ff4a --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_mulratio.mdx @@ -0,0 +1,124 @@ +--- +title: float_mulratio +description: Multiply an XFL floating point by a non-XFL numerator and denominator +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Compute the multiplication of an XFL (xls17) floating point number and the quotient of two integers +* Return a new XFL as an int64_t + + + +* Multiplies a float by a ratio defined by a numerator and denominator. +* Returns an error code or new XFL as a bigint. + + + +### Definition + + + +```c +int64_t float_mulratio ( + int64_t float1, + uint32_t round_up, + uint32_t numerator, + uint32_t denominator +); +``` + + + +```javascript +function float_mulratio( + f1: bigint, + round_up: number, + numerator: number, + denominator: number + ): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t max_vault_pusd = + float_mulratio(max_vault_pusd, 0, + COLLATERALIZATION_NUMERATOR, COLLATERALIZATION_DENOMINATOR); +``` + + + +```javascript +const max_vault_pusd = + float_mulratio(max_vault_pusd, 0, + COLLATERALIZATION_NUMERATOR, COLLATERALIZATION_DENOMINATOR); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ----------- | --------- | ------------------------------------------------------------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number representing the first operand to the multiplication | +| round_up | uint32_t | If non-zero all computations will be rounded up | +| numerator | uint32_t | The numerator of the quotient that the float will be multiplied by | +| denominator | uint32_t | The denominator of the quotient that the float will be multiplied by | + + + + + + + +| Name | Type | Description | +| ----------- | ------ | ------------------------------------------------------------------------------------------- | +| f1 | bigint | An XFL floating point enclosing number representing the first operand to the multiplication | +| round_up | number | If non-zero all computations will be rounded up | +| numerator | number | The numerator of the quotient that the float will be multiplied by | +| denominator | number | The denominator of the quotient that the float will be multiplied by | + + + + + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- one of the supplied parameters was not a valid XFL enclosing number

OVERFLOW
- the result of the multiplication was too large to store in an XFL.

DIVISION_BY_ZERO
- the supplied denominator was zero.

| + + +
+ + + + +| Type | Description | +| ------------------- | ----------------------------------------------------------- | +| ErrorCode or bigint | Returns an error code or tThe XFL (xls17) enclosing number. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_multiply.mdx b/src/content/docs/docs/hooks/functions/float/float_multiply.mdx new file mode 100644 index 0000000..7599f89 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_multiply.mdx @@ -0,0 +1,117 @@ +--- +title: float_multiply +description: Multiply two XFL numbers together +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Compute the multiplication of two XFL (xls17) floating point numbers +* Return a new XFL as an int64_t + + + +* Compute the multiplication of two XFL (xls17) floating point numbers +* Return n error code or new XFL as a bigint. + + + + + +### Definition + + + +```c +int64_t float_multiply ( + int64_t float1, + int64_t float2 +); +``` + + + + + +```javascript +function float_multiply(f1: bigint, f2: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t max_vault_pusd = + float_multiply(vault_xrp, exchange_rate); +``` + + + + + +```javascript +const max_vault_pusd = + float_multiply(vault_xrp, exchange_rate) +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------------------------------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number representing the first operand to the multiplication | +| float2 | int64_t | An XFL floating point enclosing number representing the second operand to the multiplication | + + + + + +| Name | Type | Description | +| ---- | ------ | -------------------------------------------------------------------------------------------- | +| f1 | bigint | An XFL floating point enclosing number representing the first operand to the multiplication | +| f2 | bigint | An XFL floating point enclosing number representing the second operand to the multiplication | + + + + + +### Return Code + + + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- one of the supplied parameters was not a valid XFL enclosing number

OVERFLOW
- the result of the multiplication was too large to store in an XFL.

| +
+ + + + +| Type | Description | +| ------------------ | ------------------------------------------------- | +| Errorcor or bigint | An error code or The XFL (xls17) enclosing number | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_negate.mdx b/src/content/docs/docs/hooks/functions/float/float_negate.mdx new file mode 100644 index 0000000..c9173ea --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_negate.mdx @@ -0,0 +1,110 @@ +--- +title: float_negate +description: Negate an XFL floating point number +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Multiply an XFL by `-1` +* Return a new XFL as an int64_t + + + +* Negates a float representation. +* Returns an error code or the negated float as a bigint. + + + +### Definition + + + +```c +int64_t float_negate ( + int64_t float1 +); +``` + + + + + +```javascript +function float_negate(f1: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t negative_one = + float_negate(float_one()); +``` + + + + + +```javascript +const negative_one = + float_negate(float_one()); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number | + + + + + + + +| Name | Type | Description | +| ---- | ------ | -------------------- | +| f1 | bigint | The float to negate. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- one of the supplied parameters was not a valid XFL enclosing number

| + + +
+ + +| Type | Description | +| ------------------- | -------------------------------------------------- | +| ErrorCode or bigint | An error code or The XFL (xls17) enclosing number. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_one.mdx b/src/content/docs/docs/hooks/functions/float/float_one.mdx new file mode 100644 index 0000000..7851a32 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_one.mdx @@ -0,0 +1,83 @@ +--- +title: float_one +description: Return the number 1 represented in an XFL enclosing number +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Return one(`1`) as an XFL int64_t + + + +* Retrieves the float representation of a number. + + + + + +### Definition + + + +```c +int64_t float_one(); +``` + + + +```javascript +function float_one(): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t one = + float_one(); +``` + + + + + +```javascript +const one = float_one() +``` + + + + + +### Parameters + +This function has no parameters. + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------- | +| int64_t | The XFL (xls17) enclosing number | + + + +| Type | Description | +| ------------------- | -------------------------------- | +| ErrorCode \| bigint | The XFL (xls17) enclosing number | + + + diff --git a/src/content/docs/docs/hooks/functions/float/float_root.mdx b/src/content/docs/docs/hooks/functions/float/float_root.mdx new file mode 100644 index 0000000..12311f0 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_root.mdx @@ -0,0 +1,117 @@ +--- +title: float_root +description: Compute the nth root of an XFL +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Compute a the `nth` root of an XFL number +* Return the new XFL + + + + + +* Calculates the nth root of a float representation. +* An error code or the resulting root as a bigint. + + + + + +### Definition + + + +```c +int64_t float_root ( + int64_t float1, + uint32_t n +); +``` + + + + + +```javascript +function float_root(f1: bigint, n: number): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t three = + float_root(nine, 2); +``` + + + + + +```javascript +const three = + float_root(nine, 2) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------ | --------- | -------------------------------------------------------------------------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number representing the floating point number to take the square root of | +| n | uint32_t | The root to compute, for example `2` is a square root. | + + + +| Name | Type | Description | +| ---- | ------ | ------------------------------------ | +| f1 | bigint | The float to calculate the root of. | +| n | number | The degree of the root to calculate. | + + + + + +### Return Code + + + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The computed nth root

If negative, an error:
INVALID_FLOAT
- the supplied parameter was not a valid XFL enclosing number

COMPLEX_NOT_SUPPORTED
- the supplied parameter was a negative number which would result in a complex root.

| +
+ + + + +| Type | Description | +| ------------------- | -------------------------------------------------------- | +| bigint or ErrorCode | Returns an error code or the resulting root as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_set.mdx b/src/content/docs/docs/hooks/functions/float/float_set.mdx new file mode 100644 index 0000000..1593e31 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_set.mdx @@ -0,0 +1,120 @@ +--- +title: float_set +description: Create a float from an exponent and mantissa +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Compute an XFL (xls17) floating point from the provided exponent and mantissa +* Return that XFL as an int64_t + + + +* Sets the exponent and mantissa for a float representation. +* Returns an error code or a new XFL as a bigint. + + + + + +### Definition + + + +```c +int64_t float_set ( + int32_t exponent, + int64_t mantissa +); +``` + + + + + +```javascript +function float_set(exponent: number, mantissa: number): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t small_amount = + float_set(-81, 1); +``` + + + + + +```javascript +const small_amount = float_set(-81, 1); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | -------- | --------------------------------------------------------------- | +| exponent | int32_t | An exponent in the range `-96` to `80` | +| mantissa | int64_t | A mantissa. If negative then the sign of the float is negative. | + + + + + + + + + +| Name | Type | Description | +| -------- | ------ | --------------------------------------------------------------- | +| exponent | bigint | An exponent in the range `-96` to `80` | +| mantissa | bigint | A mantissa. If negative then the sign of the float is negative. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- The adjustment of the mantissa to 16 digits produced an under or overflow.

| + + +
+ + + + +| Type | Description | +| ------------------- | -------------------------------------------------- | +| ErrorCode \| bigint | An error code or the XFL (xls17) enclosing number. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_sign.mdx b/src/content/docs/docs/hooks/functions/float/float_sign.mdx new file mode 100644 index 0000000..3e19503 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_sign.mdx @@ -0,0 +1,102 @@ +--- +title: float_sign +description: Get the sign of an XFL enclosing number +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Return `1` if the XFL is negative, otherwise return 0 + + + +* Return 1 if the XFL is negative, otherwise return 0 + + + +### Definition + + + +```c +int64_t float_sign ( + int64_t float1 +); +``` + + + +```javascript +function float_sign(f1: bigint): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t sign = + float_sign(float_one()); +``` + + + + + +```javascript +const sign = + float_sign(float_one()); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number | + + + +| Name | Type | Description | +| ---- | ------ | ---------------------------------------- | +| f1 | bigint | The float to retrieve the mantissa from. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The sign of the XFL:
0 if positive, 1 if negative.

If negative, an error:
INVALID_FLOAT
- the supplied parameter was not a valid XFL enclosing number

| + + +
+ + +| Type | Description | +| ------------------- | ------------------------------------------ | +| bigint or ErrorCode | An error code or the mantissa as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_sto.mdx b/src/content/docs/docs/hooks/functions/float/float_sto.mdx new file mode 100644 index 0000000..b5cf1a8 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_sto.mdx @@ -0,0 +1,139 @@ +--- +title: float_sto +description: Output an XFL as a serialized object +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) +Serialized Objects + +### Behaviour + + + +* Read an XFL floating point number and optionally a field code and currency code +* Write a serialized amount to `write_ptr` according to the parameters provided + + + +* Stores a float representation into a specified field. +* Returns an error code or the updated value as an array of numbers. + + + +### Definition + + + +```c +int64_t float_sto ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t cread_ptr, + uint32_t cread_len, + uint32_t iread_ptr, + uint32_t iread_len, + int64_t float1, + uint32_t field_code +); +``` + + + + + +```javascript +function float_sto( + currency: ByteArray | HexString | undefined, + issuer: ByteArray | HexString | undefined, + f1: bigint, + field_code: number + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +uint8_t amt_out[48]; +if (float_sto(SBUF(amt_out), + SBUF(currency), SBUF(hook_accid), pusd_to_send, -1) < 0) + rollback(SBUF("Peggy: Could not dump pusd amount into sto"), 1); +``` + + + + + +```javascript +const amt_out = float_sto(currency, hook_accid, pusd_to_send, -1) +if (typeof amt_out === 'number') + rollback("Peggy: Could not dump pusd amount into sto", 1) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the serialized amount field. Recommend at least 48 bytes. | +| write_len | uint32_t | The length of the output buffer. | +| cread_ptr | uint32_t | Pointer to a buffer contianing the currency code to serialize into the output. _May be null._ | +| cread_len | uint32_t | The length of the currency code. This must be 20 or 3 or 0 (null). | +| iread_ptr | uint32_t | Pointer to a buffer containing the issuer's Account ID to serialize into the output. _May be null._ | +| iread_len | uint32_t | The length of the issuer's Account ID. This must be either 20 or 0 (null). | +| float1 | int64_t | An XFL floating point enclosing number to serialize. | +| field_code | uint32_t |

The sf field code to prefix the serialized amount with. E.g. sfAmount.
If this field is 0xFFFFFFFFU (i.e. (uint32_t)(-1)) then no field code is prepended to the output, and no issuer or currency code is appended, but serialization proceeds as a floating point amount.
If this field is 0 no field code is prepended to the output, and no issuer or currency code is appended, but serialization proceeds as though the amount is an XRP native amount rather than a floating point.

| + + +
+ + + + +| Name | Type | Description | +| ----------- | ----------------------------------- | ---------------------------------------------------------- | +| currency | ByteArray \| HexString \| undefined | The current value to store into. | +| issuer | ByteArray \| HexString \| undefined | The value to store. | +| f1 | bigint | The field code indicating where to store the float. | +| field_code | number | An error code or the updated value as an array of numbers. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written to the output buffer.

If negative, an error:
INVALID_FLOAT
- the supplied float was not a valid XFL enclosing number

OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

INVALID_ARGUMENT
- If instructed to output as XRP or without field code then all non-write pointers and lengths should be 0 (null).

TOO_SMALL
- The output buffer was too small to receive the serialized object.

XFL_OVERFLOW
- Expressing the output caused an overflow during normalization.

| + + +
+ + + + +| Type | Description | +| ---------------------- | ------------------------------------------------------------------ | +| ErrorCode \| ByteArray | Returns an error code or the updated value as an array of numbers. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_sto_set.mdx b/src/content/docs/docs/hooks/functions/float/float_sto_set.mdx new file mode 100644 index 0000000..79cfd20 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_sto_set.mdx @@ -0,0 +1,110 @@ +--- +title: float_sto_set +description: Read a serialized amount into an XFL +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) +Serialized Objects + +### Behaviour + + + +* Read a serialized floating point number. +* If there are more fields/data after the serialized floating pointer number then ignore them. +* Return it as an XFL enclosing number + + + +* Sets the buffer for storing float representations. +* Returns ErrorCode or the result as a number. + + + + + +### Definition + + + +```c +int64_t float_sto_set ( + uint32_t read_ptr, + uint32_t read_len +); +``` + + + +```javascript +function float_sto_set(buf: ByteArray | HexString): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t vault_pusd = float_sto_set(vault, 8); +if (vault_pusd < 0) + rollback("Failed to parse serialized float.", 33, 1); +``` + + + + + +```javascript +const vault_pusd = float_sto_set(vault) +if (typeof vault_pusd === 'string') + rollback("Failed to parse serialized float.", 1) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| --------- | --------- | ----------------------------------------------------------------- | +| read_ptr | uint32_t | Pointer to a buffer contianing the serialized XFL. _May be null._ | +| read_len | uint32_t | The length of the buffer. | + + + + + +| Name | Type | Description | +| ---- | ---------------------- | ------------------ | +| buf | ByteArray \| HexString | The buffer to set. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes written to the output buffer.

If negative, an error:
NOT_AN_OBJECT
- the supplied buffer did not contain a valid serialized floating point number

OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| +
+ + +| Type | Description | +| ------------------- | ---------------------------------------- | +| ErrorCode or number | An error code or the result as a number. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/float/float_sum.mdx b/src/content/docs/docs/hooks/functions/float/float_sum.mdx new file mode 100644 index 0000000..f2879f9 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/float/float_sum.mdx @@ -0,0 +1,113 @@ +--- +title: float_sum +description: Add two XFL numbers together +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Floating Point Numbers (XFL) + +### Behaviour + + + +* Compute the addition of two XFL (xls17) floating point numbers +* Return a new XFL as an int64_t + + + +* Sums two float representations. +* Returns an error code or the sum as a bigint. + + + +### Definition + + + +```c +int64_t float_sum ( + int64_t float1, + int64_t float2 +); +``` + + + + + +```javascript +function float_sum(f1: bigint, f2: bigint): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t two = + float_sum(float_one(), float_one()); +``` + + + + + +```javascript +const two = + float_sum(float_one(), float_one()); +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ------ | -------- | -------------------------------------------------------------------------------------- | +| float1 | int64_t | An XFL floating point enclosing number representing the first operand to the addition | +| float2 | int64_t | An XFL floating point enclosing number representing the second operand to the addition | + + + + + + + +| Name | Type | Description | +| ---- | ------ | ------------------------ | +| f1 | bigint | The first float to sum. | +| f2 | bigint | The second float to sum. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The XFL (xls17) enclosing number

If negative, an error:
INVALID_FLOAT
- one of the supplied parameters was not a valid XFL enclosing number

OVERFLOW
- the result of the addition was too large to store in an XFL.

| +
+ + +| Type | Description | +| ------------------- | ------------------------------------- | +| ErrorCode or bigint | An error code or the sum as a bigint. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_account.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_account.mdx new file mode 100644 index 0000000..d361672 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_account.mdx @@ -0,0 +1,94 @@ +--- +title: hook_account +description: Retreive the 20 byte Account ID the Hook is executing on +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Write the 20 byte Account ID to the write_ptr + + + +* Retrieve the 20 byte Account ID the Hook is executing on. + + + +### Definition + + + +```c +int64_t hook_account ( + uint32_t write_ptr, + uint32_t write_len +); +``` + + + +``JavaScript +function hook_account(): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t hook_acc_id[20]; +int64_t bytes_written = + hook_account(hook_acc_id, 20); +``` + + + + + +```javascript +const hook_acc_id =hook_account() +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 20 bytes. | +| write_len | uint32_t | Length of the output buffer. | + + + +No parameters + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| +
+ + +| Type | Description | +| ---------------------- | ----------------------------------------------------------------------------------------- | +| ErrorCode or ByteArray | Returns the Account ID the Hook is executing on, or an error code if the retrieval fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_again.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_again.mdx new file mode 100644 index 0000000..19fbe23 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_again.mdx @@ -0,0 +1,57 @@ +--- +title: hook_again +description: Returns the position in the hook chain the currently executing hook occupies +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* If the hook is being strongly executed then flag this specific hook in the chain for [Again As Weak Execution](../../../concepts/weak-and-strong.md). +* If the originating transaction successfully is applied then the hook will be called again in a second, Weak Execution. + +### Definition + + + +```c +int64_t hook_again(void); +``` + + +```javascript +function hook_again(): ErrorCode | number +``` + + + +### Example + + + +```c +int64_t result = + hook_again(); +``` + + +```javascript +const result = hook_again() +``` + + + +### Parameters + +This API has no parameters + +### Return Code + + + +
TypeDescription
int64_t1 iff successfully flagged for Again As Weak.

PREREQUISITE_NOT_MET
- This hook is already being executed weakly at the time of the call.

ALREADY_SET
- The function was already called this execution.
+
+ +
TypeDescription
numberReturns a status code indicating the result of the operation.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_hash.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_hash.mdx new file mode 100644 index 0000000..ae06336 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_hash.mdx @@ -0,0 +1,91 @@ +--- +title: hook_hash +description: Retreive the 32 byte namespace biased SHA512H of the currently executing Hook +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Look up the hash of the hook installed on hook account at position `hook_no` +* Write the 32 byte hash to `write_ptr` + + +* Look up the hash of the hook installed on the hook account at the specified position. +* The Namespace biased SHA512H of the currently executing Hook, or an error code if the lookup fails. + + + + + +### Definition + + + +```c +int64_t hook_hash ( + uint32_t write_ptr, + uint32_t write_len, + int32_t hook_no +); +``` + + +```javascript +function hook_hash(hookno: number): ErrorCode | ByteArray +``` + + + +### Example + + + +```c +uint8_t hash[32]; +int64_t bytes_written = + hook_hash(hash, 32, -1); +``` + + +```javascript +const hash = hook_hash(hookno) +``` + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 32 bytes. | +| write_len | uint32_t | Length of the output buffer. | +| hook_no | int32_t | The position in the hook chain the hook is located at, or -1 for the currently executing hook. | + + +| Name | Type | Description | +| -------- | ------ | ---------------------------------------------------------------------------------------------- | +| hook_no | number | The position in the hook chain the hook is located at, or -1 for the currently executing hook. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

DOESNT_EXIST
- The specified hook sequence number doesn't exist in the hook chain.

| +
+ +| Type | Description | +| ---------------------- | ----------------------------------------------------------------------------------------------------------- | +| ByteArray or ErrorCode | Returns the Namespace biased SHA512H of the currently executing Hook, or an error code if the lookup fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_param.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_param.mdx new file mode 100644 index 0000000..5f51e0f --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_param.mdx @@ -0,0 +1,110 @@ +--- +title: hook_param +description: Retrieve the parameter value for a named hook parameter +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Look up the value for a named parameter specified in `read_ptr` +* Write the parameter's value to `write_ptr` + + + +* Retrieve the value of a parameter associated with the specified key. +* Returns the value associated with the key, or an error code if the retrieval fails. + + + +### Definition + + + +```c +int64_t hook_param ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len +); +``` + + + +```javascript +function hook_param(key: ByteArray | HexString): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t pname[] = {0xCAU, 0xFEU}; +uint8_t pvalue[32]; +int64_t value_len = + hook_param(pvalue, 32, pname, 2); +``` + + + +```javascript +const pname = [0xCA, 0xFE] +const pvalue = hook_param(pname) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 32 bytes. | +| write_len | uint32_t | Length of the output buffer. | +| read_ptr | uint32_t | Pointer to a buffer containing the parameter's name | +| read_len | uint32_t | Length of the parameter's name | + + + + + + + +| Name | Type | Description | +| ---- | ---------------------- | -------------------------------------------------- | +| key | ByteArray or HexString | The key for which to retrieve the parameter value. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

DOESNT_EXIST
- The specified paramater doesn't exist or is null

TOO_SMALL
- The parameter name can't be null

TOO_BIG
- The parameter name is greater than 32 bytes

| + + +
+ + + + +| Type | Description | +| ---------------------- | ----------------------------------------------------------------------------------- | +| ByteArray or ErrorCode | Returns the value associated with the key, or an error code if the retrieval fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_param_set.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_param_set.mdx new file mode 100644 index 0000000..5f20681 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_param_set.mdx @@ -0,0 +1,121 @@ +--- +title: hook_param_set +description: >- + Set or delete a parameter on a hook on the same account further down the + execution chain +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Search the hook chain on the hook account for a 32 byte hash indicated by `hread_ptr` +* If found: set a parameter: +* With the parameter name indicated by `kread_ptr` and +* The parameter value indicated by `read_ptr` + + + +* Set a parameter for the hook with the specified value and key, and associate it with a hash. +* Returns a status code indicating the result of the operation. + + + +### Definition + + + +```c +int64_t hook_param_set ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t kread_ptr, + uint32_t kread_len, + uint32_t hread_ptr, + uint32_t hread_len +); +``` + + +```javascript +function hook_param_set( + val: ByteArray | HexString, + key: ByteArray | HexString, + hash: ByteArray | HexString + ): number +``` + + + +### Example + + + +```c +uint8_t pvalue[] = "some parameter value"; +uint8_t pname[] = "paramname"; +uint8_t phash[] = { 0x19U, 0xFEU, 0x69U, 0xF1U, 0x53U, 0x66U, 0x4EU, 0x8CU, + 0x97U, 0xF4U, 0x4CU, 0x5CU, 0x3CU, 0x65U, 0x63U, 0x79U, + 0xC2U, 0xD0U, 0x26U, 0xE7U, 0x90U, 0xEFU, 0x38U, 0xF7U, + 0xEDU, 0x73U, 0xE9U, 0xCEU, 0x9CU, 0x9DU, 0xBFU, 0x03U }; +int64_t result = + hook_param_set(pvalue, sizeof(pvalue), + pname, sizeof(pname), + phash, sizeof(phash)); +``` + + +```javascript +const pvalue = "some parameter value" +const pname = "paramname" +const phash = [ 0x19, 0xFE, 0x69, 0xF1, 0x53, 0x66, 0x4E, 0x8C, + 0x97, 0xF4, 0x4C, 0x5C, 0x3C, 0x65, 0x63, 0x79, + 0xC2, 0xD0, 0x26, 0xE7, 0x90, 0xEF, 0x38, 0xF7, + 0xED, 0x73, 0xE9, 0xCE, 0x9C, 0x9D, 0xBF, 0x03 ] +const result = hook_param_set(str2hex(pvalue), str2hex(pname), phash) +``` + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ------------------------------- | +| read_ptr | uint32_t | Pointer to parameter value | +| read_len | uint32_t | Length of the parameter value | +| kread_ptr | uint32_t | Pointer to the parameter name | +| kread_len | uint32_t | Length of the parameter name | +| hread_ptr | uint32_t | Pointer to hook hash | +| hread_len | uint32_t | Length of hook hash (always 32) | + + + +| Name | Type | Description | +| ---- | ---------------------- | ----------------------------------------- | +| val | ByteArray or HexString | The value to set for the parameter. | +| key | ByteArray or HexString | The key associated with the parameter. | +| hash | ByteArray or HexString | The hash to associate with the parameter. | + + + + + +### Return Code + + + + + +
TypeDescription
int64_tThe length of the parameter value successfully set

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- The parameter name can't be null

TOO_BIG
- The parameter name is greater than 32 bytes
+
+ + + + +
TypeDescription
numberReturns a status code indicating the result of the operation.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_pos.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_pos.mdx new file mode 100644 index 0000000..a2e6cdc --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_pos.mdx @@ -0,0 +1,60 @@ +--- +title: hook_pos +description: Returns the position in the hook chain the currently executing hook occupies +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Returns the position in the hook chain the currently executing hook occupies. + +### Definition + + + +```c +int64_t hook_pos(void); +``` + + +```javascript +hook_pos() +``` + + + +### Example + + + +```c +int64_t pos = + hook_pos(); +``` + + +```javascript +const pos = hook_pos() +``` + + + +### Parameters + +This API has no parameters + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------- | +| int64_t | The position in the chain the currently executing hook occupies. The first position is 0. | + + +| Type | Description | +| ------ | ---------------------------------------------------------------------------------------- | +| number | Returns the current position in the hook chain, or an error code if the retrieval fails. | + + + diff --git a/src/content/docs/docs/hooks/functions/hook-context/hook_skip.mdx b/src/content/docs/docs/hooks/functions/hook-context/hook_skip.mdx new file mode 100644 index 0000000..ba19396 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/hook-context/hook_skip.mdx @@ -0,0 +1,101 @@ +--- +title: hook_skip +description: Skip a hook that appears later in the hook chain on the hook account +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Search the hook chain for a hook identified by the hook hash at `read_ptr` +* Mark it as disabled for this chain execution + + + +* Skip the execution of a hook based on the provided hash and flag. +* Returns a status code indicating the result of the operation. + + + +### Definition + + + +```c +int64_t hook_skip ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t flags +); +``` + + +```javascript +function hook_skip( + hash: ByteArray | HexString, + flag: number + ): ErrorCode | number +``` + + + +### Example + + + +```c +uint8_t phash[] = { 0x19U, 0xFEU, 0x69U, 0xF1U, 0x53U, 0x66U, 0x4EU, 0x8CU, + 0x97U, 0xF4U, 0x4CU, 0x5CU, 0x3CU, 0x65U, 0x63U, 0x79U, + 0xC2U, 0xD0U, 0x26U, 0xE7U, 0x90U, 0xEFU, 0x38U, 0xF7U, + 0xEDU, 0x73U, 0xE9U, 0xCEU, 0x9CU, 0x9DU, 0xBFU, 0x03U }; +int64_t result = + hook_skip(phash, 32, 0); +``` + + +```javascript +const phash = [ 0x19, 0xFE, 0x69, 0xF1, 0x53, 0x66, 0x4E, 0x8C, + 0x97, 0xF4, 0x4C, 0x5C, 0x3C, 0x65, 0x63, 0x79, + 0xC2, 0xD0, 0x26, 0xE7, 0x90, 0xEF, 0x38, 0xF7, + 0xED, 0x73, 0xE9, 0xCE, 0x9C, 0x9D, 0xBF, 0x03 ] +const result = hook_skip(phash, 0); +``` + + + +### Parameters + + + + + +| Name | Type | Description | +| --------- | --------- | ------------------------------------------------------------------------------------------------------------- | +| read_ptr | uint32_t | Pointer to a buffer containing the hook hash | +| read_len | uint32_t | Length of the hook hash (always 32) | +| flags | uint32_t |

If 0:
- add the hash to the hook skip list

If 1
- remove the hash from the hook skip list

| +
+ + + + +| Name | Type | Description | +| ---- | ---------------------- | --------------------------------------------------- | +| hash | ByteArray or HexString | The hash of the hook to skip. | +| flag | number | A flag indicating the reason for skipping the hook. | + +
+ +### Return Code + + + +
TypeDescription
int64_tIf successful 1

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

DOESNT_EXIST
- The specified paramater doesn't exist or is null

INVALID_ARGUMENT
- Hash is not 32 bytes
+
+ + +
TypeDescription
number or ErrorCodeReturns a status code indicating the result of the operation.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/ledger/fee_base.mdx b/src/content/docs/docs/hooks/functions/ledger/fee_base.mdx new file mode 100644 index 0000000..fe4b347 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/ledger/fee_base.mdx @@ -0,0 +1,73 @@ +--- +title: fee_base +description: Fetch the fee base of the current ledger +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Hook Fees + +### Behaviour + +* Return the fee base from the current ledger + +### Definition + + + +```c +int64_t fee_base(); +``` + + + +```javascript +function fee_base(): number +``` + + + + + +### Example + + + +```c +int64_t fee = + fee_base(); +``` + + + +```javascript +const fee = fee_base() +``` + + + + + +### Parameters + +This API takes no parameters. + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------- | +| int64_t | The fee base of the current ledger | + + + + + +| Type | Description | +| ------ | ---------------------------------- | +| number | The fee base of the current ledger | + + + diff --git a/src/content/docs/docs/hooks/functions/ledger/ledger_keylet.mdx b/src/content/docs/docs/hooks/functions/ledger/ledger_keylet.mdx new file mode 100644 index 0000000..211512d --- /dev/null +++ b/src/content/docs/docs/hooks/functions/ledger/ledger_keylet.mdx @@ -0,0 +1,124 @@ +--- +title: ledger_keylet +description: Search for a keylet within a specified range on the current ledger +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read a 34 byte Keylet from the `lread_ptr` +* Read a 32 byte Keylet from the `hread_ptr` +* Search the ledger for the first (lowest) Keylet of this type in this range. +* If any matching Keylet is found, write it to `write_ptr`. + + + +* This function searches the ledger for the first (`lowest`) Keylet of this type in the given range. +* Returns the number of bytes written (34 bytes) on success, or an error code if an error occurs. + + + + + +### Definition + +C + + + +```c +int64_t ledger_keylet ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t lread_ptr, + uint32_t lread_len, + uint32_t hread_ptr, + uint32_t hread_len +); +``` + + + + + +```javascript +function ledger_keylet( + low: ByteArray | HexString, + high: ByteArray | HexString + ): ErrorCode | ByteArray +``` + + + + + +### Example + +C + + + +```c +//TODO +``` + + + + + +```javascript +ledger_keylet(low, high) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer to store the output serialised Keylet. . | +| write_len | uint32_t | Length of the output buffer. Must be 34 bytes | +| lread_ptr | uint32_t | Pointer to the 34 byte serialised Keylet that represents the lower boundary of the Keylet range to search. | +| lread_len | uint32_t | Always 34 bytes | +| hread_ptr | uint32_t | Pointer to the 34 byte serialised Keylet that represents the upper boundary of the Keylet range to search. | +| hread_len | uint32_t | Always 34 bytes | + + + + + + + +| Name | Type | Description | +| ---- | ---------------------- | ---------------------------------------------------------------------------------------------------------- | +| low | ByteArray \| HexString | Pointer to the 34-byte serialized Keylet that represents the lower boundary of the Keylet range to search. | +| high | ByteArray \| HexString | Pointer to the 34-byte serialized Keylet that represents the upper boundary of the Keylet range to search. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written (34 bytes) on success.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL / TOO_BIG
- write_len, lread_len or hread_len was not 34 bytes

INVALID_ARGUMENT
- One or more of the provided Keylets was not a valid serialised Keylet

DOES_NOT_MATCH
- The two provided Keylets were not of the same Keylet Type.

DOESNT_EXIST
- No matching Keylet was found in the specified range.

| +
+ + + + +| Type | Description | +| ---------------------- | ----------------------------------------------------------------------------------------------- | +| ErrorCode \| ByteArray | Returns the number of bytes written (34 bytes) on success, or an error code if an error occurs. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/ledger/ledger_last_hash.mdx b/src/content/docs/docs/hooks/functions/ledger/ledger_last_hash.mdx new file mode 100644 index 0000000..3a23bb9 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/ledger/ledger_last_hash.mdx @@ -0,0 +1,98 @@ +--- +title: ledger_last_hash +description: Retreive the 32 byte namespace biased SHA512H of the last closed ledger +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Write the 32 byte Hash to the write_ptr + + + +* Retrieves the hash of the last ledger. + + + +### Definition + + + +```c +int64_t ledger_last_hash ( + uint32_t write_ptr, + uint32_t write_len +); +``` + + + + + +```javascript +function ledger_last_hash(): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t hash[32]; +int64_t bytes_written = + ledger_last_hash(hash, 32); +``` + + + +```javascript +const hash = ledger_last_hash() +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 32 bytes. | +| write_len | uint32_t | Length of the output buffer. | + + + + + + + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| + + +
+ + +| Type | Description | +| ------ | ----------------------------------------------------------------------------------------------- | +| number | Returns an error code if an error occurs, or an array representing the hash of the last ledger. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/ledger/ledger_last_time.mdx b/src/content/docs/docs/hooks/functions/ledger/ledger_last_time.mdx new file mode 100644 index 0000000..fbe7a23 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/ledger/ledger_last_time.mdx @@ -0,0 +1,79 @@ +--- +title: ledger_last_time +description: Fetch the last closed ledger's timestamp +--- +import { Aside, Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Return the Xahau Timestamp from the last closed ledger. + + + +### Definition + + + +```c +int64_t ledger_last_time(); +``` + + + + + +```javascript +function ledger_last_time(): ErrorCode | number +``` + + + +### Example + + + +```c +int64_t ts = + ledger_last_time(); +``` + + + + + +```javascript +const ts = ledger_last_time() +``` + + + + + +### Parameters + +This API takes no parameters. + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------- | +| int64_t | The XRPL timestamp of the last closed ledger | + + + + + + + +| Type | Description | +| ------ | ---------------------------------------------------------------------------------------------------- | +| number | Returns an error code if an error occurs, or a number representing the timestamp of the last ledger. | + + + diff --git a/src/content/docs/docs/hooks/functions/ledger/ledger_nonce.mdx b/src/content/docs/docs/hooks/functions/ledger/ledger_nonce.mdx new file mode 100644 index 0000000..8553a51 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/ledger/ledger_nonce.mdx @@ -0,0 +1,104 @@ +--- +title: ledger_nonce +description: Generate a 32 byte nonce for use in an emitted transaction +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Write a 32 byte random value to the write_ptr + + + +* Retrieves the nonce of the current ledger. + + + + + +### Definition + +C + + + +```c +int64_t ledger_nonce ( + uint32_t write_ptr, + uint32_t write_len +); +``` + + + + + +```javascript +function ledger_nonce(): ErrorCode | ByteArray +``` + + + +### Example + + + +```c +uint8_t n[32]; +int64_t bytes_written = + ledger_nonce(n, 32); +``` + + + + + +```javascript +const nonce = ledger_nonce() +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 32 bytes. | +| write_len | uint32_t | Length of the output buffer. | + + + + + + + + + + + +### Return Code + + + + + +| Type | Description | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| ErrorCode \| ByteArray | Returns an error code if an error occurs, or an array representing the nonce of the current ledger. specified outside of hook memory. | + + + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/ledger/ledger_seq.mdx b/src/content/docs/docs/hooks/functions/ledger/ledger_seq.mdx new file mode 100644 index 0000000..f1c6687 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/ledger/ledger_seq.mdx @@ -0,0 +1,73 @@ +--- +title: ledger_seq +description: Fetch the current ledger sequence number +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Return the sequence number from the current ledger + +### Definition + +C + + + +```c +int64_t ledger_seq(); +``` + + + +```javascript +function ledger_seq(): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t seq = + ledger_seq(); +``` + + + + + +```javascript +const seq = ledger_seq() +``` + + + + + +### Parameters + +This API takes no parameters. + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------- | +| int64_t | The sequence number of the current ledger | + + + + + +| Type | Description | +| ------ | ----------------------------------------- | +| number | The sequence number of the current ledger | + + + diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/meta_slot.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/meta_slot.mdx new file mode 100644 index 0000000..e795a33 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/meta_slot.mdx @@ -0,0 +1,83 @@ +--- +title: meta_slot +description: Load the metadata of the originating transaction into a slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* If the Hook is being [Weakly Executed](../../../concepts/weak-and-strong.md) then emplace the metadata of the originating transaction into the slot specified or into a new slot if no slot is specified + +### Definition + + + +```c +int64_t meta_slot ( + uint32_t slot_no +); +``` + + + +```javascript +function meta_slot(slotno: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t meta_slot_no = + meta_slot(0); +``` + + + +```javascript +const meta_slot_no = meta_slot(0) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | ----------------------------------------------------------------------------- | +| slot_no | uint32_t | The slot number to emplace into, or 0 if you wish to pick the next available. | + + + +| Name | Type | Description | +| ------ | ------ | ----------------------------------------- | +| slotno | number | The slot number to retrieve metadata for. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The slot the otxn was placed in

INVALID_ARGUMENT
- specified slot number exceeds the largest possible slot number

NO_FREE_SLOTS
- the request could not granted because no free slot was avaialble to place the originating transaction into.

PREREQUISITE_NOT_MET
- The hook is being Strongly Executed and therefore no transactional metadata is available.

| +
+ + +| Type | Description | +| ------------------- | --------------------------------------------- | +| ErrorCode \| number | Returns an error code or the slot's metadata. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_burden.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_burden.mdx new file mode 100644 index 0000000..fdde6db --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_burden.mdx @@ -0,0 +1,78 @@ +--- +title: otxn_burden +description: Get the burden of the originating transaction +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Return the burden of the originating transaction or `1` if no burden field is present. + + + +* Retrieve the burden of the originating transaction. +* Returns the burden as a number, or an ErrorCode if the retrieval fails. + + + +### Definition + + + +```c +int64_t otxn_burden ( + void +); +``` + + + +```javascript +function otxn_burden(): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t burden = + otxn_burden(); +``` + + + +```javascript +const burden = otxn_burden() +``` + + + + + +### Parameters + +None + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------- | +| int64_t | The burden of the originating transaction, or `1` if no burden was present on the originating transaction. | + + + +| Type | Description | +| ------------------- | ----------------------------------------------------------------------- | +| number or ErrorCode | Returns the burden as a number, or an ErrorCode if the retrieval fails. | + + + diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_field.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_field.mdx new file mode 100644 index 0000000..83829fb --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_field.mdx @@ -0,0 +1,103 @@ +--- +title: otxn_field +description: Serialize and output a field from the originating transaction +--- +import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Find the specified `sf` field in the originating transaction +* Write the serialized version of the field to the output buffer + + + +* Retrieve the value of a specific field in the originating transaction. +* Returns the value of the specified field as an array of numbers, or an ErrorCode if the lookup fails. + + + +### Definition + + + +```c +int64_t otxn_field ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t field_id +); +``` + + + +```javascript +function otxn_field(field_id: number): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +int64_t account_field_len = + otxn_field(account_field, 20, sfAccount); +``` + + + + + +```javascript +const account_field = otxn_field(sfAccount) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. | +| write_len | uint32_t | Length of the output buffer. | +| field_id | uint32_t |

The sf code of the field you are searching for.

To compute this manually take the serialized type and shift it into the 16 highest bits of uint32_t, then take the field and place it in the 16 lowest bits.

For example:
sfEmitNonce has type 5 and field 11 thus its value is 0x050BU

| + + +
+ + +| Name | Type | Description | +| --------- | ------ | --------------------------------------------------------------------------------------------------- | +| field_id | number |

Returns the value of the specified field as an array of numbers, if the lookup fails.

| +
+
+ +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- output buffer was not large enough to hold the serialized field

INVALID_FIELD
- the sf field_id was invalid

DOESNT_EXIST
- the field was not found in the originating transaction

| +
+ + +| Type | Description | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------- | +| ByteArray or ErrorCode |

Returns the value of the specified field as an array of numbers, or an ErrorCode if the lookup fails.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_generation.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_generation.mdx new file mode 100644 index 0000000..e40bb22 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_generation.mdx @@ -0,0 +1,78 @@ +--- +title: otxn_generation +description: Get the generation of the originating transaction +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Return the generation of the originating transaction or `1` if no generation field is present. + + + +* Retrieve the generation number of the originating transaction. +* Returns the generation number as a number. + + + +### Definition + + + +```c +int64_t otxn_generation ( + void +); +``` + + + +```javascript +function otxn_generation(): number +``` + + + + + +### Example + + + +```c +int64_t generation = + otxn_generation(); +``` + + + +```javascript +const generation = otxn_generation() +``` + + + + + +### Parameters + +None + +### Return Code + + + +| Type | Description | +| ------ | ------------------------------------------ | +| number | Returns the generation number as a number. | + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------ | +| int64_t | The generation of the originating transaction, or `1` if no generation was present on the originating transaction. | + + + diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_id.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_id.mdx new file mode 100644 index 0000000..4fbc2cd --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_id.mdx @@ -0,0 +1,98 @@ +--- +title: otxn_id +description: Output the canonical hash of the originating transaction +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Write the canonical hash of the originating transaction to the output buffer. +* If flags = 1 and the transaction is an EMIT_FAILURE transaction then write the canonical hash of the originating transaction that caused the emission. + + + +* Output the canonical hash of the originating transaction. +* Returns the transaction hash as an array of numbers, or an ErrorCode if the retrieval fails. + + + +### Definition + + + +```c +int64_t otxn_id ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t flags +); +``` + + + +```javascript +function otxn_id(flag: number): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t txn_id[32]; +int64_t bytes_written = + otxn_id(txn_id, 32, 0); +``` + + + +```javascript +const tx_id = otxn_id(0) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of to store the hash. | +| write_len | uint32_t | Length of the output buffer. Should be at least 32 bytes. | +| flags | uint32_t |

If 0:
Write the canonical hash of the originating transaction.

If 1 AND the originating transaction is an EMIT_FAILURE:
Write the canonical hash of the emitting transaction.

| +
+ + +| Name | Type | Description | +| ----- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| flags | number |

If 0:
Write the canonical hash of the originating transaction.

If 1 AND the originating transaction is an EMIT_FAILURE:
Write the canonical hash of the emitting transaction.

| +
+
+ + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- output buffer was not large enough to hold the serialized object

| +
+ + +| Type | Description | +| ---------------------- | -------------------------------------------------------------------------------------------- | +| ErrorCode \| ByteArray | Returns the transaction hash as an array of numbers, or an ErrorCode if the retrieval fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_json.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_json.mdx new file mode 100644 index 0000000..b37426a --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_json.mdx @@ -0,0 +1,53 @@ +--- +title: otxn_json +description: Output the originating transaction in JSON format. +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Output the originating transaction in JSON format. +* Returns the originating transaction as a JSON object or Transaction, or an ErrorCode if the retrieval fails. + + + +### Definition + + + +```javascript +function otxn_json(): ErrorCode | Record | Transaction +``` + + + + + +### Example + + + +```javascript +const tx_json = otxn_json() +``` + + + + + +### Parameters + +No parameters + +### Return Code + + + +| Type | Description | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | +| ErrorCode \| Record\ \| Transaction | Returns the originating transaction as a JSON object or Transaction, or an ErrorCode if the retrieval fails. | + + + diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_param.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_param.mdx new file mode 100644 index 0000000..de0c325 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_param.mdx @@ -0,0 +1,102 @@ +--- +title: otxn_param +description: Retrieve the parameter value for a named Invoke transaction parameter +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Look up the value for a named parameter specified in `read_ptr` on the originating transaction (ttINVOKE only). +* Write the parameter's value to `write_ptr` + + + +* Look up the value for a named parameter specified on the originating transaction. +* Returns the value of the specified parameter, or an ErrorCode if the lookup fails. + + + +### Definition + + + +```c +int64_t otxn_param ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len +); +``` + + + +```javascript +function otxn_param(name: ByteArray | HexString): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t pname[] = {0xCAU, 0xFEU}; +uint8_t pvalue[32]; +int64_t value_len = + otxn_param(pvalue, 32, pname, 2); +``` + + + +```javascript +const pname = [0xCA, 0xFE] +const pvalue = otxn_param(pname) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ---------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. Should be at least 32 bytes. | +| write_len | uint32_t | Length of the output buffer. | +| read_ptr | uint32_t | Pointer to a buffer containing the parameter's name | +| read_len | uint32_t | Length of the parameter's name | + + + +| Name | Type | Description | +| ---- | ---------------------- | ------------------------------------------------------------------------- | +| name | ByteArray \| HexString | The name of the parameter to look up, specified as a ByteArray or string. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

DOESNT_EXIST
- The specified paramater doesn't exist or is null

TOO_SMALL
- The parameter name can't be null

TOO_BIG
- The parameter name is greater than 32 bytes

| +
+ + +| Type | Description | +| ---------------------- | ---------------------------------------------------------------------------------- | +| ErrorCode \| ByteArray | Returns the value of the specified parameter, or an ErrorCode if the lookup fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_slot.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_slot.mdx new file mode 100644 index 0000000..343c73f --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_slot.mdx @@ -0,0 +1,83 @@ +--- +title: otxn_slot +description: Load the originating transaction into a slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Emplace the originating transaction into the slot specified or into a new slot if no slot is specified + +### Definition + + + +```c +int64_t otxn_slot ( + uint32_t slot_no +); +``` + + + +```javascript +function otxn_slot(slotno: number): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +int64_t otxn_slot_no = + otxn_slot(0); +``` + + + +```javascript +const otxn_slot_no = otxn_slot(0) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | ----------------------------------------------------------------------------- | +| slot_no | uint32_t | The slot number to emplace into, or 0 if you wish to pick the next available. | + + + +| Name | Type | Description | +| ------ | ------ | --------------------------- | +| slotno | number | The slot number to look up. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The slot the otxn was placed in

INVALID_ARGUMENT
- specified slot number exceeds the largest possible slot number

NO_FREE_SLOTS
- the request could not granted because no free slot was avaialble to place the originating transaction into.

| +
+ + +| Type | Description | +| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| ErrorCode \| ByteArray |

Returns the value associated with the specified slot number as an array of numbers, or an ErrorCode if the lookup fails.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/originating-transaction/otxn_type.mdx b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_type.mdx new file mode 100644 index 0000000..c0850cf --- /dev/null +++ b/src/content/docs/docs/hooks/functions/originating-transaction/otxn_type.mdx @@ -0,0 +1,110 @@ +--- +title: otxn_type +description: Get the Transaction Type of the originating transaction +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Return the Transaction Type of the originating transaction + +### Definition + + + +```c +int64_t otxn_type ( + void +); +``` + + + + + +```javascript +function otxn_type(): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t tt = + otxn_type(); +``` + + + +```javascript +const tt = txn_type() +``` + + + +### Parameters + +None + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------- | +| int64_t | The Transaction Type of the originating transaction. Check the table below for a list of known Transaction Types at time of writing | + + + +| Type | Description | +| ------------------- | --------------------------------------------------------------------------------- | +| ErrorCode \| number | Returns the Transaction Type as a number, or an ErrorCode if the retrieval fails. | + + + + + +### Known Transaction Types + +| Name | Value | +| ------------------------------- | ----- | +| ttPAYMENT | 0 | +| ttESCROW_CREATE | 1 | +| ttESCROW_FINISH | 2 | +| ttACCOUNT_SET | 3 | +| ttESCROW_CANCEL | 4 | +| ttREGULAR_KEY_SET | 5 | +| ttOFFER_CREATE | 7 | +| ttOFFER_CANCEL | 8 | +| ttTICKET_CREATE | 10 | +| ttTICKET_CANCEL | 11 | +| ttSIGNER_LIST_SET | 12 | +| ttPAYCHAN_CREATE | 13 | +| ttPAYCHAN_FUND | 14 | +| ttPAYCHAN_CLAIM | 15 | +| ttCHECK_CREATE | 16 | +| ttCHECK_CASH | 17 | +| ttCHECK_CANCEL | 18 | +| ttDEPOSIT_PREAUTH | 19 | +| ttTRUST_SET | 20 | +| ttACCOUNT_DELETE | 21 | +| ttHOOK_SET | 22 | +| ttURITOKEN_MINT | 45 | +| ttURITOKEN_BURN | 46 | +| ttURITOKEN_BUY | 47 | +| ttURITOKEN_CREATE_SELL_OFFER | 48 | +| ttURITOKEN_CANCEL_SELL_OFFER | 49 | +| ttGENESIS_MINT | 96 | +| ttIMPORT | 97 | +| ttCLAIM_REWARD | 98 | +| ttINVOKE | 99 | +| ttAMENDMENT | 100 | +| ttFEE | 101 | +| ttUNL_MODIFY | 102 | +| ttEMIT_FAILURE | 103 | +| ttUNL_REPORT | 104 | diff --git a/src/content/docs/docs/hooks/functions/overview/hook-api-conventions.mdx b/src/content/docs/docs/hooks/functions/overview/hook-api-conventions.mdx new file mode 100644 index 0000000..128365c --- /dev/null +++ b/src/content/docs/docs/hooks/functions/overview/hook-api-conventions.mdx @@ -0,0 +1,69 @@ +--- +title: Hook API Conventions +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Naming conventions + +All Hook APIs follow a standard naming convention: + +| | | | | +| --------- | --------------- | ------------ | --------------- | +| namespace | \[ _ noun #1 ] | \[ _ verb ] | \[ _ noun #2 ] | + +This may look confusing at first but is actually quite simple: + +* If the first noun is missing then it is implicitly the same as the namespace +* If the verb is missing then it is implicitly `get` + +Thus: + +* `state()` means: fetch a hook state. +* `state_set()` means: set a hook. +* `state_foreign()` means: fetch a foreign hook state. + +### Memory model + +Each Hook executes as a singular stack frame. All working memory must exist within this stackframe. There is no heap and no dynamic memory. + +When Hooks communicate with `xahaud` they can only pass _integer_ values. Typically these integers are pointers within the Hook's memory. Since the Hook runs within xahaud, these points can then be resolved by xahaud and written to or read from as needed to perform the Hook API function. + +### Allowed functions + +Only two functions are allowed within a Hook: `hook()` and `cbak()`. Read about this [here](../../../concepts/compiling-hooks.md) + +### Parameters + + + +All parameters passed to a Hook API must be one of: `uint32_t, int32_t, uint64_t, int64_t`. Typically these are pointers and lengths of buffers within the Hook's stack frame. Sometimes they are [Integer Encoded Floating Point Numbers (XFL)](../../../concepts/floating-point-numbers-xfl.md) or other data. + +The parameters to a Hook API are always in the following order: + +1. Writing pointer _if any_ +2. Writing length _if any_ +3. Reading pointer _if any_ +4. Reading length _if any_ +5. Specifics / other fields _if any_ + +Some Hook APIs may only write or may only read from memory, and some might not do either and return a value only by return code. + + + +All parameters passed to a Hook API must be one of: `string, number[], bigint(xfl), object(json)`. Typically these are pointers and lengths of buffers within the Hook's stack frame. Sometimes they are [Integer Encoded Floating Point Numbers (XFL)](../../../concepts/floating-point-numbers-xfl.md) or other data. + +The parameters to a Hook API are always in the following order: + +1. Writing variable _if any_ +2. Reading variable _if any_ +3. Specifics / other fields _if any_ + +Some Hook APIs may only write or may only read from memory, and some might not do either and return a value only by return code. + + + + + +### Return codes + +All Hook APIs return a _signed integer_. Read about return codes here: [Return codes](return-codes.md) diff --git a/src/content/docs/docs/hooks/functions/overview/return-codes.mdx b/src/content/docs/docs/hooks/functions/overview/return-codes.mdx new file mode 100644 index 0000000..c6e6cd8 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/overview/return-codes.mdx @@ -0,0 +1,65 @@ +--- +title: Return Codes +--- +### Return code design + +Web assembly allows for exceptions (traps) however this language feature is not used for Hooks. Instead there is only one way to return from any Hook API (you may think of every Hook API as being `noexcept`). + +To provide for efficient error handling: + +1. All Hook API functions return a _signed_ integer. +2. All negative return codes are an error. +3. All return codes `0` or greater are a function specific output, usually but not always the number of bytes read or written. + +### Error codes + +Error codes are global across all Hook APIs and may be found in the table below. + +| Name | Value | Description | +| ---------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| SUCCESS | >= 0 | Non-negative return codes refer always to success and usually indicate the number of bytes written or events performed, depending on the specific API. | +| OUT_OF_BOUNDS | -1 | A pointer or buffer length provided as a parameter described memory outside of the Hook's allowed memory region. | +| INTERNAL_ERROR | -2 | Reserved for internal invariant trips, generally unrelated to inputs. These should be reported with an issue. | +| TOO_BIG | -3 | Attempted to set a parameter or value larger than the allowed space. | +| TOO_SMALL | -4 | The API was unable to produce output to the write_ptr because the specified write_len was too small. | +| DOESNT_EXIST | -5 | The requested object or item wasn't found. | +| NO_FREE_SLOTS | -6 | The Hook attempted to allocate an item into a slot, but there were no slots free. To avoid ensure re-use of existing slots. The maximum number of slots is 255. | +| INVALID_ARGUMENT | -7 | One or more of the parameters to the API were invalid according to the individual API's specification. | +| ALREADY_SET | -8 | Some APIs allow for a once-per-execution parameter to be set. A second attempt to set a once-per-execution parameter results in this error. | +| PREREQUISITE_NOT_MET | -9 | An API required the Hook to do something before the API is allowed to be called. Check the API's documentation. | +| FEE_TOO_LARGE | -10 | During fee calculation if an absurdly large fee is calculated this error is returned. | +| EMISSION_FAILURE | -11 | An attempt to `emit()` a TXN was unsccessful for any of a number of reasons. Check the `trace` log of the rippled to which you are submitting the originating TXN. | +| TOO_MANY_NONCES | -12 | A Hook may only use up to 256 calls to `nonce()` per execution. Further calls result in this error code. | +| TOO_MANY_EMITTED_TXN | -13 |

A Hook must declare ahead of time how many TXN it intends to emit().
If it emits fewer than this many, this is allowed.
If it emits more than this many this error is returned.

| +| NOT_IMPLEMENTED | -14 | While Hooks is/was in development an API may return this if some or all of that API is planned but not yet implemented. | +| INVALID_ACCOUNT | -15 | An API which accepts a 20 byte Account ID may return this if, in its opinion, the Account ID was not valid for any reason. | +| GUARD_VIOLATION | -16 | All loops inside a Hook must declare at the top of the loop, as the first non trivial instruction, before any branch instruction, the promised maximum number of iterations of the loop. If this promise is violated the hook terminates immediately with this error code. | +| INVALID_FIELD | -17 | The requested serialized field could not be found in the specified object. | +| PARSE_ERROR | -18 | While parsing serialized content an error was encountered (typically indicating an invalidly serialized object). | +| RC_ROLLBACK | -19 | Used internally to communicate a rollback event. | +| RC_ACCEPT | -20 | Used internally to communicate an accept event. | +| NO_SUCH_KEYLET | -21 | Specified keylet could not be found, or keylet is invalid | +| NOT_AN_ARRAY | -22 | API was asked to assume object under analysis is an STArray but it was not. | +| NOT_AN_OBJECT | -23 | API was asked to assume object under analysis is an STObject but it was not. | +| INVALID_FLOAT | -10024 | A floating point operation resulted in Not-A-Number or API call attempted to specify an XFL floating point number outside of the expressible range of XFL. | +| DIVISION_BY_ZERO | -25 | API call would result in a division by zero, so API ended early. | +| MANITSSA_OVERSIZED | -26 | When attempting to create an XFL the mantissa must be 16 decimal digits. | +| MANTISSA_UNDERSIZED | -27 | When attempting to create an XFL the mantissa must be 16 decimal digits. | +| EXPONENT_OVERSIZED | -28 | When attempting to create an XFL the exponent must not exceed 80. | +| EXPONENT_UNDERSIZED | -29 | When attempting to create an XFL the exponent must not be less than -96. | +| OVERFLOW | -30 | A floating point operation done on an XFL resulted in a value larger than XFL format is able to represent. | +| NOT_IOU_AMOUNT | -31 | An API assumed an STAmount was an IOU when in fact it was XRP. | +| NOT_AN_AMOUNT | -32 | An API assumed an STObject was an STAmount when in fact it was not. | +| CANT_RETURN_NEGATIVE | -33 | An API would have returned a negative integer except that negative integers are reserved for error codes (i.e. what you are reading.) | +| NOT_AUTHORIZED | -34 | Hook attempted to set foreign state but was not authorized to do so (grant was missing or invalid.) | +| PREVIOUS_FAILURE_PREVENTS_RETRY | -35 | Hook previously received a `NOT_AUTHORIZED` return code and is not allowed to retry. | +| TOO_MANY_PARAMS | -36 | Attempted to set a hook parameter for a later hook in the chain, but there are now too many parameters. | +| INVALID_TXN | -37 | Serialized transaction was not a valid transaction (usually because of a missing required field or data corruption / truncation.) | +| RESERVE_INSUFFICIENT | -38 | Setting an additional state object on this account would cause the reserve requirements to exceed the account's balance. | +| COMPLEX_NOT_SUPPORTED | -39 | Hook API would be forced to return a complex number, which it cannot do. | +| DOES_NOT_MATCH | -40 | Two arguments were required to be of the same type but are not. | +| INVALID_KEY | -41 | The provided public key was not valid. | +| NOT_A_STRING | -42 | The buffer did not contain a nul terminated string. | +| MEM_OVERLAP | -43 | The writing pointer points to a buffer that overlaps with the reading pointer. | +| TOO_MANY_STATE_MODIFICATIONS | -44 | More than 5000 modified state entries in the combined hook chains | +| TOO_MANY_NAMESPACES | -45 | More than 256 namespaces on this account | diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_emplace.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_emplace.mdx new file mode 100644 index 0000000..f28a032 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_emplace.mdx @@ -0,0 +1,142 @@ +--- +title: sto_emplace +description: Emplace a field into an existing STObject at its canonical placement +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Parse an STObject `S` (source object) pointed to by `sread_ptr` +* Parse an STObject `F` (to inject/emplace) pointed to by `fread_ptr` +* Write a new STObject to `write_ptr` which places `F` into `S` at the canonical position `field_id` + + + + + +* Ask for the STO object by the param `sto` +* Ask for the bytes representing the field to be added by the param `field_bytes` +* Ask for the ID of the field to be added by the param `field_id` +* Return the updated STO object in binary encoded ledger data format, or an error code if the operation fails. + + + +### Definition + +C + + + +```c +int64_t sto_emplace ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t sread_ptr, + uint32_t sread_len, + uint32_t fread_ptr, + uint32_t fread_len, + uint32_t field_id +); +``` + + + + + +```javascript +function sto_emplace( + sto: ByteArray | HexString, + field_bytes: ByteArray | HexString, + field_id: number + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t tx_out[1024]; + +int64_t tx_len = + sto_emplace(tx_out, sizeof(tx_out), + tx_in, tx_len, + sequence_field, 5, sfSequence); + +if (tx_len <= 0) + rollback("Emplacing failed.", 17, 1); +``` + + + + + +```javascript +const tx_out = sto_emplace(tx_in, sequence_field, sfSequence) +if (typeof tx_out === 'number') + rollback("Emplacing failed.", 1) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| write_ptr | uint32_t | The buffer to write the modified STObject to | +| write_len | uint32_t | The length of the output buffer | +| sread_ptr | uint32_t | The buffer to read the source STObject from | +| sread_len | uint32_t | The Length of the source object | +| fread_ptr | uint32_t | The buffer to read the field to be emplaced/injected from | +| fread_len | uint32_t | The length of the field to be emplaced/injected | +| field_id | uint32_t | The `sf` code (location) to form the emplacement. If this already exists in the source object then the existing field is overriden. If it doesn't exist it is inserted. | + + + + + + + +| Name | Type | Description | +| ------------ | ---------------------- | ----------------------------------------------------------------------------- | +| sto | ByteArray \| HexString | The STO object (binary encoded ledger data) to which the field will be added. | +| field_bytes | ByteArray \| HexString | The bytes representing the field to be added. | +| field_id | number | The ID of the field to be added. | + + + + + +### Return Code + + + +
TypeDescription
int64_tThe number of bytes written to write_ptr

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- Output buffer must be at least as large as the source object + the injected field, even if the field is only being overriden.

TOO_BIG
- Field you are attempting to emplace is too large

PARSE_ERROR
- The supplied STObject is malformed or not an STObject.
+ + +
+ + + + +
TypeDescription
ErrorCode | ByteArrayThe updated STO object in binary encoded ledger data format, or an error code if the operation fails.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_erase.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_erase.mdx new file mode 100644 index 0000000..48b533e --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_erase.mdx @@ -0,0 +1,128 @@ +--- +title: sto_erase +description: Remove a field from an STObject +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Parse an STObject pointed to by `read_ptr` +* Write a new STObject to `write_ptr` but without `field_id` if it was present in the original object. + + + +* It will look for the STO object (binary encoded ledger data) from which the field will be removed. +* It will look for the ID of the field to be erased. +* Returns the updated STO object in binary encoded ledger data format, or an error code if the operation fails. + + + +### Definition + + + +```c +int64_t sto_erase ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len, + uint32_t field_id +); +``` + + + + + +```javascript +function sto_erase( + sto: ByteArray | HexString, + field_id: number + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +int64_t result = + sto_erase(tx_out, sizeof(tx_out), + tx_in, tx_len, sfSigners); + +if (tx_len <= 0) + rollback("Erasing failed.", 15, 1); +``` + + + + + +```javascript +const tx_out = sto_erase(tx_in, sfSigners) + +if (typeof tx_out === 'number') + rollback("Erasing failed.", 1) +``` + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | -------------------------------------------- | +| write_ptr | uint32_t | The buffer to write the modified STObject to | +| write_len | uint32_t | The length of the output buffer | +| read_ptr | uint32_t | The buffer to read the source STObject from | +| read_len | uint32_t | The Length of the source object | +| field_id | uint32_t | The `sf` code (location) to erase | + + + + + +| Name | Type | Description | +| --------- | ---------------------- | --------------------------------------------------------------------------------- | +| sto | ByteArray \| HexString | The STO object (binary encoded ledger data) from which the field will be removed. | +| field_id | number | The ID of the field to be erased. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written to write_ptr

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- Output buffer must be at least as large as the source object.

TOO_BIG
- Field you are attempting to erase from is too large

PARSE_ERROR
- The supplied STObject is malformed or not an STObject.

DOESNT_EXIST
- The specified field_id isn't present in the STObject.

| + + +
+ + +| Type | Description | +| ---------------------- | ----------------------------------------------------------------------------------------------------- | +| ErrorCode \| ByteArray | The updated STO object in binary encoded ledger data format, or an error code if the operation fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_from_json.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_from_json.mdx new file mode 100644 index 0000000..568bb7c --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_from_json.mdx @@ -0,0 +1,73 @@ +--- +title: sto_from_json +description: Format JSON as an STO object (binary encoded ledger data). +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Takes a JSON object and converts it into a binary encoded ledger data format. +* Returns STO Object in binary encoded ledger data format, or an error code if the conversion fails. + + + + + +### Definition + + + +```javascript +function sto_from_json( + jsonobj: Record | Transaction + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```javascript +const stoBlob = sto_from_json(stoJson) +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ------- | ----------------------------------- | ----------------------------------------------- | +| jsonobj | Record\ \| Transaction | JSON object to be converted into an STO object. | + + + + + +### Return Code + + + + + +| Type | Description | +| ---------------------- | ------------------------------------------------------------------------------------------ | +| ErrorCode \| ByteArray | STO Object in binary encoded ledger data format, or an error code if the conversion fails. | + + + diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_subarray.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_subarray.mdx new file mode 100644 index 0000000..49eece1 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_subarray.mdx @@ -0,0 +1,157 @@ +--- +title: sto_subarray +description: >- + Index into a xahaud serialized array and return the location and length of an + index +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Parse a STArray pointed to by `read_ptr` +* Find the array index specified by `array_id` +* Return the byte offset and length of the serialized field within the STObject, if it is found + + + + + +* Ask for the STO object (binary encoded ledger data) from which to extract the subarray. +* Find the array index specified by `array_id` +* Return a subarray from an STO object. + + + +### Definition + + + +```c +int64_t sto_subarray ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t array_id +); +``` + + + + + +```javascript +function sto_subarray( + sto: ByteArray | HexString, + array_id: number + ): bigint | number +``` + + + + + +### Example + + + +```c +#define SUB_OFFSET(x) ((int32_t)(x >> 32)) +#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL)) + + int64_t memo_lookup = + sto_subarray(memos, memos_len, 0); + +if (memo_lookup < 0) +{ + // sfMemo was not found in the STObject pointed at by memo_ptr +} +else +{ + // 0th index of the STArray was found and its location is as follows: + uint8_t* memo_ptr = SUB_OFFSET(memo_lookup) + memos; + uint32_t memo_len = SUB_LENGTH(memo_lookup); +} +``` + + + + + +```javascript +const SUB_OFFSET = (x) => Number(x >> 32n) +const SUB_LENGTH = (x) => Number(x & 0xFFFFFFFFn) + +const memo_lookup = sto_subarray(memos, 0) + +if (typeof memo_lookup === 'number') +{ + // sfMemo was not found in the STObject pointed at +} +else +{ + // 0th index of the STArray was found and its location is as follows: + const memo_start = SUB_OFFSET(memo_lookup) + const memo_len = SUB_LENGTH(memo_lookup) + const memo = memos.slice(memo_start, memo_len) +} +``` + + + +### Parameters + + + +| Name | Type | Description | +| --------- | --------- | ------------------------------------------------------------------------- | +| read_ptr | uint32_t | Pointer to the buffer containing the STArray | +| read_len | uint32_t | Length of STArray | +| array_id | uint32_t | The index of the entry within the STArray you are seeking. Starts from 0. | + + + + + + + +| Name | Type | Description | +| --------- | ---------------------- | ------------------------------------------------------------------------------- | +| sto | ByteArray \| HexString | The STO object (binary encoded ledger data) from which to extract the subarray. | +| array_id | number | The ID of the array to be extracted. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The location of the field within the specified buffer:
- The high 32 bits are the offset location.
- The low 32 bits are the length.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- Input buffer isn't large enough to possibly contain a valid STArray.

DOESNT_EXIST
- The searched for index isn't present in the supplied STArray.

PARSE_ERROR
- The supplied STArray is malformed or not an STArray.

| + + +
+ + + + +| Type | Description | +| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| bigint / ErrorCode |

The location of the field within the specified buffer:
- The high 32 bits are the offset location.
- The low 32 bits are the length.

or an error code if the extraction fails.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_subfield.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_subfield.mdx new file mode 100644 index 0000000..32b3742 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_subfield.mdx @@ -0,0 +1,158 @@ +--- +title: sto_subfield +description: >- + Index into a xahaud serialized object and return the location and length of a + subfield +--- +import { Tabs, TabItem, LinkButton, Aside } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Parse a STObject pointed to by `read_ptr` +* Find the field specified by `field_id` +* If the field is found, and: +* + 1. It is an array, then return the start and length of the array including the leadin/leadout bytes, or +* + 2. It is **not** an array, then return the start and length of the PAYLOAD of the field (excluding the leadin bytes). + + + + + +* Parse a STObject into `sto` variable +* Find the field specified by `field_id` + + + + + +### Definition + + + +```c +int64_t sto_subfield ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t field_id +); +``` + + + + + +```javascript +function sto_subfield( + sto: ByteArray | HexString, + field_id: number + ): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +#define SUB_OFFSET(x) ((int32_t)(x >> 32)) +#define SUB_LENGTH(x) ((int32_t)(x & 0xFFFFFFFFULL)) +int64_t memos_lookup = + sto_subfield(txn_ptr, txn_len, sfMemos); +if (memos_lookup < 0) +{ + // sfMemos was not found in the STObject pointed at by memo_ptr +} +else +{ + // sfMemos was found and its location is as follows: + uint8_t* memos_ptr = SUB_OFFSET(memos_lookup) + memos_ptr; + int64_t memos_len = SUB_LENGTH(memos_lookup); +} +``` + + + + + +```javascript +const SUB_OFFSET = (x) => Number(x >> 32n) +const SUB_LENGTH = (x) => Number(x & 0xFFFFFFFFn) +const memos_lookup = sto_subfield(txn, sfMemos); +if (typeof memos_lookup === 'number') +{ + // sfMemos was not found in the STObject pointed at by memo_ptr +} +else +{ + // sfMemos was found and its location is as follows: + const memo_start = SUB_OFFSET(memos_lookup) + const memo_len = SUB_LENGTH(memos_lookup) + const memo = txn.slice(memo_start, memo_len) +} +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| --------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| read_ptr | uint32_t | Pointer to the buffer containing the STObject | +| read_len | uint32_t | Length of STObject | +| field_id | uint32_t |

The sf code of the field you are searching for.

To compute this manually take the serialized type and shift it into the 16 highest bits of uint32_t, then take the field and place it in the 16 lowest bits.

For example:
sfEmitNonce has type 5 and field 11 thus its value is 0x050BU

| + + +
+ + + + +| Name | Type | Description | +| --------- | ---------------------- | ------------------------------------------------------------------------------- | +| sto | ByteArray or HexString | The STO object (binary encoded ledger data) from which to extract the subfield. | +| field_id | number | The ID of the field to be extracted. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The location of the field within the specified buffer:
- The high 32 bits are the offset location.
- The low 32 bits are the length.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- Input buffer isn't large enough to possibly contain a valid STObject.

DOESNT_EXIST
- The searched for field isn't present in the supplied STObject.

PARSE_ERROR
- The supplied STObject is malformed or not an STObject.

| + + +
+ + + + +| Type | Description | +| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| bigint / ErrorCode |

The location of the field within the specified buffer:
- The high 32 bits are the offset location.
- The low 32 bits are the length.

or an error code if the extraction fails.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_to_json.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_to_json.mdx new file mode 100644 index 0000000..6c49dfc --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_to_json.mdx @@ -0,0 +1,75 @@ +--- +title: sto_to_json +description: Format an STO object (binary encoded ledger data) as JSON format. +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Format an STO object (binary encoded ledger data) as JSON format. + + This function takes a serialized transaction `blob` and converts it into a human-readable JSON format. +* Returns Decoded JSON representation of the STO object, or an error code if the conversion fails. + + + + + +### Definition + + + +```javascript +function sto_to_json( + blob: ByteArray | HexString + ): ErrorCode | Record | Transaction +``` + + + + + +### Example + + + +```javascript +const jsonSto = sto_to_json(stoBlob) +``` + + + + + +### Parameters + + + + + +| Name | Type | Description | +| ---- | ---------------------- | ------------------------------------------------------- | +| blob | ByteArray \| HexString | The blob (e.g. serialized transaction) to be converted. | + + + + + +### Return Code + + + + + +| Type | Description | +| ------------------------------------------------ | ---------------------------------------------------------------------------------------- | +| ErrorCode \| Record\ \| Transaction | Decoded JSON representation of the STO object, or an error code if the conversion fails. | + + + diff --git a/src/content/docs/docs/hooks/functions/serialization/sto_validate.mdx b/src/content/docs/docs/hooks/functions/serialization/sto_validate.mdx new file mode 100644 index 0000000..d8042ac --- /dev/null +++ b/src/content/docs/docs/hooks/functions/serialization/sto_validate.mdx @@ -0,0 +1,117 @@ +--- +title: sto_validate +description: Validate an STObject +--- +import { Tabs, TabItem, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Serialized Objects + +### Behaviour + + + +* Parse an STObject pointed to by `read_ptr` +* Return 1 if the serialization is valid, 0 otherwise. + + + +* The `blob` (e.g. serialized transaction) is provided to be validated. +* Returns number 1 if the STObject is valid, 0 if it isn't, or an error code if validation fails. + + + + + +### Definition + + + +```c +int64_t sto_validate ( + uint32_t read_ptr, + uint32_t read_len +); +``` + + + + + +```javascript +function sto_validate(blob: ByteArray | HexString): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t result = + sto_validate(tx_out, sizeof(tx_out)); + +if (tx_len <= 0) + rollback("Invalid STO.", 12, 1); +``` + + + + + +```javascript +const result = sto_validate(tx_out) + +if (result <= 0) + rollback("Invalid STO.", 1) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| --------- | --------- | ------------------------------------------- | +| read_ptr | uint32_t | The buffer to read the source STObject from | +| read_len | uint32_t | The Length of the source object | + + + + + + + +| Name | Type | Description | +| ---- | ---------------------- | ------------------------------------------------------- | +| blob | ByteArray \| HexString | The blob (e.g. serialized transaction) to be validated. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

1 if the STObject pointed to by read_ptr is a valid STObject.
0 if it isn't.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| + + +
+ + +| Type | Description | +| ------------------- | ----------------------------------------------------------------------------------------------- | +| ErrorCode \| number | Returns number 1 if the STObject is valid, 0 if it isn't, or an error code if validation fails. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot.mdx b/src/content/docs/docs/hooks/functions/slot/slot.mdx new file mode 100644 index 0000000..2915ceb --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot.mdx @@ -0,0 +1,104 @@ +--- +title: slot +description: Serialize and output a slotted object +--- +import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Serialize the object currently occupying the specified slot +* Write the serialized version of the object to the output buffer + + + + + +* Retrieves the JSON Retrieves the data associated with the specified slot. of the specified slot. +* Returns an error code or the slot's data. + + + +### Definition + + + +```c +int64_t slot ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t slot_no +); +``` + + + + + +```javascript +function slot(slotno: number): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t txn[512]; +int64_t bytes_written = + slot(txn, 512, 1); // assumes a transaction is slotted into slot=1 +``` + + + +```javascript +const txn = slot(1) // assumes a transaction is slotted into slot=1 +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ----------------------------------------------------------- | +| write_ptr | uint32_t | Pointer to a buffer of a suitable size to store the output. | +| write_len | uint32_t | Length of the output buffer. | +| slot_no | uint32_t | The slot number | + + + +| Name | Type | Description | +| ------ | ------ | --------------- | +| slotno | number | The slot number | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- output buffer was not large enough to hold the serialized object

| +
+ + +| Type | Description | +| ---------------------- | ----------------------------------------- | +| ErrorCode \| ByteArray | Returns an error code or the slot's data. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_clear.mdx b/src/content/docs/docs/hooks/functions/slot/slot_clear.mdx new file mode 100644 index 0000000..c104199 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_clear.mdx @@ -0,0 +1,82 @@ +--- +title: slot_clear +description: Free up a currently occupied slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Free the specified slot, releasing any object that was slotted there + +### Definition + + + +```c +int64_t slot_clear ( + uint32_t slot_no +); +``` + + + +```javascript +function slot_clear(slotno: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +slot_clear(1); // assumes a transaction is slotted into slot=1 +``` + + + +```javascript +slot_clear(1) // assumes a transaction is slotted into slot=1 +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | --------------- | +| slot_no | uint32_t | The slot number | + + + +| Name | Type | Description | +| ------ | ------ | --------------- | +| slotno | number | The slot number | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

1 or an error

If negative, an error:
DOESNT_EXIST
- the specified slot does not contain any object or it is an invalid slot

| +
+ + +| Type | Description | +| ------------------- | ----------------------------------------------------------- | +| ErrorCode \| number | Returns an error code or the result of the clear operation. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_count.mdx b/src/content/docs/docs/hooks/functions/slot/slot_count.mdx new file mode 100644 index 0000000..3568f6a --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_count.mdx @@ -0,0 +1,83 @@ +--- +title: slot_count +description: Count the elements of an array object in a slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Count the elements of an array in the specified slot +* Return the count + +### Definition + + + +```c +int64_t slot_count ( + uint32_t slot_no +); +``` + + + + + +```javascript +function slot_count(slotno: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +slot_count(1); // assumes an array is slotted into slot=1 +``` + + + +```javascript +slot_count(1) // assumes an array is slotted into slot=1 +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | --------------- | +| slot_no | uint32_t | The slot number | + + + +| Name | Type | Description | +| ------ | ------ | --------------- | +| slotno | number | The slot number | + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of elements inside the slotted array

If negative, an error:
DOESNT_EXIST
- the specified slot does not contain any object or it is an invalid slot

NOT_AN_ARRAY
- the specified slot does not contain an array object

| +
+ + +| Type | Description | +| ------------------- | ---------------------------------------------- | +| ErrorCode or number | Returns an error code or the count of entries. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_float.mdx b/src/content/docs/docs/hooks/functions/slot/slot_float.mdx new file mode 100644 index 0000000..ee4eec5 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_float.mdx @@ -0,0 +1,94 @@ +--- +title: slot_float +description: >- + Parse the STI_AMOUNT in the specified slot and return it as an XFL enclosed + number +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Parse the STI_AMOUNT in the specified slot and return it as an XFL enclosed number + + + +* Retrieves the bigint value associated with the specified slot. +* Returns an error code or the bigint value. + + + +### Definition + + + +```c +int64_t slot_float ( + uint32_t slot_no +); +``` + + + +```javascript +function slot_float(slotno: number): ErrorCode | bigint +``` + + + + + +### Example + + + +```c +int64_t xfl = + slot_float(amt_slot); +``` + + + + + +```javascript +const xfl = slot_float(amt_slot) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | --------------- | +| slot_no | uint32_t | The slot number | + + + +| Name | Type | Description | +| ------ | ------ | -------------------------------------------------- | +| slotno | number | The slot number to retrieve the bigint value from. | + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The XFL enclosing number

If negative, an error:
DOESNT_EXIST
- the specified slot does not contain any object or it is an invalid slot

NOT_AN_AMOUNT
- the specified slot does not contain an STI_AMOUNT object

| +
+ + +| Type | Description | +| ------------------- | ------------------------------------------ | +| bigint or ErrorCode | Returns an error code or the bigint value. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_set.mdx b/src/content/docs/docs/hooks/functions/slot/slot_set.mdx new file mode 100644 index 0000000..7340159 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_set.mdx @@ -0,0 +1,105 @@ +--- +title: slot_set +description: Locate an object based on its keylet and place it into a slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Locate an object given the Keylet provided in `read_ptr` +* Emplace the located object into the slot specified or into a new slot if no slot (zero) is specified + + + +* Sets the data for the specified slot. +* Returns an error code or the result of the set operation. + + + + + +### Definition + + + +```c +int64_t slot_set ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t slot_no +); +``` + + + + + +```javascript +function slot_set( + kl: ByteArray | HexString, + slotno: number + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t slot_no = + slot_set(keylet, 34, 0); +``` + + + +```javascript +const slot_no = slot_set(keylet, 0) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| --------- | --------- | ----------------------------------------------------------------------------------------------- | +| read_ptr | uint32_t | Pointer to a buffer containing the keylet of the object to locate. This can also be a txn hash. | +| read_len | uint32_t | Length of the read buffer. Should always be 32 or 34. | +| slot_no | uint32_t | The slot number to emplace into, or 0 if you wish to pick the next available. | + + + +| Name | Type | Description | +| ------ | ---------------------- | --------------------------------------------------------- | +| kl | ByteArray \| HexString | The data to set in the slot, can be an array or a string. | +| slotno | number | The slot number to set data for. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The slot number the object was inserted into

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

INVALID_ARGUMENT
- read_len must be either 32 or 34 bytes depending on whether a txn hash or a keylet is being used in read_ptr
- the hash or keylet was invalid

DOESNT_EXIST
- the requested object was not found

| +
+ + +| Type | Description | +| ------------------- | --------------------------------------------------------- | +| ErrorCode or number | Returns an error code or the result of the set operation. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_size.mdx b/src/content/docs/docs/hooks/functions/slot/slot_size.mdx new file mode 100644 index 0000000..9515a99 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_size.mdx @@ -0,0 +1,90 @@ +--- +title: slot_size +description: Compute the serialized size of an object in a slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Return the number of bytes the object in the specified slot occupies when serialized + + + +* Retrieves the size of the specified slot. + + + +### Definition + + + +```c +int64_t slot_size ( + uint32_t slot_no +); +``` + + + +```javascript +function slot_size(slotno: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t bytes_needed = slot_size(1); // get size of slot 1 +``` + + + +```javascript +const bytes_needed = slot_size(1); // get size of slot 1 +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | --------------- | +| slot_no | uint32_t | The slot number | + + + +| Name | Type | Description | +| ------ | ------ | ------------------------------------- | +| slotno | number | The slot number to check the size of. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes the object occupies when serialized

If negative, an error:
DOESNT_EXIST
- the specified slot does not contain any object or it is an invalid slot

| +
+ + +| Type | Description | +| ------------------- | ---------------------------------------------- | +| ErrorCode \| number | Returns an error code or the size of the slot. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_subarray.mdx b/src/content/docs/docs/hooks/functions/slot/slot_subarray.mdx new file mode 100644 index 0000000..56d76d7 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_subarray.mdx @@ -0,0 +1,107 @@ +--- +title: slot_subarray +description: Index into a slotted array and assign a sub-object to another slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Look up the array in slot `parent_slot` +* Retrieve the sub-object at the index specified in `array_id` +* Place sub-object into the slot `new_slot` or the next available slot if `new_slot` is 0. +* Return the new slot number. + + + +* Creates a subarray in the specified parent slot. +* Returns an error code or the result of the subarray creation. + + + +### Definition + + + +```c +int64_t slot_subarray ( + uint32_t parent_slot, + uint32_t array_id, + uint32_t new_slot +); +``` + + + +```javascript +function slot_subarray( + parent_slotno: number, + array_id: number, + new_slotno: number + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t subslot = 0; +subslot = + slot_subarray(slot_no, i, (uint32_t)subslot); +``` + + + +```javascript +let subslot = 0 +subslot = slot_subarray(slot_no, i, subslot) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| parent_slot | uint32_t | Slot the parent array is in | +| array_id | uint32_t |

The sf code of the field you are searching for.

To compute this manually take the serialized type and shift it into the 16 highest bits of uint32_t, then take the field and place it in the 16 lowest bits.

For example:
sfEmitNonce has type 5 and field 11 thus its value is 0x050BU

| +| new_slot | uint32_t | New slot number to place the object from the selected array index into. If null, choose the next available slot. _May be null._ | +
+ + +| Name | Type | Description | +| -------------- | ------ | --------------------------------------------- | +| parent_slotno | number | The parent slot number. | +| array_id | number | The ID of the array to create a subarray for. | +| new_slotno | number | The new slot number for the subarray. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The slot number of the newly allocated object

If negative, an error:

DOESNT_EXIST
- The specified array_id doesn't exist in the array pointed to by parent_slot

NO_FREE_SLOTS
- The API would require a new slot to be allocated but the Hook is already at the maximum number of slots.

NOT_AN_ARRAY
- The specified parent_slot does not contain an STArray.

| +
+ + +| Type | Description | +| ------ | ------------------------------------------------------------- | +| number | Returns an error code or the result of the subarray creation. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_subfield.mdx b/src/content/docs/docs/hooks/functions/slot/slot_subfield.mdx new file mode 100644 index 0000000..4dfc8f9 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_subfield.mdx @@ -0,0 +1,105 @@ +--- +title: slot_subfield +description: Index into a slotted object and assign a sub-object to another slot +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Look up the object in slot `parent_slot` +* Retrieve the sub-object at `field_id` +* Place sub-object into the slot `new_slot` or the next available slot if `new_slot` is 0. +* Return the new slot number. + + + +* Creates a subfield in the specified parent slot. +* Returns an error code or the result of the subfield creation. + + + +### Definition + + + +```c +int64_t slot_subfield ( + uint32_t parent_slot, + uint32_t field_id, + uint32_t new_slot +); +``` + + + +```javascript +function slot_subfield( + parent_slotno: number, + field_id: number, + new_slotno: number + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t amt_slot = + slot_subfield(oslot, sfAmount, 0); +``` + + + +```javascript +const amt_slot = slot_subfield(oslot, sfAmount, 0) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| parent_slot | uint32_t | Slot the parent object is in | +| field_id | uint32_t |

The sf code of the field you are searching for.

To compute this manually take the serialized type and shift it into the 16 highest bits of uint32_t, then take the field and place it in the 16 lowest bits.

For example:
sfEmitNonce has type 5 and field 11 thus its value is 0x050BU

| +| new_slot | uint32_t | New slot number to place the object from the selected field into. If null, choose the next available slot. _May be null._ | +
+ + +| Name | Type | Description | +| -------------- | ------ | --------------------------------------------- | +| parent_slotno | number | The parent slot number. | +| field_id | number | The ID of the field to create a subfield for. | +| new_slotno | number | The new slot number for the subfield. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The slot number of the newly allocated object

If negative, an error:

DOESNT_EXIST
- The searched for field isn't present in the parent slot or the parent slot is unfilled.

NO_FREE_SLOTS
- The API would require a new slot to be allocated but the Hook is already at the maximum number of slots.

INVALID_FIELD
- The specified field is not a valid sf field.

NOT_AN_OBJECT
- The slotted object is not a valid STObject.

| +
+ + +| Type | Description | +| ------------------- | ------------------------------------------------------------- | +| number or ErrorCode | Returns an error code or the result of the subfield creation. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/slot_type.mdx b/src/content/docs/docs/hooks/functions/slot/slot_type.mdx new file mode 100644 index 0000000..28ad034 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/slot_type.mdx @@ -0,0 +1,98 @@ +--- +title: slot_type +description: >- + Retrieve the field code of an object in a slot and, optionally, some other + information +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Locate the object pointed to by the specified `slot_no` +* Determine its `sf` field code and return this, or some other information (see below) if `flags` are used + + + +* Retrieves the type of the specified slot. +* Returns an error code or the type of the slot. + + + +### Definition + + + +```c +int64_t slot_type ( + uint32_t slot_no, + uint32_t flags +); +``` + + + +```javascript +function slot_type(slotno: number, flags: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t fidle_code = + slot_type(1, 0); +``` + + + +```javascript +const field_code = slot_type(1, 0) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| slot_no | uint32_t | The slot number | +| flags | uin32_t |

For normal operation this should be 0.

To determine whether or not an STI_AMOUNT type contains a native (XAH) amount or a floating point (IOU) amount set to 1.

| +
+ + +| Name | Type | Description | +| ------ | ------ | ------------------------------------- | +| slotno | number | The slot number to check the type of. | +| flags | number | Flags to determine the type. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

If flags is 0 then:
The sf field code of the slotted object

If flags is 1 then:
1 if and only if the slotted object is an STI_AMOUNT and the type of the amount is XAH.

If negative, an error:
DOESNT_EXIST
- the specified slot_no does not contain an object.

NOT_AN_AMOUNT
- flags was set to 1 but the slotted object is not an STI_AMOUNT object

| +
+ + +| Type | Description | +| ------------------- | ---------------------------------------------- | +| ErrorCode or number | Returns an error code or the type of the slot. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/slot/xpop_slot.mdx b/src/content/docs/docs/hooks/functions/slot/xpop_slot.mdx new file mode 100644 index 0000000..fe1e563 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/slot/xpop_slot.mdx @@ -0,0 +1,89 @@ +--- +title: xpop_slot +description: Serialize and output the xpop transaction blob and metadata +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Locate the xpop blob on the `Import` transaction +* Emplace the located tx and meta objects into the slots specified + +### Definition + + + +```c +int64_t xpop_slot ( + uint32_t slot_no_tx, + uint32_t slot_no_meta +); +``` + + + + + +```javascript +function xpop_slot(slotno_tx: number, slotno_meta: number): ErrorCode | number +``` + + + + + +### Example + + + +```c +int64_t bytes_written = + xpop_slot(1, 2); // assumes a txn is slotted into slot=1 meta is slotted into slot=2 +``` + + + +```javascript +const bytes_written = xpop_slot(1, 2) +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| -------------- | --------- | ---------------------------------------------- | +| slot_no_tx | uint32_t | The slot number to emplace the tx blob into. | +| slot_no_meta | uin32_t | The slot number to emplace the meta blob into. | + + + +| Name | Type | Description | +| ------------ | ------ | ----------------------------------- | +| slotno_tx | number | The transaction slot number to pop. | +| slotno_meta | number | The metadata slot number to pop. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

PREREQUISITE_NOT_MET

- The originating tx type was not Import.

NO_FREE_SLOTS

- The API would require a new slot to be allocated but the Hook is already at the maximum number of slots.

| +
+ + +| Type | Description | +| ------------------- | --------------------------------------------------------- | +| number or ErrorCode | Returns an error code or the result of the pop operation. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/state/state.mdx b/src/content/docs/docs/hooks/functions/state/state.mdx new file mode 100644 index 0000000..de5af89 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/state/state.mdx @@ -0,0 +1,108 @@ +--- +title: state +description: >- + Retrieve the data pointed to by a Hook State key and write it to an output + buffer +--- +import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read a 32 byte Hook State key from the `kread_ptr` +* Write the data (value) at that key to the buffer pointed to by `write_ptr` + + + +* Retrieves the Hook State value associated with the specified key. +* Returns an error code or the Hook State value for the key. + + + +### Definition + + + +```c +int64_t state ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t kread_ptr, + uint32_t kread_len +); +``` + + + +```javascript +function state(key: ByteArray | HexString): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +if (state(SBUF(vault), SBUF(vault_key)) != 16) + rollback(SBUF("Error: could not read state!"), 1); +``` + + + +```javascript +const value = state(SBUF(vault), SBUF(vault_key)) +if (typeof value === 'number' || value.length != 16) + rollback("Error: could not read state!", 1); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ----------------------------------------------------------------- | +| write_ptr | uint32_t | A pointer to the buffer to write the data in the Hook State into. | +| write_len | uint32_t | The length of the write buffer. | +| kread_ptr | uint32_t | Pointer to a buffer containing the Hook State key. | +| kread_len | uint32_t | The length of the Hook State key. (Should be 32.) | + + + + + +| Name | Type | Description | +| ---- | ---------------------- | ----------------------------------------------------- | +| key | ByteArray or HexString | The key of the Hook State to retrieve the value from. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written to the write buffer.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

DOESNT_EXIST
- the specified Hook State key doesn't have an associated value on the ledger at the time of the call.

TOO_BIG
- the key specified by read_ptr and read_len was larger than 32 bytes.

TOO_SMALL
- the output buffer was too small to store the Hook State data.

| +
+ + +| Type | Description | +| ---------------------- | ---------------------------------------------------------- | +| ByteArray or ErrorCode | Returns an error code or the Hook State value for the key. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/state/state_foreign.mdx b/src/content/docs/docs/hooks/functions/state/state_foreign.mdx new file mode 100644 index 0000000..e058d90 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/state/state_foreign.mdx @@ -0,0 +1,129 @@ +--- +title: state_foreign +description: >- + Retrieve the data pointed to, on another account, by a Hook State key and + write it to an output buffer +--- +import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read a 20 byte Account ID from the `aread_ptr` +* Read a 32 byte Hook State key from the `kread_ptr` +* Write the data (value) at that key at that Account ID to the buffer pointed to by `write_ptr` + + + +* Retrieves the Foreign Hook State value belonging to another account for the specified key. +* Returns an error code or the Hook State value for the key. + + + +### Definition + + + +```c +int64_t state_foreign ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t kread_ptr, + uint32_t kread_len, + uint32_t nread_ptr, + uint32_t nread_len, + uint32_t aread_ptr, + uint32_t aread_len +); +``` + + + +```javascript +function state_foreign( + key: ByteArray | HexString, + namespace: ByteArray | HexString | undefined | null, + accountid: ByteArray | HexString | undefined | null + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +uint8_t ns[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +int64_t lookup = + state_foreign(SBUF(blacklist_status), SBUF(otxn_accid), SBUF(ns), SBUF(blacklist_accid)); +if (lookup < 0) + rollback(SBUF("Error: could not find key on foreign state."), 1); +``` + + + +```javascript +const ns = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] +const blacklist_status = + state_foreign(otxn_accid, ns, blacklist_accid) +if (typeof blacklist_status === 'number') + rollback("Error: could not find key on foreign state.", 1); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | ------------------------------------------------------------------------------- | +| write_ptr | uint32_t | A pointer to the buffer to write the data in the Hook State into. | +| write_len | uint32_t | The length of the write buffer. | +| kread_ptr | uint32_t | Pointer to a buffer containing the Hook State key. | +| kread_len | uint32_t | The length of the Hook State key. (Should be 32.) | +| nread_ptr | uint32_t | A pointer to the buffer containing the 32 byte Namespace to lookup the state on | +| nread_len | uint32_t | The length of the namespace buffer (Should be 32). | +| aread_ptr | uint32_t | A pointer to a buffer containing the 20 byte Account ID to look up state on. | +| aread_len | uint32_t | The length of the Account buffer. (Should always be 20). | + + + + + +| Name | Type | Description | +| --------- | ---------------------- | ----------------------------------------------------- | +| key | ByteArray or HexString | The key of the Hook State to retrieve the value from. | +| namespace | ByteArray or HexString | The Hook namespace to look in. | +| accountid | ByteArray or HexString | The owner of the state. | +| | | | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes written to the write buffer.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

DOESNT_EXIST
- the specified Hook State key doesn't have an associated value on the ledger at the time of the call.

TOO_BIG
- the key specified by read_ptr and read_len was larger than 32 bytes.

TOO_SMALL
- the output buffer was too small to store the Hook State data.

INVALID_ACCOUNT
- the account specified at aread_ptr is invalid or does not exist.

| +
+ + +| Type | Description | +| ---------------------- | ---------------------------------------------------------- | +| ErrorCode or ByteArray | Returns an error code or the Hook State value for the key. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/state/state_foreign_set.mdx b/src/content/docs/docs/hooks/functions/state/state_foreign_set.mdx new file mode 100644 index 0000000..9dd333b --- /dev/null +++ b/src/content/docs/docs/hooks/functions/state/state_foreign_set.mdx @@ -0,0 +1,127 @@ +--- +title: state_foreign_set +description: Set the Hook State on another account for a given key, value and namespace +--- +import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read a 32 byte Hook State key from the `kread_ptr` +* Read an arbitrary amount of data from `read_ptr` (the value) +* Read a 32 byte Namespace from the `nread_ptr` +* Read a 20 byte Account ID from `aread_ptr` +* Update the Hook State key on the specified account within the specified namespace with the value +* But only if a [Grant](https://xrpl-hooks.readme.io/docs/grants) on that account allows this. +* If the Hook Account is specified in `aread_ptr` then the behaviour is that of state_set but still allows specification of namespace through `nread_ptr` + + + +* Sets the Foreign Hook State with the specified value, key, namespace, and account ID. +* This operation requires authorization and a Grant to allow this action. +* Returns the number of bytes written to Hook State (the length of the data), negative on error. + + + +### Definition + + + +```c +int64_t state_foreign_set ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t kread_ptr, + uint32_t kread_len, + uint32_t nread_ptr, + uint32_t nread_len, + uint32_t aread_ptr, + uint32_t aread_len +); +``` + + + +```javascript +function state_foreign_set( + value: ByteArray | HexString | undefined | null, + key: ByteArray | HexString, + namespace: ByteArray | HexString | undefined | null, + accountid: ByteArray | HexString | undefined | null + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +if (state_foreign_set(SBUF(vault), SBUF(vault_key), SBUF(namespace), SBUF(account)) < 0) + rollback(SBUF("Error: could not set foreign state!"), 1); +``` + + + +```javascript +if (state_foreign_set(vault, vault_key, namespace, account) < 0) + rollback("Error: could not set foreign state!", 1); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| read_ptr | uint32_t |

Pointer to the data (value) to write into Hook State.
If this is 0 (null) then delete the data at this key. May be null.

| +| read_len | uint32_t |

The length of the data.
If this is 0 (null) then delete the data at this key. May be null.

| +| kread_ptr | uint32_t | A pointer to the Hook State key at which to store the value. | +| kread_len | uint32_t | The length of the key. (Should always be 32.) | +| nread_ptr | uint32_t | A pointer to the namespace which the key belongs to. | +| nread_len | uint32_t | The length of the namespace. (Should always be 32.) | +| aread_ptr | uint32_t | A pointer to the Account ID whose state we are trying to modify. | +| aread_len | uint32_t | The length of the Account ID. (Should always be 20.) | + + +
+ + +| Name | Type | Description | +| --------- | ---------------------- | ----------------------------------------------- | +| value | ByteArray or HexString | The value of data to persist. | +| key | ByteArray or HexString | The key of the Hook State to set the value for. | +| namespace | ByteArray or HexString | The Hook namespace to look in. | +| accountid | ByteArray or HexString | The owner of the state. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written to Hook State (the length of the data.)

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_BIG
- kread_len was greater than 32, or
- read_len was greater than the maximum hook data size.

TOO_SMALL
- kread_len was 0.

NOT_AUTHORIZED
- no appropriate HookGrant was present on the foreign account to allow this state mutation.

PREVIOUS_FAILURE_PREVENTS_RETRY
- during this execution a previous state_foreign_set failed with NOT_AUTHORIZED, and consequently no further calls to this API are allowed during this execution.

| +
+ + +| Type | Description | +| ------------------- | ---------------------------------------------------------------------------------------------- | +| number or ErrorCode | Returns the number of bytes written to Hook State (the length of the data), negative on error. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/state/state_set.mdx b/src/content/docs/docs/hooks/functions/state/state_set.mdx new file mode 100644 index 0000000..8df982e --- /dev/null +++ b/src/content/docs/docs/hooks/functions/state/state_set.mdx @@ -0,0 +1,119 @@ +--- +title: state_set +description: Set the Hook State for a given key and value +--- +import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read a 32 byte Hook State key from the `kread_ptr` +* Read an arbitrary amount of data from `read_ptr` (the value) +* Update the Hook State key with the value + + + +* Sets the Hook State with the specified value and key. +* Returns the number of bytes written to Hook State (the length of the data), negative on error. + + + +### Definition + + + +```c +int64_t state_set ( + uint32_t read_ptr, + uint32_t read_len, + uint32_t kread_ptr, + uint32_t kread_len +); +``` + + + +```javascript +function state_set( + value: ByteArray | HexString | undefined | null, + key: ByteArray | HexString + ): ErrorCode | number +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +if (state_set(SBUF(vault), SBUF(vault_key)) < 0) + rollback(SBUF("Error: could not set state!"), 1); +``` + + + + + +```javascript +const result = state_set(vault, vault_key) +if (result < 0) + rollback("Error: could not set state!", 1); +``` + + + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| read_ptr | uint32_t |

Pointer to the data (value) to write into Hook State.
If this is 0 (null) then delete the data at this key. May be null.

| +| read_len | uint32_t |

The length of the data.
If this is 0 (null) then delete the data at this key. May be null.

| +| kread_ptr | uint32_t | A pointer to the Hook State key at which to store the value. | +| kread_len | uint32_t | The length of the key. (Should always be 32.) | + + +
+ + +| Name | Type | Description | +| ----- | ---------------------- | ----------------------------------------------- | +| value | ByteArray or HexString | The value of data to persist. | +| key | ByteArray or HexString | The key of the Hook State to set the value for. | + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written to Hook State (the length of the data.)

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_BIG
- kread_len was greater than 32, or
- read_len was greater than the maximum hook data size.

TOO_SMALL
- kread_len was 0.

| +
+ + +| Type | Description | +| ------------------- | ---------------------------------------------------------------------------------------------- | +| number or ErrorCode | Returns the number of bytes written to Hook State (the length of the data), negative on error. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/trace-debug/trace.mdx b/src/content/docs/docs/hooks/functions/trace-debug/trace.mdx new file mode 100644 index 0000000..fd17b03 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/trace-debug/trace.mdx @@ -0,0 +1,99 @@ +--- +title: trace +description: Write the contents of a buffer to the Xahaud trace log +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Write a buffer from inside the Hook to the trace log along with a message (if any) + +### Definition + + + +```c +int64_t trace ( + uint32_t mread_ptr, + uint32_t mread_len, + uint32_t dread_ptr, + uint32_t dread_len, + uint32_t as_hex +); +``` + + + + + +```javascript +function trace( + message: string | null, + data: any, + hex: boolean | 0 | 1 + ): ErrorCode +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +trace(SBUF("Buffer conatained"), SBUF(some_buffer), 1); +``` + + + +```javascript +trace("Buffer conatained", some_buffer, 1); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | --------------------------------------------------------------------------------------------------- | +| mread_ptr | uint32_t | Pointer to a message to output before the buffer. _May be null._ | +| mread_len | uint32_t | Length of the message. _May be null._ | +| dread_ptr | uint32_t | Pointer to the buffer to output. | +| dread_len | uint32_t | Length of the buffer to output. | +| as_hex | uint32_t |

If 1 output the buffer as hex.
If 0 output the buffer as utf-8.

| +
+ + +| Name | Type | Description | +| ------- | ------- | -------------------------------------------------------------------- | +| message | string | The 'logging key', message to output before the buffer (can be null) | +| data | any | The data to log | +| hex | boolean |

Should it log formatted in HEX?

0 - NO
1 - YES

| +
+
+ + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

0 if successful

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| +
+ + +| Type | Description | +| --------- | ------------------------------------------------------------------------------------------- | +| ErrorCode |

int64_t, value is 0 if successful

If negative, an error: OUT_OF_BOUNDS

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/trace-debug/trace_float.mdx b/src/content/docs/docs/hooks/functions/trace-debug/trace_float.mdx new file mode 100644 index 0000000..93ba21f --- /dev/null +++ b/src/content/docs/docs/hooks/functions/trace-debug/trace_float.mdx @@ -0,0 +1,63 @@ +--- +title: trace_float +description: Write a XFL float to the Xahaud trace log +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Write a XFL floating point to the trace log along with a message (if any) + +### Definition + + + +```c +int64_t trace_float ( + uint32_t mread_ptr, + uint32_t mread_len, + int64_t float1 +); +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +trace_float(SBUF("This is a float"), float_one()); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | --------------------------------------------------------------------------------------------------------- | +| rmead_ptr | uint32_t | Pointer to a message to output before the hex-encoded serialized object found in the slot. _May be null._ | +| mread_len | uint32_t | Length of the message. _May be null._ | +| float1 | int64_t | The enclosing XFL integer. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

0 if successful

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/trace-debug/trace_num.mdx b/src/content/docs/docs/hooks/functions/trace-debug/trace_num.mdx new file mode 100644 index 0000000..76a4d03 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/trace-debug/trace_num.mdx @@ -0,0 +1,63 @@ +--- +title: trace_num +description: Write an integer to the Xahaud trace log +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +* Write an integer to the trace log along with a message (if any) + +### Definition + + + +```c +int64_t trace_num ( + uint32_t mread_ptr, + uint32_t mread_len, + int64_t number +); +``` + + + + + +### Example + + + +```c +#define SBUF(str) (uint32_t)(str), sizeof(str) +trace_num(SBUF("This is an integer"), 10); +``` + + + + + +### Parameters + + + +| Name | Type | Description | +| ---------- | --------- | --------------------------------------------------------------------------------------------------------- | +| rmead_ptr | uint32_t | Pointer to a message to output before the hex-encoded serialized object found in the slot. _May be null._ | +| mread_len | uint32_t | Length of the message. _May be null._ | +| number | int64_t | The number. | + + + + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

0 if successful

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

| +
+
+ diff --git a/src/content/docs/docs/hooks/functions/utilities/util_accid.mdx b/src/content/docs/docs/hooks/functions/utilities/util_accid.mdx new file mode 100644 index 0000000..bc98e45 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/utilities/util_accid.mdx @@ -0,0 +1,110 @@ +--- +title: util_accid +description: Convert an r-address into a 20 byte Account ID +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read an r-address from the `read_ptr` +* Write a 20 byte Account ID to the `write_ptr` + + + + + +* Read an r-address from the `raddress` +* Returns a 20 byte Account ID or an ErrorCode + + + + + +### Definition + + + +```c +int64_t util_accid ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len +); +``` + + + +```javascript +function util_accid(raddress: string): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t accid_out[20]; +uint8_t raddr_in[] = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"; + +int64_t bytes_written = + util_accid(accid_out, 20, raddr_in, sizeof(raddr_in)-1); +// NB: if specified as a c-string as above, account for the nul char +``` + + + + + +```javascript +const accId = util_accid('rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh') +``` + + + + + + + +### Parameters + + + +
NameTypeDescription
write_ptruint32_tPointer to a buffer of a suitable size to store the output Account ID. Must be at least 20 bytes.
write_lenuint32_tLength of the output buffer.
read_ptruint32_tPointer to the r-address.
read_lenuint32_tThe length of the r-address.
+ + +
+ + +
NameTypeDescription
raddressstringThe r-address to format as HEX account ID.
+
+
+ + + +### Return Code + + + +| Type | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| int64_t |

The number of bytes written (the length of the output r-address).

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

INVALID_ARGUMENT
- read_ptr pointed at something which wasn't a valid r-address.

TOO_SMALL
- write_len was not large enough to store produced Account ID. (Should be 20 bytes).

TOO_BIG
- read_len was longer than an r-address can be.

| + + +
+ + + + +| Type | Description | +| --------------- | ------------------------------------------------------------------------------------------------ | +| string / number | If there is an error in formatting, otherwise returns the HEX Account ID as an array of numbers. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/utilities/util_keylet.mdx b/src/content/docs/docs/hooks/functions/utilities/util_keylet.mdx new file mode 100644 index 0000000..f3c69f0 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/utilities/util_keylet.mdx @@ -0,0 +1,148 @@ +--- +title: util_keylet +description: Compute a serialized keylet of a given type +--- +import { Tabs, TabItem, Aside, LinkButton } from '@astrojs/starlight/components'; + +### Concepts + +Slots and Keylets + + + +### Behaviour + +* Compute a keylet of the specified `keylet_type` according to the parameters `a` through `f` depending on type. +* Write the serialized 34 byte keylet into `write_ptr` + +### Definition + + + +```c +int64_t util_keylet ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t keylet_type, + uint32_t a, + uint32_t b, + uint32_t c, + uint32_t d, + uint32_t e, + uint32_t f +); +``` + + + + + +```javascript +function util_keylet( + keylet_type: number, + accountid: ByteArray | HexString, + statekey: ByteArray | HexString, + namespace: ByteArray | HexString + ): ErrorCode | ByteArray +``` + + + + + +### Example + + + +```c +uint8_t keylet[34]; +if (util_keylet(keylet, 34, KEYLET_LINE, + hook_accid, 20, + account_field, 20, + currency_code, 20) != 34) + rollback("Keylet Failed.", 14, 1); +``` + + + + + +```javascript +if (util_keylet( + KEYLET_LINE, hook_accid, account_field, currency_code + ).length < 34) + rollback("Keylet Failed.", 1) +``` + + + + + +### Parameters + + + +
NameTypeDescription
write_ptruint32_tPointer to a buffer the serialized keylet will be written to
write_lenuint32_tLength of output buffer, should be at least 34.
keylet_typeuint32_tOne of the keylet types as defined in hookapi.h e.g. KEYLET_LINE for a trustline.
auint32_tSee keylet table below
buint32_tSee keylet table below
cuint32_tSee keylet table below
duint32_tSee keylet table below
euint32_tSee keylet table below
fuint32_tSee keylet table below
+ + +
+ + + + +
NameTypeDescription
keylet_typeThe type of the keylet to create
accountid(Optional) First piece of data for the keylet, can be an array of numbers, a string, or a number.
statekey(Optional) Second piece of data for the keylet, can be an array of numbers, a string, or a number.
namespace(Optional) Third piece of data for the keylet, can be an array of numbers, a string, or a number.
+
+
+ + + +### Keylet Table + + + +| Keylet Type | Parameters | +| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| KEYLET_HOOK_STATE |

a points to an Account ID
b is the length of the Account ID (should be 20)
c points to a hook state key
d is the length of the key (should be 32)
e points to a hook state namespace
f is the length of the namespace (should be 32)

| +|

KEYLET_AMENDMENTS
KEYLET_FEES
KEYLET_NEGATIVE_UNL
KEYLET_EMITTED_DIR

| `a`, `b`, `c`, `d`, `e`, `f` must all be zero | +| KEYLET_SKIP |

Either:
a, b, c, d, e, f all zero
Or:
a is a LedgerIndex
b is 1
c, d, e, f must all ​be zero

| +| KEYLET_LINE |

a points to the High Account ID
b is the length of the above (should be 20)
c points to the Low Account ID
d is the length of the above (should be 20)
e points to the Currency Code
f is the length of the above (should be 20)

| +| KEYLET_QUALITY |

a points to a serialized keylet
b is the length of the above (should be 34)
c is the high 32 bits of the uint64 to pass
d is the low 32 bits of the uint64 to pass
e, f must all be zero

| +| KEYLET_DEPOSIT_PREAUTH |

a points to an Account ID
b is the length (should be 20)
c points to an Account ID
d is the length (should be 20)
e, f must all be zero

| +|

KEYLET_UNCHECKED
KEYLET_CHILD
KEYLET_EMITTED_TXN

|

a points to a key.
b is the length of the key (should be 32.)
c, d, e, f must both ​be zero

| +|

KEYLET_OWNER_DIR
KEYLET_SIGNERS
KEYLET_ACCOUNT
KEYLET_HOOK

|

a points to an Account ID.
b is the length (should be 20.)
c, d, e, f must all be zero.

| +| KEYLET_PAGE |

a points to a key.
b is the length of the key (should be 32.)
c is the high 32 bits of the uint64 to pass
d is the low 32 bits of the uint64 to pass
e, f must both ​be zero

| +|

KEYLET_OFFER
KEYLET_CHECK
KEYLET_ESCROW
KEYLET_NFT_OFFER

|

a points to an Account ID.
b is the length (should be 20.)
And Either:
c is a 32bit unsigned integer (sequence)
d is 0
Or:
c points to a 32 byte key
d is the length of the key (32).
In both cases:
e and f must be 0.

| +| KEYLET_PAYCHAN |

a points to an Account ID
b is the length (should be 20)
c points to an Account ID
d is the length (should be 20)
And Either:
e 32bit unsigned int to pass
f is zero
Or:
e points to a 32 byte key
f is the length of the key (32)

| + + +
+ + + + +
+ + + +### Return Code + + + +| Type | Description | +| -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written, should always be 34.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

INVALID_ARGUMENT
- Call didn't comply with the above table.

TOO_SMALL
- Writing buffer was smaller than 34 bytes.

| + + +
+ + + + +| Type | Description | +| ------ | --------------------------------------------------------------------------------------------------------------------- | +| number | ErrorCode if there is an error in creating the keylet, otherwise returns the generated keylet as an array of numbers. | + +
+ diff --git a/src/content/docs/docs/hooks/functions/utilities/util_raddr.mdx b/src/content/docs/docs/hooks/functions/utilities/util_raddr.mdx new file mode 100644 index 0000000..d9b98d3 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/utilities/util_raddr.mdx @@ -0,0 +1,106 @@ +--- +title: util_raddr +description: Convert a 20 byte Account ID to an r-address +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Read a 20 byte Account ID from the `read_ptr` +* Write the equivalent r-address for that Account ID to `write_ptr` + + + +* Read a 20 byte Account ID from the `accountid` +* Return the equivalent r-address for that Account ID + + + +### Definition + + + +```c +int64_t util_raddr ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len +); +``` + + + +```javascript +function util_raddr(accountid: ByteArray | HexString): ErrorCode | string +``` + + + + + +### Example + + + +```c +uint8_t raddr_out[40]; +uint8_t acc_id[20] = +{ + 0x2dU, 0xd8U, 0xaaU, 0xdbU, 0x4eU, 0x15U, + 0xebU, 0xeaU, 0xeU, 0xfdU, 0x78U, 0xd1U, 0xb0U, + 0x35U, 0x91U, 0x4U, 0x7bU, 0xfaU, 0x1eU, 0xeU +}; +int64_t bytes_written = + util_raddr(raddr_out, sizeof(raddr_out), acc_id, 20); +``` + + + + + +```javascript +const raddr = util_raddr('8D329C03074A98EF0488AB6ABBF5883F68CCFD4E') +// or +const raddr = util_raddr([ + 0x8D, 0x32, 0x9C, 0x03, 0x07, 0x4A, 0x98, 0xEF, 0x04, 0x88, + 0xAB, 0x6A, 0xBB, 0xF5, 0x88, 0x3F, 0x68, 0xCC, 0xFD, 0x4E +]) +``` + + + + + +### Parameters + + + + + +
NameTypeDescription
write_ptruint32_tPointer to a buffer of a suitable size to store the output r-address. Recommend at least 35 bytes.
write_lenuint32_tLength of the output buffer.
read_ptruint32_tPointer to the Account ID.
read_lenuint32_tThe length of the input. Always 20.
+
+ + +
NameTypeDescription
accountidnumber[]/stringThe HEX account ID to return as r-address, can be provided as an array of numbers or a string.
+
+
+ +### Return Code + + + +| Type | Description | +| -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| int64_t |

The number of bytes written (the length of the output r-address).

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

INVALID_ARGUMENT
- read_len was not 20.

TOO_SMALL
- write_len was not large enough to store produced r-address in.

| +
+ + +| Type | Description | +| ------------- | ----------------------------------------------------------------------------------------- | +| string/number | ErrorCode if there is an error in formatting, otherwise returns the r-address as a string | + +
+ diff --git a/src/content/docs/docs/hooks/functions/utilities/util_sha512h.mdx b/src/content/docs/docs/hooks/functions/utilities/util_sha512h.mdx new file mode 100644 index 0000000..b7216ec --- /dev/null +++ b/src/content/docs/docs/hooks/functions/utilities/util_sha512h.mdx @@ -0,0 +1,98 @@ +--- +title: util_sha512h +description: Compute an sha512-half over some data +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + + + +* Compute an `SHA512` hash over the data pointed to by `read_ptr` +* Write the first half of the hash to `write_ptr` + + + +* Compute an `SHA512` hash over the data pointed to by `data` +* Return the first half of the hash + + + +### Definition + + + +```c +int64_t util_sha512h ( + uint32_t write_ptr, + uint32_t write_len, + uint32_t read_ptr, + uint32_t read_len +); +``` + + + +```javascript +function util_sha512h(data: ByteArray | HexString): ErrorCode | ByteArray +``` + + + +### Example + +C + + + +```c +uint8_t hash_out[32]; +if (util_sha512h(hash_out, 32, data_in_ptr, data_in_len) < 0) + rollback("Could not generate Hash", 23, 1); +``` + + + + + +```javascript +if (util_sha512h(data) < 0) + rollback("Could not generate Hash", 1) +``` + + + + + +### Parameters + + + +
NameTypeDescription
write_ptruint32_tPointer to a buffer the hash will be written to
write_lenuint32_tLength of output buffer, should be at least 32.
read_ptruint32_tPointer to the buffer data will be read from (to compute the hash over)
read_lenuint32_tLength of input data
+ + +
+ + + + +
NameTypeDescription
dataByteArray or HexStringThe data to compute the hash over, can be provided as an array of numbers or a string.
+
+
+ + + +### Return Code + + + +
TypeDescription
int64_tThe number of bytes written, should always be 32.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.

TOO_SMALL
- Output buffer isn't large enough
+ + +
+ + +
TypeDescription
ByteArrayErrorCode if there is an error in computing the hash, otherwise returns the SHA512-half hash as an array of numbers.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/utilities/util_verify.mdx b/src/content/docs/docs/hooks/functions/utilities/util_verify.mdx new file mode 100644 index 0000000..b1012a8 --- /dev/null +++ b/src/content/docs/docs/hooks/functions/utilities/util_verify.mdx @@ -0,0 +1,96 @@ +--- +title: util_verify +description: Verify a cryptographic signature +--- +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +### Behaviour + +Verify a cryptographic signature + +* If the public key is prefixed with `0xED` then use `ED25519` +* Otherwise assume `SECP256k1` + +### Definition + + + +```c +int64_t util_verify ( + uint32_t dread_ptr, + uint32_t dread_len, + uint32_t sread_ptr, + uint32_t sread_len, + uint32_t kread_ptr, + uint32_t kread_len +); +``` + + + + + +```javascript +function util_verify( + signedData: ByteArray | HexString, + signature: ByteArray | HexString, + pubkey: ByteArray | HexString + ): 0 | 1 +``` + + + + + +### Example + + + +```c +if (!util_verify(payload_ptr, payload_len, + signature_ptr, signature_len, + publickey_ptr, publickey_len)) + rollback("Invalid Signature", 17, 60); +``` + + + +```javascript +if (util_verify(signedData,signature,pubkey)) + rollback("Invalid Signature", 60) +``` + + + + + +### Parameters + + + +
NameTypeDescription
dread_ptruint32_tPointer to the signed data
dread_lenuint32_tLength of the signed data
sread_ptruint32_tPointer to the signature
sread_lenuint32_tLength of the signature
kread_ptruint32_tPointer to the public key
kread_lenuint32_tLength of the public key
+ + +
+ + +
NameTypeDescription
signedDatanumber / stringThe signed data to verify, can be provided as an array of numbers or a string.
signaturenumber / stringThe signature to verify, can be provided as an array of numbers or a string.
pubkeynumber / stringThe public key responsible for the signature, can be provided as an array of numbers or a string.
+
+
+ + + +### Return Code + + + +
TypeDescription
int64_t0 - validation failed, the signature is invalid.
1 - validation succeeded, the signature is valid.

If negative, an error:
OUT_OF_BOUNDS
- pointers/lengths specified outside of hook memory.
+ + +
+ + +
TypeDescription
number0 - validation failed, the signature is invalid.
1 - validation succeeded, the signature is valid.
+
+
+ diff --git a/src/content/docs/docs/hooks/functions/websocket-apis/account_info.mdx b/src/content/docs/docs/hooks/functions/websocket-apis/account_info.mdx new file mode 100644 index 0000000..699c82b --- /dev/null +++ b/src/content/docs/docs/hooks/functions/websocket-apis/account_info.mdx @@ -0,0 +1,44 @@ +--- +title: account_info +--- +### New features + +The `account_info` API will now provide, in addition to its regular behaviour: + +* A list of namespaces currently in use by at least one Hook State Object +* A total count of all Hook State Objects the account has + +Example query: + +JSON + +```json +{ + "command": "account_info", + "account": "raaFre81618XegCrzTzVotAmarBcqNSAvK" +} +``` + +E.g. + +JSON + +```json +{ + "result": { + "account_data": { + "Account": "raaFre81618XegCrzTzVotAmarBcqNSAvK", + ..., + "HookNamespaces": [ + "01EAF09326B4911554384121FF56FA8FECC215FDDE2EC35D9E59F2C53EC665A0" + ], + "HookStateCount": 49, + ... + }, + "ledger_current_index": 5555046, + "validated": false + }, + "status": "success", + "type": "response" +} +``` diff --git a/src/content/docs/docs/hooks/functions/websocket-apis/account_namespace.mdx b/src/content/docs/docs/hooks/functions/websocket-apis/account_namespace.mdx new file mode 100644 index 0000000..056439b --- /dev/null +++ b/src/content/docs/docs/hooks/functions/websocket-apis/account_namespace.mdx @@ -0,0 +1,64 @@ +--- +title: account_namespace +--- +Use the `account_namespace` websocket API to query the Hook State Objects on a particular account in a particular namespace. + +Usage: + +JSON + +```json +{ + "command": "account_namespace", + "account": "", + "namespace_id": "" +} +``` + +Example query: + +JSON + +```json +{ + "command": "account_namespace", + "account": "raaFre81618XegCrzTzVotAmarBcqNSAvK", + "namespace_id": "01EAF09326B4911554384121FF56FA8FECC215FDDE2EC35D9E59F2C53EC665A0" +} +``` + +Example result: + +JSON + +```json +{ + "result": { + "account": "raaFre81618XegCrzTzVotAmarBcqNSAvK", + "ledger_current_index": 5554739, + "namespace_entries": [ + { + "Flags": 0, + "HookStateData": "CE66D3EBD1A91E9D6F47ADCF8890C92C3EE65A42313174682047656E20496E74656C28522920436F726528544D292069372D31313635473720322E3800080AF0000C3500000009C400000FA0", + "HookStateKey": "4556520237F1F3A48DFAED331FDB8F894522B5CE634C86A0258BA1B300000018", + "LedgerEntryType": "HookState", + "OwnerNode": "0", + "index": "065E103AC0838155A392DECA99D77FAE768EC822BFEC6BC999268ECBD16C8FAF" + }, + { + "Flags": 0, + "HookStateData": "00000000044E8000", + "HookStateKey": "4556520100000000000000000000000000000000000000000000000000000004", + "LedgerEntryType": "HookState", + "OwnerNode": "0", + "index": "0890BE9EE8CD129D21728FC3C2423CC0AB99D325A269A8A749C840F712989E5B" + }, + ... + ], + "namespace_id": "01EAF09326B4911554384121FF56FA8FECC215FDDE2EC35D9E59F2C53EC665A0", + "validated": false + }, + "status": "success", + "type": "response" +} +``` diff --git a/src/content/docs/docs/hooks/index.mdx b/src/content/docs/docs/hooks/index.mdx new file mode 100644 index 0000000..756c1f8 --- /dev/null +++ b/src/content/docs/docs/hooks/index.mdx @@ -0,0 +1,79 @@ +--- +title: Hooks +description: 'Introducing Hooks: The Smart Contract Functionality for Xahau.' +--- + +import { Aside } from '@astrojs/starlight/components'; + + + +### What are Hooks? + +Hooks allow the creation of customized logic and automation within the Xahau, making transactions smarter and more convenient. These small, efficient modules add custom on-ledger functionality, such as creating custom triggers for specific events on the ledger. + +These triggers can be used to send on-ledger actions or execute other actions in response to the specified event. Hooks are currently available on the [Xahau network](https://xahau.network/). + +> _To learn more about the theoretical concepts of Hooks you can visit the_ [_Concepts_](concepts/introduction) _section._ + +> _To learn how to code Hooks in C and its functions, visit_ [_Hooks C-Functions_](functions/overview/hook-api-conventions/)_._ + +> _There is a_ [_Hooks Builder site_](https://builder.xahau.network/) _where you can develop, test, debug, and deploy your own Hooks on testnet in your browser, using our examples or building your own from scratch._ + +> There is an upcoming development to allow writing Hooks in JavaScript, also known as JSHooks. At the moment it can be tested using [JSHooks](https://github.com/Xahau/jshooks-alpha) repo. + +### Why are Hooks a Big Deal? + +Simply put, Hooks add a robust smart contract functionality to Xahau, empowering you to construct and deploy applications with bespoke functionalities aligning with your specific needs and requirements. + +Hooks provide a versatile platform as they can be used for implementing a broad spectrum of business logic and smart contract paradigms. Once a hook is set up on an account, it enables you to do the following: + +* Block or allow transactions to and from the account. +* Change and keep track of the hook’s internal state and logic to inform programmatic choices. +* Autonomously initiate new transactions on the account’s behalf. + +Hooks can be written in C or any other preferred language and then compiled into WebAssembly. + +
+![Using Hooks Builder, you can develop, test, debug and deploy your own Hooks on our testnet, using our examples or building your own from scratch.](../assets/cdn.feather-2.webp) +
*Using Hooks Builder, you can develop, test, debug and deploy your own Hooks on our testnet, using our examples or building your own from scratch.*
+
+ +The Hooks Builder serves as an integrated development environment, facilitating the crafting, testing, debugging, and deployment of your Hooks on our testnet. + +Whether you're utilizing our examples or building from scratch, Hooks Builder provides a helpful environment for honing and deploying your smart contract solutions. + +### Some Examples of specific Hooks and Use Cases + +Showcasing the potential of Hooks with these concrete examples, each illustrating a unique application of smart contract functionality on Xahau: + +* **Auto-Savings Hook**: Automate savings by configuring a Hook to transfer a set amount of XAH to a separate savings account on the ledger. This could be done to help save a portion of XAH and build up savings at specified intervals—daily, weekly, or monthly. This recurring transfer mechanism can be a base for developing personal finance applications or subscription-based models. +* **Carbon-Offset Hook**: Each transaction triggers an additional transfer of 1% of the amount to a carbon offset account managed by a trusted non-governmental organization (NGO) using the money for a good cause. This feature can be used as a base for building applications that contribute to environmental sustainability with every transaction made. +* **Firewall Hook**: By filtering incoming and outgoing transactions. The Firewall Hook can block malicious transactions originating from known scam accounts or containing suspicious memos. By retrieving an updated blocklist from a Hook on a different account, the firewall maintains a robust defense against fraud without the need for manual intervention. Additionally, implementing spending limits to deny high-value unauthorized withdrawals could be a crucial feature for financial applications. + +### **Distinguishing Hooks from Ethereum Virtual Machine (EVM)** + +Xahau Hooks and the EVM allow developers to build and deploy custom logic and automation within their platforms. However, some key differences between these two technologies set them apart. + +* **Platform Compatibility**: Hooks are tailored for Xahau, while EVM smart contracts are designed for Ethereum-based blockchains. +* **Execution Efficiency**: Hooks utilize WebAssembly (WASM), outperforming the bytecode used by the EVM in terms of speed and efficiency. +* **Predictable Execution Time**: Xahau Hooks use guards to ensure maximum execution time is well-bounded and known ahead of time, improving efficiency. + +### Alternatives to Hooks on the XRPL ecosystem + +Ripple and Peersyst announced that an EVM-compatible sidechain is now live [on the company's devnet](https://opensource.ripple.com/docs/evm-sidechain/intro-to-evm-sidechain/). This sidechain functions as an autonomous blockchain, complete with its unique consensus protocol and transaction rules. The EVM sidechain is an alternative to Hooks, adding smart contract functionality to the ecosystem. + +However, it's essential to note that EVM sidechain contracts function on Layer 2, which requires a two-step process where XRP is transitioned onto the sidechain for contract execution and then back to the main ledger. Once on the sidechain, then again on the XRPL, meaning Layer 2 smart contracts cannot influence the flow. Hooks can decide if a transaction is allowed in the first place. Layer 2 can make a retroactive decision, but the initial transaction has already happened. + +Hooks are more closely integrated with XRPL, operating directly on Xahau, an Layer 1 XRPL-core fork, so they are more tightly integrated with the underlying blockchain technology than the EVM-compatible sidechain to take advantage of the specific features and capabilities of the XRPL platform. With the inherent scalability and performance of WebAssembly, Hooks are optimal to enhance Xahau's functionality. + +### Hooks Will Expand the On-ledger Functionality and Help Xahau Grow + +Hooks add native smart contract capabilities to Xahau, enabling the crafting of custom applications that meet the unique needs of users, bringing new functionalities, and opening up whole new domains of functionality. With Hooks, the possibilities are virtually unlimited. + +As Xahau continues to grow, there is no doubt that Hooks will play a significant role in driving further innovation and adoption of the platform by retail and enterprise users. diff --git a/src/content/docs/docs/index.mdx b/src/content/docs/docs/index.mdx new file mode 100644 index 0000000..1a554e0 --- /dev/null +++ b/src/content/docs/docs/index.mdx @@ -0,0 +1,33 @@ +--- +title: Xahau Documentation +--- + +import { LinkCard } from '@astrojs/starlight/components'; + +Welcome to the Xahau Documentation. This is your comprehensive guide to understanding and working with Xahau. This documentation is divided into three main categories: Features, Infrastructure, and Technical. + +Each category is designed to provide you with detailed insights and instructions about different aspects of Xahau. + +### Features + +The Features section is where you'll find information about the unique aspects of Xahau. One of the key areas covered in this section is Developer Tooling. + +Our Developer Tooling page covers Hooks Tools and Client Libraries, simplifying the process of interacting with Hooks and the Xahau Ledger. This section is designed to help you understand the functionality and capabilities of Xahau, with practical examples to help illustrate these features in action. + +### Protocol Reference + +The Protocol Reference section of Xahau's documentation provides an in-depth look at the platform's unique aspects, including various transaction types like AccountDelete, CheckCancel, and Payment, each with its own specific use and characteristics. + +It also covers the different ledger objects integral to the network's operation, such as AccountRoot and Amendments. This comprehensive overview aims to enhance the understanding of Xahau's functionalities and capabilities, ensuring users can fully leverage the network's features. + +### Infrastructure + +The Infrastructure section provides detailed instructions for setting up the build environment on both Ubuntu 22.04 and macOS 13.5.2. + +In the 'Building Xahau' chapter, you will find a step-by-step guide through the process of establishing environmental variables, installing core and Xahaud dependencies, and compiling the software. + +This includes the acquisition and setup of essential components like LLVM, Boost, WasmEdge, and Protobuf. The steps explain why certain versions and configurations are needed to ensure compatibility and optimal performance. + +This section ends with cloning the Xahau repository and creating the Xahaud target, setting developers on the path to adding to or deploying the Xahau network. + +**We hope this documentation provides you with the information you need to understand, use, and contribute to Xahau. Happy exploring!** diff --git a/src/content/docs/docs/infrastructure/building-xahau/index.mdx b/src/content/docs/docs/infrastructure/building-xahau/index.mdx new file mode 100644 index 0000000..12a6f91 --- /dev/null +++ b/src/content/docs/docs/infrastructure/building-xahau/index.mdx @@ -0,0 +1,9 @@ +--- +title: Building Xahau +description: A Guide to Setting Up the Development Environment. +--- +This section provides detailed instructions for setting up the build environment on both Ubuntu 22.04 and macOS 13.5.2. + +The building Xahau chapter will guide you through the process of establishing environmental variables, installing core and **Xahaud** dependencies, and compiling the software, including the acquisition and setup of essential components like LLVM, Boost, WasmEdge, and Protobuf. + +The steps explain why certain versions and configurations are needed to ensure compatibility and optimal performance. Ending with cloning the Xahau repository and creating the **Xahaud** target, which sets developers on the path to adding to or deploying the Xahau network. diff --git a/src/content/docs/docs/infrastructure/building-xahau/mac-os-13-5-2.mdx b/src/content/docs/docs/infrastructure/building-xahau/mac-os-13-5-2.mdx new file mode 100644 index 0000000..297000c --- /dev/null +++ b/src/content/docs/docs/infrastructure/building-xahau/mac-os-13-5-2.mdx @@ -0,0 +1,189 @@ +--- +title: Mac OS - 15.3.2 (24D81) +--- +import { Aside } from '@astrojs/starlight/components'; + + + +## CMake Legacy Building + +| Dependency | Working Versions | +| ----------- | ---------------- | +| Apple Clang | 14.3.1, 16.0.0 | +| LLVM | 14, 16 | +| LLD | 14, 16 | +| Boost | 1.86.0 | +| CMake | 3.23.1 | +| Protobuf | 3.20.0 | +| WasmEdge | 0.11.2 | + +### Using Apple Clang 14.3.1 + +1. Download an older version of Xcode + 1. Go to the [https://developer.apple.com/download/more/](https://developer.apple.com/download/more/) page. You will need to sign in with your Apple Developer account. + 2. Search for the version of Xcode that includes Apple Clang 14. This is typically specified in the release notes for each Xcode version. + 3. Download the Xcode \`.xip\` file for the version you need. +2. Install the older version of Xcode: + 1. Once the download is complete, extract the \`.xip\` file, which will give you an Xcode application. + 2. Rename this Xcode application if you want to keep multiple versions of Xcode on your system (e.g., \`Xcode_14.3.1.app\`). + 3. Drag the Xcode application to your \`/Applications\` directory. +3. Switch to the desired version of the toolchain + 1. If you want to use the newly installed version of Xcode and its toolchain by default, you can switch to it using the \`xcode-select\` command: + + ``` + sudo xcode-select -s /Applications/Xcode_14.3.1.app/Contents/Developer + ``` + 2. Replace \`Xcode_14.3.1.app\` with the actual name of the Xcode version you installed. + 3. Open Terminal and run the following command to check the version of Clang: + + `clang --version` + + + +``` +export DEVELOPER_DIR=/Applications/Xcode_14.3.1.app/Contents/Developer +clang --version +``` + +### Set Build Env Variables + +First make a dependency directory. I like to use `~/dependencies` + +``` +mkdir ~/dependencies +``` + +Next we need to set the environment variables. + +### Set Version Env Variables + +``` +export LLVM_VERSION=14 +export BOOST_VERSION=1.86.0 +export WASMEDGE_VERSION=0.11.2 +export PROTOBUF_VERSION=3.20.0 +``` + +### Set Build Env Variables + +``` +export DEP_DIR=~/dependencies +export BOOST_FOLDER_NAME="boost_$(echo "$BOOST_VERSION" | sed 's/\./_/g')" +export BOOST_ROOT="$DEP_DIR/$BOOST_FOLDER_NAME" +export BOOST_LIBRARY_DIRS="$BOOST_ROOT/libs" +export BOOST_INCLUDE_DIR="$BOOST_ROOT/boost" +export BOOST_CXXFLAGS="${BOOST_CXXFLAGS:-} -DBOOST_ASIO_HAS_STD_INVOKE_RESULT" +export LLVM_PREFIX=`brew --prefix llvm@$LLVM_VERSION` +export LLVM_DIR="$LLVM_PREFIX/lib/cmake/llvm" +export LLVM_LIBRARY_DIR="$LLVM_PREFIX/lib" +export LLD_DIR="$LLVM_PREFIX/lib/cmake/lld" +export CC=clang +export CXX=clang++ +export LDFLAGS="${LDFLAGS:-} -L$BOOST_LIBRARY_DIRS -L$LLVM_PREFIX/lib" +export CPPFLAGS="${CPPFLAGS:-} -I$BOOST_ROOT/include -I$LLVM_PREFIX/include" +export CFLAGS="${CFLAGS:-} -DBOOST_ASIO_HAS_STD_INVOKE_RESULT" +export CXXFLAGS="${CXXFLAGS:-} -DBOOST_ASIO_HAS_STD_INVOKE_RESULT" +``` + +### Install Core Dependencies + +``` +brew update +brew install automake \ + wget \ + curl \ + git \ + pkg-config \ + openssl \ + autoconf \ + libtool \ + unzip \ + cmake \ + "llvm@$LLVM_VERSION" +``` + +### Install Rippled Dependencies + +Install Protobuf + +``` +cd $DEP_DIR && \ +wget -nc https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOBUF_VERSION/protobuf-all-$PROTOBUF_VERSION.tar.gz && \ +tar -xzf protobuf-all-$PROTOBUF_VERSION.tar.gz && \ +cd protobuf-$PROTOBUF_VERSION/ && \ +./autogen.sh && \ +./configure --disable-shared link=static && \ +make -j$(sysctl -n hw.logicalcpu) && \ +sudo make install +``` + + + +Install Boost + +``` +cd $DEP_DIR && \ +wget https://archives.boost.io/release/$BOOST_VERSION/source/$BOOST_FOLDER_NAME.tar.gz && \ +tar -xvzf $BOOST_FOLDER_NAME.tar.gz && \ +cd $BOOST_FOLDER_NAME && \ +./bootstrap.sh && \ +./b2 -j$(sysctl -n hw.logicalcpu) +``` + +Install WasmEdge + +``` +cd $DEP_DIR && \ +wget -nc -q https://github.com/WasmEdge/WasmEdge/archive/refs/tags/$WASMEDGE_VERSION.zip && \ +unzip -o $WASMEDGE_VERSION.zip && \ +cd WasmEdge-$WASMEDGE_VERSION && \ +sed -i '' \ + 's|https://boostorg\.jfrog\.io/artifactory/main/release/|https://archives.boost.io/release/|g' CMakeLists.txt && \ +mkdir build && \ +cd build && \ +cmake -DCMAKE_BUILD_TYPE=Release \ + -DWASMEDGE_BUILD_SHARED_LIB=OFF \ + -DWASMEDGE_BUILD_STATIC_LIB=ON \ + -DWASMEDGE_BUILD_AOT_RUNTIME=ON \ + -DWASMEDGE_FORCE_DISABLE_LTO=ON \ + -DCMAKE_POSITION_INDEPENDENT_CODE=ON \ + -DWASMEDGE_LINK_LLVM_STATIC=ON \ + -DWASMEDGE_BUILD_PLUGINS=OFF \ + -DWASMEDGE_LINK_TOOLS_STATIC=ON \ + .. && \ +make -j$(sysctl -n hw.logicalcpu) && \ +sudo make install +``` + +### Clone the repository + +``` +mkdir ~/projects && \ +cd ~/projects && \ +git clone https://github.com/Xahau/xahaud.git && \ +cd xahaud && \ +git checkout dev +``` + +### Build Xahaud + +From the root `xahaud` directory: + +```shellscript +mkdir build && \ +cd build && \ +cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_DIR=$LLVM_DIR -DLLVM_LIBRARY_DIR=$LLVM_LIBRARY_DIR .. && \ +cmake --build . --target rippled --parallel -j$(sysctl -n hw.logicalcpu) +``` + +Start the built node + +``` +./rippled +``` diff --git a/src/content/docs/docs/infrastructure/building-xahau/ubuntu-22-04.mdx b/src/content/docs/docs/infrastructure/building-xahau/ubuntu-22-04.mdx new file mode 100644 index 0000000..d328449 --- /dev/null +++ b/src/content/docs/docs/infrastructure/building-xahau/ubuntu-22-04.mdx @@ -0,0 +1,166 @@ +--- +title: Ubuntu - 22.04 +--- +import { Aside } from '@astrojs/starlight/components'; + + + +## CMake Legacy Building + +| Dependency | Working Version | +| ---------- | --------------- | +| GCC / G++ | 14.0.3 | +| LLVM | 14.0.3 | +| LLD | 14.0.3 | +| Boost | 1.86.0 | +| CMake | 3.23.1 | +| Protobuf | 3.20.0 | +| WasmEdge | 0.11.2 | + +### Set Build Env Variables + +First make a dependency directory. I like to use `~/dependencies` + +``` +mkdir ~/dependencies +``` + +Next we need to set the environment variables. + +### Set Versions Env Variables + + + +``` +export UBUNTU_VERSION=jammy +export LLVM_VERSION=14 +export CMAKE_VERSION=3.23.1 +export BOOST_VERSION=1.86.0 +export WASMEDGE_VERSION=0.11.2 +export PROTOBUF_VERSION=3.20.0 +``` + +### Set Build Env Variables + +``` +export DEP_DIR=~/dependencies +export BOOST_FOLDER_NAME="boost_$(echo "$BOOST_VERSION" | sed 's/\./_/g')" +export BOOST_ROOT=$DEP_DIR/$BOOST_FOLDER_NAME +export Boost_LIBRARY_DIRS=$BOOST_ROOT/libs +export BOOST_INCLUDEDIR=$BOOST_ROOT/boost +export Boost_INCLUDE_DIRS=$BOOST_ROOT/boost +export LLVM_DIR=/usr/lib/llvm-$LLVM_VERSION/lib/cmake/llvm +export LLVM_LIBRARY_DIR=/usr/lib/llvm-$LLVM_VERSION/lib +export LLD_DIR=/usr/lib/llvm-$LLVM_VERSION/lib/cmake/lld +export CC=gcc +export CXX=g++ +export CFLAGS="-DBOOST_ASIO_HAS_STD_INVOKE_RESULT" +export CXXFLAGS="-DBOOST_ASIO_HAS_STD_INVOKE_RESULT" +export BOOST_CXXFLAGS="-DBOOST_ASIO_HAS_STD_INVOKE_RESULT" +export LDFLAGS="-L$BOOST_ROOT/lib" +export CPPFLAGS="-I$BOOST_ROOT/include" +export LDFLAGS="-L/usr/lib/llvm-$LLVM_VERSION/lib" +export CPPFLAGS="-I/usr/lib/llvm-$LLVM_VERSION/include" +``` + +### Install Core Dependencies + +``` +apt update && \ +apt install -y build-essential software-properties-common wget curl git pkg-config zlib1g-dev libssl-dev autoconf libtool unzip gcc g++ ninja-build && \ +wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc && \ +add-apt-repository "deb http://apt.llvm.org/$UBUNTU_VERSION/ llvm-toolchain-$UBUNTU_VERSION-$LLVM_VERSION main" && \ +add-apt-repository ppa:deadsnakes/ppa && \ +apt-cache policy python3.9 && \ +apt install -y python3.9 python3-pip llvm-$LLVM_VERSION-dev liblld-$LLVM_VERSION-dev libpolly-$LLVM_VERSION-dev +``` + + + +``` +sudo nano /etc/apt/sources.list +# Scroll down and remove +deb http://apt.llvm.org/ llvm-toolchain-- main +# Add the apt-repo directly with add-apt-repository "deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-14 main" +``` + +### Install Rippled Dependencies + +Install CMake + +``` +cd $DEP_DIR && \ +wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.sh && \ +sudo sh cmake-$CMAKE_VERSION-Linux-x86_64.sh --prefix=/usr/local --exclude-subdir +``` + +Install Protobuf + +``` +cd $DEP_DIR && \ +wget -nc https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOBUF_VERSION/protobuf-all-$PROTOBUF_VERSION.tar.gz && \ +tar -xzf protobuf-all-$PROTOBUF_VERSION.tar.gz && \ +cd protobuf-$PROTOBUF_VERSION/ && \ +./autogen.sh && \ +./configure --prefix=/usr --disable-shared link=static && \ +make -j$(nproc) && \ +sudo make install +``` + +Install Boost + +``` +cd $DEP_DIR && \ +wget https://boostorg.jfrog.io/artifactory/main/release/$BOOST_VERSION/source/$BOOST_FOLDER_NAME.tar.gz && \ +tar -xvzf $BOOST_FOLDER_NAME.tar.gz && \ +cd $BOOST_FOLDER_NAME && \ +./bootstrap.sh && \ +./b2 -j$(nproc) +``` + +Install WasmEdge + +``` +cd $DEP_DIR && \ +wget -nc -q https://github.com/WasmEdge/WasmEdge/archive/refs/tags/$WASMEDGE_VERSION.zip && \ +unzip -o $WASMEDGE_VERSION.zip && \ +cd WasmEdge-$WASMEDGE_VERSION && \ +mkdir build && \ +cd build && \ +cmake -DCMAKE_BUILD_TYPE=Release -DWASMEDGE_BUILD_SHARED_LIB=OFF -DWASMEDGE_BUILD_STATIC_LIB=ON -DWASMEDGE_BUILD_AOT_RUNTIME=ON -DWASMEDGE_FORCE_DISABLE_LTO=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DWASMEDGE_LINK_LLVM_STATIC=ON -DWASMEDGE_BUILD_PLUGINS=OFF -DWASMEDGE_LINK_TOOLS_STATIC=ON .. && \ +make -j$(nproc) && \ +sudo make install +``` + +### Clone the repository + +``` +mkdir ~/projects && \ +cd ~/projects && \ +git clone https://github.com/Xahau/xahaud.git && \ +cd xahaud && \ +git checkout dev +``` + +### Build Xahaud + +From the root `xahaud` directory: + +```shellscript +mkdir build && \ +cd build && \ +cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_DIR=$LLVM_DIR -DLLVM_LIBRARY_DIR=$LLVM_LIBRARY_DIR .. && \ +cmake --build . --target rippled --parallel -j$(nproc) +``` + +Start the built node + +``` +./rippled +``` diff --git a/src/content/docs/docs/infrastructure/node-requirements.mdx b/src/content/docs/docs/infrastructure/node-requirements.mdx new file mode 100644 index 0000000..9e36dce --- /dev/null +++ b/src/content/docs/docs/infrastructure/node-requirements.mdx @@ -0,0 +1,19 @@ +--- +title: Node Requirements +--- +Hardware requirements for nodes (RPC, validator, ...) should be generally along the lines of the specs outlined below. + +For specific node use cases (e.g. full history) specs may differ (and grow) over time. + +### Nodes should run (reasonably) well for own use with: + +* CPU: 6+ cores +* Memory: 16GB+ (32GB advised) +* Disk IO: 10k random RW +* Disk size: 100GB+ +* Filesystem: EXT4/XFS/... +* Network IO: 100Mbit+ + +### Nodes for future (network growth) production use: + +
MinimumPreferredIdeal
CPU16 cores20+ cores40+ cores
Memory32GB64GB128GB+
Disk IO15k random RW20k random RW30k random RW
Disk Size500GB1TB2TB
FilesystemXFSXFSXFS
Network IO500Mbit+1Gbit10Gbit
diff --git a/src/content/docs/docs/infrastructure/running-a-node/running-a-mainnet-node.mdx b/src/content/docs/docs/infrastructure/running-a-node/running-a-mainnet-node.mdx new file mode 100644 index 0000000..ea98e95 --- /dev/null +++ b/src/content/docs/docs/infrastructure/running-a-node/running-a-mainnet-node.mdx @@ -0,0 +1,26 @@ +--- +title: Running a Mainnet Node +description: >- + Xahau Mainnet allows for running your own local node. You can run a Docker + Container or connect with your own local running instance. +--- +### Connecting to the Xahau Mainnet with Docker + +To connect to the Xahau Mainnet you can use this docker container: + +[https://github.com/Xahau/mainnet-docker](https://github.com/Xahau/mainnet-docker) + +1. Clone the repository +2. Run `./build` +3. Run `./up` +4. Check the README for commands, etc. [https://github.com/Xahau/mainnet-docker/blob/main/README.md](https://github.com/Xahau/mainnet-docker/blob/main/README.md) +5. Connect using WebSockets or RPC:\ + WebSocket: `ws://localhost:16006`\ + RPC (HTTP POST): `http://localhost:16007` + +## Local instance + +### Peering info + +
Infohttps://xahau.network/
Explorerhttps://explorer.xahau.network/
Technical docshttps://xrpl-hooks.readme.io
WebSocket URLwss://xahau.network
Public peering Network ID: 21337
- Hub (Cluster) 1: bacab.alloy.ee 21337
- Hub (Cluster) 2: hubs.xahau.as16089.net 21337
- Hub 3: xahau-1.cabbit.tech 21337
- Hub 4: xahau-2.cabbit.tech 21337
Binary & config

For ubuntu 22.04:

Download:

https://build.xahau.tech

For the latest release build numbers, see the Github Build Actions.


Extract, then run:
./xahaud --net --conf xahaud.cfg Config file sample (to be saved as xahaud.cfg):

UNL (VL)https://vl.xahau.org/
+ diff --git a/src/content/docs/docs/infrastructure/running-a-node/running-a-testnet-node.mdx b/src/content/docs/docs/infrastructure/running-a-node/running-a-testnet-node.mdx new file mode 100644 index 0000000..eb542a9 --- /dev/null +++ b/src/content/docs/docs/infrastructure/running-a-node/running-a-testnet-node.mdx @@ -0,0 +1,36 @@ +--- +title: Running a Testnet Node +description: >- + Xahau Testnet allows for running your own local node. You can run a Docker + Container or connect with your own local running instance. +--- +### Connecting to the Xahau Testnet with Docker + +To connect to the Xahau Testnet (Hooks V3 testnet) you can use this Docker container: + +[https://github.com/Xahau/Xahau-Testnet-Docker/](https://github.com/Xahau/Xahau-Testnet-Docker/) + +1. Clone the repository +2. Run `./build` +3. Run `./up` +4. Check the README for commands, etc.\ + [https://github.com/Xahau/Xahau-Testnet-Docker/blob/main/README.md](https://github.com/Xahau/Xahau-Testnet-Docker/blob/main/README.md) +5. Connect using WebSockets or RPC:\ + WebSocket: `ws://localhost:16006`\ + RPC (HTTP POST): `http://localhost:16007` + +## Local instance + +### Peering info + +
Info & Faucethttps://xahau-test.net
Explorerhttps://explorer.xahau-test.net
Technical docshttps://xrpl-hooks.readme.io
WebSocket URLwss://xahau-test.net
Public peering V4Network ID: 21338

79.110.60.122 Port: 21338
79.110.60.124 Port: 21338
79.110.60.125 Port: 21338
79.110.60.121 Port: 21338
Public peering V4

2a0c:3bc0::1c74 Port: 21338

2a0c:3bc0::169d Port: 21338

2a0c:3bc0::1aaf Port: 21338

2a0c:3bc0::1d78 Port: 21338

Binary & config

For ubuntu 22.04:

Download:

https://build.xahau.tech - fetch the latest RELEASE version

Extract, then run:
./xahaud --net --quorum=2 --conf xahaud.cfg Config file sample (to be saved as xahaud.cfg):

Validators[validators]
nHBoJCE3wPgkTcrNPMHyTJFQ2t77EyCAqcBRspFCpL6JhwCm94VZ
nHUVv4g47bFMySAZFUKVaXUYEmfiUExSoY4FzwXULNwJRzju4XnQ
nHBvr8avSFTz4TFxZvvi4rEJZZtyqE3J6KAAcVWVtifsE7edPM7q
nHUH3Z8TRU57zetHbEPr1ynyrJhxQCwrJvNjr4j1SMjYADyW1WWe
+ + + +### Integrating Xumm with Hooks V3 + +
+![QR Code](../../assets/image.png) +
+ +To connect Xumm to the Hooks V3 staging net, scan this QR with the QR scanner in Xumm to add the endpoint (above) to the Xumm node list. diff --git a/src/content/docs/docs/protocol-reference/binary-format.mdx b/src/content/docs/docs/protocol-reference/binary-format.mdx new file mode 100644 index 0000000..3ac4bd6 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/binary-format.mdx @@ -0,0 +1,322 @@ +--- +title: Binary Format +--- +[\[Source\]](https://github.com/Xahau/xahaud/blob/dev/src/ripple/protocol/impl/STObject.cpp#L696-L718) + +This page describes the Xahau's canonical binary format for transactions and other data. This binary format is necessary to create and verify digital signatures of those transactions' contents, and is also used in other places including in the peer-to-peer communications between servers. The `xahaud` APIs typically use JSON to communicate with client applications. However, JSON is unsuitable as a format for serializing transactions for being digitally signed, because JSON can represent the same data in many different but equivalent ways. + +The process of serializing a transaction from JSON or any other representation into their canonical binary format can be summarized with these steps: + +1. Make sure all required fields are provided, including any required but "auto-fillable" fields. + + The Transaction Formats Reference defines the required and optional fields for Xahau transactions. + + **Note:** The `SigningPubKey` must also be provided at this step. When signing, you can derive this key from the secret key that is provided for signing. +2. Convert each field's data into its "internal" binary format. +3. Sort the fields in canonical order. +4. Prefix each field with a Field ID. +5. Concatenate the fields (including prefixes) in their sorted order. + +The result is a single binary blob that can be signed using well-known signature algorithms such as ECDSA (with the secp256k1 elliptic curve) and Ed25519. For purposes of Xahau, you must also \[hash]\[Hash] the data with the appropriate prefix (`0x53545800` if single-signing, or `0x534D5400` if multi-signing). After signing, you must re-serialize the transaction with the `TxnSignature` field included. + +**Note:** Xahau uses the same serialization format to represent other types of data, such as ledger objects and processed transactions. However, only certain fields are appropriate for including in a transaction that gets signed. (For example, the `TxnSignature` field, containing the signature itself, should not be present in the binary blob that you sign.) Thus, some fields are designated as "Signing" fields, which are included in objects when those objects are signed, and "non-signing" fields, which are not. + +#### Examples + +Both signed and unsigned transactions can be represented in both JSON and binary formats. The following samples show the same signed transaction in its JSON and binary formats: + +**JSON:** + +```json + +
+ +``` + +**Binary (represented as hexadecimal):** + +``` + +
+ +``` + +### Sample Code + +The serialization processes described here are implemented in multiple places and programming languages: + +* In C++ [in the `rippled` code base](https://github.com/Xahau/xahaud/blob/dev/src/ripple/protocol/impl/STObject.cpp). +* In JavaScript in this repository's code samples section. +* In Python 3 in this repository's code samples section. + +Additionally, many client libraries provide serialization support under permissive open-source licenses, so you can import, use, or adapt the code for your needs. + +### Internal Format + +Each field has an "internal" binary format used in the `xahaud` source code to represent that field when signing (and in most other cases). The internal formats for all fields are defined in the source code of [`SField.cpp`](https://github.com/Xahau/xahaud/blob/master/src/ripple/protocol/impl/SField.cpp). (This file also includes fields other than transaction fields.) The Transaction Format Reference also lists the internal formats for all transaction fields. + +For example, the `Flags` common transaction field becomes a UInt32 (32-bit unsigned integer). + +#### Definitions File + +The following JSON file defines the important constants you need for serializing Xahau data to its binary format and deserializing it from binary: + +[**https://github.com/XRPLF/xrpl.js/blob/main/packages/ripple-binary-codec/src/enums/definitions.json**](https://github.com/XRPLF/xrpl.js/blob/main/packages/ripple-binary-codec/src/enums/definitions.json) + +The following table defines the top-level fields from the definitions file: + +| Field | Contents | +| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `TYPES` | Map of data types to their "type code" for constructing field IDs and sorting fields in canonical order. Codes below 1 should not appear in actual data; codes above 10000 represent special "high-level" object types such as "Transaction" that cannot be serialized inside other objects. See the Type List for details of how to serialize each type. | +| `LEDGER_ENTRY_TYPES` | Map of ledger objects to their data type. These appear in ledger state data, and in the "affected nodes" section of processed transactions' metadata. | +| `FIELDS` | A sorted array of tuples representing all fields that may appear in transactions, ledger objects, or other data. The first member of each tuple is the string name of the field and the second member is an object with that field's properties. (See the "Field properties" table below for definitions of those fields.) | +| `TRANSACTION_RESULTS` | Map of transaction result codes to their numeric values. Result types not included in ledgers have negative values; `tesSUCCESS` has numeric value 0; `tec`-class codes represent failures that are included in ledgers. | +| `TRANSACTION_TYPES` | Map of all transaction types to their numeric values. | + +For purposes of serializing transactions for signing and submitting, the `FIELDS`, `TYPES`, and `TRANSACTION_TYPES` fields are necessary. + +The field definition objects in the `FIELDS` array have the following fields: + +| Field | Type | Contents | +| ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `nth` | Number | The field code of this field, for use in constructing its Field ID and ordering it with other fields of the same data type. | +| `isVLEncoded` | Boolean | If `true`, this field is length-prefixed. | +| `isSerialized` | Boolean | If `true`, this field should be encoded into serialized binary data. When this field is `false`, the field is typically reconstructed on demand rather than stored. | +| `isSigningField` | Boolean | If `true` this field should be serialized when preparing a transaction for signing. If `false`, this field should be omitted from the data to be signed. (It may not be part of transactions at all.) | +| `type` | String | The internal data type of this field. This maps to a key in the `TYPES` map, which gives the type code for this field. | + +#### Field IDs + +[\[Source - Encoding\]](https://github.com/seelabs/rippled/blob/cecc0ad75849a1d50cc573188ad301ca65519a5b/src/ripple/protocol/impl/Serializer.cpp#L117-L148) [\[Source - Decoding\]](https://github.com/seelabs/rippled/blob/cecc0ad75849a1d50cc573188ad301ca65519a5b/src/ripple/protocol/impl/Serializer.cpp#L484-L509) + +When you combine a field's type code and field code, you get the field's unique identifier, which is prefixed before the field in the final serialized blob. The size of the Field ID is one to three bytes depending on the type code and field codes it combines. See the following table: + +| | Type Code < 16 | Type Code >= 16 | +| -------------------- | -------------- | --------------- | +| **Field Code < 16** | | | +| **Field Code >= 16** | | | + +When decoding, you can tell how many bytes the field ID is by which bits **of the first byte** are zeroes. This corresponds to the cases in the above table: + +| | High 4 bits are nonzero | High 4 bits are zero | +| -------------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| **Low 4 bits are nonzero** | 1 byte: high 4 bits define type; low 4 bits define field. | 2 bytes: low 4 bits of the first byte define field; next byte defines type | +| **Low 4 bits are zero** | 2 bytes: high 4 bits of the first byte define type; low 4 bits of first byte are 0; next byte defines field | 3 bytes: first byte is `0x00`, second byte defines type; third byte defines field | + +**Caution:** Even though the Field ID consists of the two elements that are used to sort fields, you should not sort by the serialized Field ID itself, because the byte structure of the Field ID changes the sort order. + +#### Length Prefixing + +Some types of variable-length fields are prefixed with a length indicator. `Blob` fields (containing arbitrary binary data) are one such type. For a list of which types are length-prefixed, see the Type List table. + +**Note:** Some types of fields that vary in length are not length-prefixed. Those types have other ways of indicating the end of their contents. + +The length prefix consists of one to three bytes indicating the length of the field immediately after the type prefix and before the contents. + +* If the field contains 0 to 192 bytes of data, the first byte defines the length of the contents, then that many bytes of data follow immediately after the length byte. +* If the field contains 193 to 12480 bytes of data, the first two bytes indicate the length of the field with the following formula: + + ``` + 193 + ((byte1 - 193) * 256) + byte2 + ``` +* If the field contains 12481 to 918744 bytes of data, the first three bytes indicate the length of the field with the following formula: + + ``` + 12481 + ((byte1 - 241) * 65536) + (byte2 * 256) + byte3 + ``` +* A length-prefixed field cannot contain more than 918744 bytes of data. + +When decoding, you can tell from the value of the first length byte whether there are 0, 1, or 2 additional length bytes: + +* If the first length byte has a value of 192 or less, then that's the only length byte and it contains the exact length of the field contents in bytes. +* If the first length byte has a value of 193 to 240, then there are two length bytes. +* If the first length byte has a value of 241 to 254, then there are three length bytes. + +### Canonical Field Order + +All fields in a transaction are sorted in a specific order based first on the field's type (specifically, a numeric "type code" assigned to each type), then on the field itself (a "field code"). (Think of it as sorting by family name, then given name, where the family name is the field's type and the given name is the field itself.) + +#### Type Codes + +Each field type has an arbitrary type code, with lower codes sorting first. These codes are defined in [`SField.h`](https://github.com/Xahau/xahaud/blob/master/src/ripple/protocol/SField.h#L57-L74). + +For example, [UInt32 has type code 2](https://github.com/Xahau/xahaud/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/SField.h#L59), so all UInt32 fields come before all [Amount fields, which have type code 6](https://github.com/Xahau/xahaud/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/SField.h#L63). + +The definitions file lists the type codes for each type in the `TYPES` map. + +#### Field Codes + +Each field has a field code, which is used to sort fields that have the same type as one another, with lower codes sorting first. These fields are defined in [`SField.cpp`](https://github.com/Xahau/xahaud/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L72-L266). + +For example, the `Account` field of a \[Payment transaction]\[] [has sort code 1](https://github.com/Xahau/xahaud/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L219), so it comes before the `Destination` field which [has sort code 3](https://github.com/Xahau/xahaud/blob/72e6005f562a8f0818bc94803d222ac9345e1e40/src/ripple/protocol/impl/SField.cpp#L221). + +Field codes are reused for fields of different field types, but fields of the same type never have the same field code. When you combine the type code with the field code, you get the field's unique Field ID. + +### Type List + +Transaction instructions may contain fields of any of the following types: + +| Type Name | Type Code | Bit Length | Length-prefixed? | Description | +| --------- | --------- | ---------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| AccountID | 8 | 160 | Yes | The unique identifier for an account. | +| Amount | 6 | 64 or 384 | No | An amount of XRP or tokens. The length of the field is 64 bits for XRP or 384 bits (64+160+160) for tokens. | +| Blob | 7 | Variable | Yes | Arbitrary binary data. One important such field is `TxnSignature`, the signature that authorizes a transaction. | +| Hash128 | 4 | 128 | No | A 128-bit arbitrary binary value. The only such field is `EmailHash`, which is intended to store the MD-5 hash of an account owner's email for purposes of fetching a [Gravatar](https://www.gravatar.com/). | +| Hash160 | 17 | 160 | No | A 160-bit arbitrary binary value. This may define a currency code or issuer. | +| Hash256 | 5 | 256 | No | A 256-bit arbitrary binary value. This usually represents the "SHA-512Half" hash of a transaction, ledger version, or ledger data object. | +| PathSet | 18 | Variable | No | A set of possible payment paths for a cross-currency payment. | +| STArray | 15 | Variable | No | An array containing a variable number of members, which can be different types depending on the field. Two cases of this include memos and lists of signers used in multi-signing. | +| STIssue | 24 | 160 or 320 | No | An asset definition, XRP or a token, with no quantity. | +| STObject | 14 | Variable | No | An object containing one or more nested fields. | +| UInt8 | 16 | 8 | No | An 8-bit unsigned integer. | +| UInt16 | 1 | 16 | No | A 16-bit unsigned integer. The `TransactionType` is a special case of this type, with specific strings mapping to integer values. | +| UInt32 | 2 | 32 | No | A 32-bit unsigned integer. The `Flags` and `Sequence` fields on all transactions are examples of this type. | + +In addition to all of the above field types, the following types may appear in other contexts, such as ledger objects and transaction metadata: + +| Type Name | Type Code | Length-prefixed? | Description | +| ----------- | --------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Transaction | 10001 | No | A "high-level" type containing an entire transaction. | +| LedgerEntry | 10002 | No | A "high-level" type containing an entire ledger object. | +| Validation | 10003 | No | A "high-level" type used in peer-to-peer communications to represent a validation vote in the consensus process. | +| Metadata | 10004 | No | A "high-level" type containing metadata for one transaction. | +| UInt64 | 3 | No | A 64-bit unsigned integer. This type does not appear in transaction instructions, but several ledger objects use fields of this type. | +| Vector256 | 19 | Yes | This type does not appear in transaction instructions, but the Amendments ledger object's `Amendments` field uses this to represent which amendments are currently enabled. | + +#### AccountID Fields + +Fields of this type contain the 160-bit identifier for an XRP Ledger account. In JSON, these fields are represented as \[base58]\[] XRP Ledger "addresses", with additional checksum data so that typos are unlikely to result in valid addresses. (This encoding, sometimes called "Base58Check", prevents accidentally sending money to the wrong address.) The binary format for these fields does not contain any checksum data nor does it include the `0x00` "type prefix" used in address base58 encoding. (However, since the binary format is used mostly for signed transactions, a typo or other error in transcribing a signed transaction would invalidate the signature, preventing it from sending money.) + +AccountIDs that appear as stand-alone fields (such as `Account` and `Destination`) are length-prefixed despite being a fixed 160 bits in length. As a result, the length indicator for these fields is always the byte `0x14`. AccountIDs that appear as children of special fields (Amount `issuer` and PathSet `account`) are _not_ length-prefixed. + +#### Amount Fields + +The "Amount" type is a special field type that represents an amount of currency, either XAH or a token. This type consists of two sub-types: + +* XAH + + XAH is serialized as a 64-bit unsigned integer (big-endian order), except that the most significant bit is always 0 to indicate that it's XAH, and the second-most-significant bit is `1` to indicate that it is positive. Since the maximum amount of XAH (1017 drops) only requires 57 bits, you can calculate XAH serialized format by taking standard 64-bit unsigned integer and performing a bitwise-OR with `0x4000000000000000`. +* **Tokens** + + Tokens consist of three segments in order: + + 1. 64 bits indicating the amount in the token amount format. The first bit is `1` to indicate that this is not XAH. + 2. 160 bits indicating the currency code. The standard API converts 3-character codes such as "USD" into 160-bit codes using the standard currency code format, but custom 160-bit codes are also possible. + 3. 160 bits indicating the issuer's Account ID. (See also: Account Address Encoding) + +You can tell which of the two sub-types it is based on the first bit: `0` for XAH; `1` for tokens. + +The following diagram shows the serialization formats for both XAH amounts and token amounts: + +include_svg("img/serialization-amount.svg", 'XAH amounts have a "not XAH" bit, a sign bit, and 62 bits of precision. Token amounts consist of a "not XRP" bit, a sign bit, an exponent (8 bits), significant digits (54 bits), currency code (160 bits), and issuer (160 bits).') + +**Token Amount Format** + +[\[Source\]](https://github.com/Xahau/xahaud/blob/35fa20a110e3d43ffc1e9e664fc9017b6f2747ae/src/ripple/protocol/impl/STAmount.cpp) + +include_svg("img/currency-number-format.svg", "Token Amount Format diagram") + +Xahau uses 64 bits to serialize the numeric amount of a (fungible) token. (In JSON format, the numeric amount is the `value` field of a currency amount object.) In binary format, the numeric amount consists of a "not XAH" bit, a sign bit, significant digits, and an exponent, in order: + +1. The first (most significant) bit for a token amount is `1` to indicate that it is not an XAH amount. (XAH amounts always have the most significant bit set to `0` to distinguish them from this format.) +2. The sign bit indicates whether the amount is positive or negative. Unlike standard [two's complement](https://en.wikipedia.org/wiki/Two's_complement) integers, `1` indicates **positive** in Xahau format, and `0` indicates negative. +3. The next 8 bits represent the exponent as an unsigned integer. The exponent indicates the scale (what power of 10 the significant digits should be multiplied by) in the range -96 to +80 (inclusive). However, when serializing, we add 97 to the exponent to make it possible to serialize as an unsigned integer. Thus, a serialized value of `1` indicates an exponent of `-96`, a serialized value of `177` indicates an exponent of 80, and so on. +4. The remaining 54 bits represent the significant digits (sometimes called a _mantissa_) as an unsigned integer. When serializing, this value is normalized to the range 1015 (`1000000000000000`) to 1016-1 (`9999999999999999`) inclusive, except for the special case of the value 0. In the special case for 0, the sign bit, exponent, and significant digits are all zeroes, so the 64-bit value is serialized as `0x8000000000000000000000000000000000000000`. + +The numeric amount is serialized alongside the currency code and issuer to form a full token amount. + +**Currency Codes** + +At a protocol level, currency codes in Xahau are arbitrary 160-bit values, except the following values have special meaning: + +* The currency code `0x0000000000000000000000005852500000000000` is **always disallowed**. (This is the code "XAH" in the "standard format".) +* The currency code `0x0000000000000000000000000000000000000000` (all zeroes) is **generally disallowed**. Usually, XAH amounts are not specified with currency codes. However, this code is used to indicate XAH in rare cases where a field must specify a currency code for XAH. + +The `xahaud` APIs support a **standard format** for translating three-character ASCII codes to 160-bit hex values as follows: + +include_svg("img/currency-code-format.svg", "Standard Currency Code Format") + +1. The first 8 bits must be `0x00`. +2. The next 88 bits are reserved, and should be all `0`'s. +3. The next 24 bits represent 3 characters of ASCII. Ripple recommends using [ISO 4217](https://www.xe.com/iso4217.php) codes, or popular pseudo-ISO 4217 codes such as "BTC". However, any combination of the following characters is permitted: all uppercase and lowercase letters, digits, as well as the symbols `?`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `<`, `>`, `(`, `)`, `{`, `}`, `[`, `]`, and `|`. The currency code XAH (all-uppercase) is reserved for XAH and cannot be used by tokens. +4. The next 40 bits are reserved and should be all `0`'s. + +The **nonstandard format** is any 160 bits of data as long as the first 8 bits are not `0x00`. + +#### Array Fields + +Some transaction fields, such as `SignerEntries` (in \[SignerListSet transactions]\[]) and `Memos`, are arrays of objects (called the "STArray" type). + +Arrays contain several object fields in their native binary format in a specific order. In JSON, each array member is a JSON "wrapper" object with a single field, which is the name of the member object field. The value of that field is the ("inner") object itself. + +In the binary format, each member of the array has a Field ID prefix (based on the single key of the wrapper object) and contents (comprising the inner object, serialized as an object). To mark the end of an array, append an item with a "Field ID" of `0xf1` (the type code for array with field code of 1) and no contents. + +The following example shows the serialization format for an array (the `SignerEntries` field): + +include_svg("img/serialization-array.svg", 'Array field ID, followed by the Field ID and contents of each array element, followed by the "Array end" field ID') + +#### Blob Fields + +The Blob type is a length-prefixed field with arbitrary data. Two common fields that use this type are `SigningPubKey` and `TxnSignature`, which contain (respectively) the public key and signature that authorize a transaction to be executed. + +Blob fields have no further structure to their contents, so they consist of exactly the amount of bytes indicated in the variable-length encoding, after the Field ID and length prefixes. + +#### Hash Fields + +Xahau has several "hash" types: Hash128, Hash160, and Hash256. These fields contain arbitrary binary data of the given number of bits, which may or may not represent the result of a hash operation. + +All such fields are serialized as the specific number of bits, with no length indicator, in big-endian byte order. + +#### Issue Fields + +Some fields specify a _type_ of asset, which could be XAH or a fungible token, without an amount. These fields have consist of one or two 160-bit segments in order: + +1. The first 160 bits are the currency code of the asset. For XAH, this is all 0's. +2. If the first 160 bits are all 0's (the asset is XAH), the field ends there. Otherwise, the asset is a token and the next 160 bits are the AccountID of the token issuer. + +#### Object Fields + +Some fields, such as `SignerEntry` (in \[SignerListSet transactions]\[]), and `Memo` (in `Memos` arrays) are objects (called the "STObject" type). The serialization of objects is very similar to that of arrays, with one difference: **object members must be placed in canonical order** within the object field, where array fields have an explicit order already. + +The canonical field order of object fields is the same as the canonical field order for all top-level fields, but the members of the object must be sorted within the object. After the last member, there is an "Object end" Field ID of `0xe1` with no contents. + +The following example shows the serialization format for an object (a single `Memo` object in the `Memos` array). + +include_svg("img/serialization-object.svg", 'Object field ID, followed by the Object ID and contents of each object member in canonical order, followed by the "Object end" field ID') + +#### PathSet Fields + +The `Paths` field of a cross-currency \[Payment transaction]\[] is a "PathSet", represented in JSON as an array of arrays. For more information on what paths are used for, see Paths. + +A PathSet is serialized as **1 to 6** individual paths in sequence[\[Source\]](https://github.com/Xahau/xahaud/blob/4cff94f7a4a05302bdf1a248515379da99c5bcd4/src/ripple/app/tx/impl/Payment.h#L35-L36). Each complete path is followed by a byte that indicates what comes next: + +* `0xff` indicates another path follows +* `0x00` indicates the end of the PathSet + +Each path consists of **1 to 8** path steps in order[\[Source\]](https://github.com/Xahau/xahaud/blob/4cff94f7a4a05302bdf1a248515379da99c5bcd4/src/ripple/app/tx/impl/Payment.h#L38-L39). Each step starts with a **type** byte, followed by one or more fields describing the path step. The type indicates which fields are present in that path step through bitwise flags. (For example, the value `0x30` indicates changing both currency and issuer.) If more than one field is present, the fields are always placed in a specific order. + +The following table describes the possible fields and the bitwise flags to set in the type byte to indicate them: + +| Type Flag | Field Present | Field Type | Bit Size | Order | +| --------- | ------------- | ------------- | -------- | ----- | +| `0x01` | `account` | AccountID | 160 bits | 1st | +| `0x10` | `currency` | Currency Code | 160 bits | 2nd | +| `0x20` | `issuer` | AccountID | 160 bits | 3rd | + +Some combinations are invalid; see Path Specifications for details. + +The AccountIDs in the `account` and `issuer` fields are presented _without_ a length prefix. When the `currency` is XRP, the currency code is represented as 160 bits of zeroes. + +Each step is followed directly by the next step of the path. As described above, the last step of a path is followed by either `0xff` (if another path follows) or `0x00` (if this ends the last path). + +The following example shows the serialization format for a PathSet: + +include_svg("img/serialization-pathset.svg", "PathSet is several paths each followed by a continue or end byte; each path is several path steps consisting of a type byte and one or more 160-bit fields based on the type byte") + +#### UInt Fields + +Xahau has several unsigned integer types: UInt8, UInt16, UInt32, and UInt64. All of these are standard big-endian binary unsigned integers with the specified number of bits. + +When representing these fields in JSON objects, most are represented as JSON numbers by default. One exception is UInt64, which is represented as a string because some JSON decoders may try to represent these integers as 64-bit "double precision" floating point numbers, which cannot represent all distinct UInt64 values with full precision. + +Another special case is the `TransactionType` field. In JSON, this field is conventionally represented as a string with the name of the transaction type, but in binary, this field is a UInt16. The `TRANSACTION_TYPES` object in the definitions file maps these strings to specific numeric values. diff --git a/src/content/docs/docs/protocol-reference/data-types/base-58-encodings.mdx b/src/content/docs/docs/protocol-reference/data-types/base-58-encodings.mdx new file mode 100644 index 0000000..6e95736 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/data-types/base-58-encodings.mdx @@ -0,0 +1,24 @@ +--- +title: Base 58 Encodings +--- +Xahau APIs often use a "base58" encoding with a checksum (sometimes called "Base58Check") to represent account addresses and other types of values related to cryptographic keys. This encoding is the same as [the one used for Bitcoin addresses](https://en.bitcoin.it/wiki/Base58Check_encoding), except that Xahau uses the following dictionary: `rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz`. + +Xahau prefixes different types of values with a specific 8-bit number before encoding them to distinguish between different data types. With the arrangement of characters in Xahau's base58 dictionary, the result is that the base58 representations for different types of encoded values start with specific letters by type. + +The following table lists all the encodings Xahau uses: + +| Data Type | Starts With | Type Prefix | Content size¹ | Maximum characters | +| ---------------------------------------- | ----------- | ----------- | ------------- | ------------------ | +| Account address | r | `0x00` | 20 bytes | 35 | +| Account public key | a | `0x23` | 33 bytes | 53 | +| Seed value (for secret keys) | s | `0x21` | 16 bytes | 29 | +| Validation public key or node public key | n | `0x1C` | 33 bytes | 53 | + +¹ Content size excludes the 1-byte type prefix. + +### See Also + +* Address Encoding - detailed information on address encoding +* Cryptographic Keys - types of cryptographic keys in Xahau and how they're used +* \[wallet_propose Reference]\[wallet_propose method] - API method for generating account keys +* \[validation_create Reference]\[validation_create method] - API method for generating validator keys diff --git a/src/content/docs/docs/protocol-reference/data-types/currency-formats.mdx b/src/content/docs/docs/protocol-reference/data-types/currency-formats.mdx new file mode 100644 index 0000000..92c5529 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/data-types/currency-formats.mdx @@ -0,0 +1,117 @@ +--- +title: Currency Formats +--- +Xahau has two kinds of digital asset: XAH and tokens. Both types have high precision, although their formats are different. + +### Comparison + +The following table summarizes some of the differences between XAH and tokens in Xahau: + +| XAH | Tokens | +| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------- | +| Has no issuer. | Always issued by a Xahau account. | +| Specified as a string. | Specified as an object. | +| Tracked in accounts. | Tracked in trust lines. | +| Can never be created; can only be destroyed. | Can be issued or redeemed freely. | +| Minimum value: `0`. (Cannot be negative.) | Minimum value: `-9999999999999999e80`. Minimum nonzero absolute value: `1000000000000000e-96`. | +| Maximum value `100000000000` (1011) XAH. That's `100000000000000000` (1017) "drops". | Maximum value `9999999999999999e80`. | +| Precise to the nearest "drop" (0.000001 XAH) | 15 decimal digits of precision. | +| Can't be frozen. | The issuer can freeze balances. | +| No transfer fees; XAH-to-XAH payments are always direct. | Can take indirect paths with each issuer charging a percentage transfer fee. | +| Can be used in Payment Channels and Escrow. | Can be used with Payment Channels or Escrow. | + +For more information, see What is XAH? and Tokens. + +### Specifying Currency Amounts + +Use the appropriate format for the type of currency you want to specify: + +* XAH Amounts +* Token Amounts + +#### XAH Amounts + +To specify an amount of XAH, use a String Number indicating _drops_ of XAH, where each drop is equal to 0.000001 XAH. For example, to specify 13.1 XAH: + +``` +"13100000" +``` + +**Do not specify XAH as an object.** + +XAH amounts cannot be negative. + +#### Token Amounts + +To specify an amount of a (fungible) token, use an Amount object. This is a JSON object with three fields: + +| `Field` | Type | Description | +| ---------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `currency` | String - Currency Code | Arbitrary currency code for the token. Cannot be XAH. | +| `value` | String Number | Quoted decimal representation of the amount of the token. This can include scientific notation, such as `1.23e11` meaning 123,000,000,000. Both `e` and `E` may be used. This can be negative when displaying balances, but negative values are disallowed in other contexts such as specifying how much to send. | +| `issuer` | String | Generally, the account that issues this token. In special cases, this can refer to the account that holds the token instead (for example, in a Clawback transaction). | + +**Caution:** These field names are case-sensitive. + +For example, to represent $153.75 US dollars issued by account `r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59`, you would specify: + +```json +{ + "currency": "USD", + "value": "153.75", + "issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59" +} +``` + +#### Specifying Without Amounts + +In some cases, you need to define an asset (which could be XAH or a token) without a specific amount, such as when defining an order book in the decentralized exchange. + +To describe a token without an amount, specify it as a currency object, but omit the `value` field. For example: + +```json +{ + "currency": "TST", + "issuer": "rP9jPyP5kyvFRb6ZiRghAGw5u8SGAmU4bd" +} +``` + +To describe XAH without an amount, specify it as a JSON object with _only_ a `currency` field. Never include an `issuer` field for XAH. For example: + +```json +{ + "currency": "XAH" +} +``` + +### String Numbers + +### XAH Precision + +XAH has the same precision as a 64-bit unsigned integer where each unit is equivalent to 0.000001 XAH. It uses integer math, so that any amount less than a full drop is rounded down. + +### Token Precision + +Tokens can represent a wide variety of assets, including those typically measured in very small or very large denominations. This format uses significant digits and a power-of-ten exponent in a similar way to scientific notation. The format supports positive and negative significant digits and exponents within the specified range. Unlike typical floating-point representations of non-whole numbers, this format uses integer math for all calculations, so it always maintains 15 decimal digits of precision. Multiplication and division have adjustments to compensate for over-rounding in the least significant digits. + +When sending token amounts in Xahau's peer-to-peer network, servers serialize the amount to a 64-bit binary value. + +**Tip:** For tokens that should not be divisible at all, see Non-Fungible Tokens (NFTs). + +### Currency Codes + +#### Standard Currency Codes + +The standard format for currency codes is a three-character string such as `USD`. This is intended for use with [ISO 4217 Currency Codes](https://www.xe.com/iso4217.php). The following rules apply: + +* Currency codes must be exactly 3 ASCII characters in length. The following characters are permitted: all uppercase and lowercase letters, digits, as well as the symbols `?`, `!`, `@`, `#`, `$`, `%`, `^`, `&`, `*`, `<`, `>`, `(`, `)`, `{`, `}`, `[`, `]`, and `|`. +* Currency codes are case-sensitive. +* The currency code XAH (all-uppercase) is disallowed. Real XAH typically does not use a currency code in Xahau's protocol. + +At the protocol level, this format is serialized into a 160-bit binary value starting with `0x00`. + +#### Nonstandard Currency Codes + +You can also use a 160-bit (40-character) hexadecimal string such as `015841551A748AD2C1F76FF6ECB0CCCD00000000` as the currency code. To prevent this from being treated as a "standard" currency code, the first 8 bits MUST NOT be `0x00`. + +**Deprecated:** Some previous versions of [ripple-lib](https://github.com/XRPLF/xrpl.js) supported an "interest-bearing" or "demurraging" currency code type. These codes have the first 8 bits `0x01`. Demurraging / interest-bearing currencies are no longer supported, but you may find them in ledger data. For more information, see Demurrage. diff --git a/src/content/docs/docs/protocol-reference/data-types/index.mdx b/src/content/docs/docs/protocol-reference/data-types/index.mdx new file mode 100644 index 0000000..62977c6 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/data-types/index.mdx @@ -0,0 +1,105 @@ +--- +title: Data Types +--- +Different types of objects are uniquely identified in different ways: + +Accounts are identified by their Address, for example `"r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59"`. Addresses always start with "r". Many `rippled` methods also accept a hexadecimal representation. + +Transactions are identified by a Hash of the transaction's binary format. You can also identify a transaction by its sending account and Sequence Number. + +Each closed Ledger has a Ledger Index and a Hash value. When \[Specifying Ledgers]\[] you can use either one. + +### Addresses + +### Hashes + +#### Hash Prefixes + +[\[Source\]](https://github.com/Xahau/xahaud/blob/master/src/ripple/protocol/HashPrefix.h) + +In many cases, Xahau prefixes an object's binary data with a 4-byte code before calculating its hash, so that objects of different types have different hashes even if their binary formats are the same. The existing 4-byte codes are structured as three alphabetic characters, encoded as ASCII, followed by a zero byte. + +Some types of hash appear in API requests and responses. Others are only calculated as the first step of signing a certain type of data, or calculating a higher-level hash. The following table shows all 4-byte hash prefixes Xahau uses: + +| Object Type | API Fields | Hash Prefix (Hex) | Hash Prefix (Text) | +| ------------------------------------- | -------------------------------- | ----------------- | ------------------ | +| Consensus proposal | N/A | `0x50525000` | `PRP\0` | +| Ledger Version | `ledger_hash` | `0x4C575200` | `LWR\0` | +| Ledger state data | `account_state` in ledger header | `0x4D4C4E00` | `MLN\0` | +| Ledger data inner node | N/A | `0x4D494E00` | `MIN\0` | +| Ledger data inner node (SHAMapv2) | N/A | `0x494E5200` | `INR\0` | +| Payment Channel Claim | N/A | `0x434C4D00` | `CLM\0` | +| Signed Transaction | `hash` of transactions | `0x54584E00` | `TXN\0` | +| Transaction with metadata | N/A | `0x534E4400` | `SND\0` | +| Unsigned Transaction (Single-signing) | N/A | `0x53545800` | `STX\0` | +| Unsigned Transaction (Multi-signing) | N/A | `0x534D5400` | `SMT\0` | +| Validation vote | N/A | `0x56414C00` | `VAL\0` | +| Validator manifest | N/A | `0x4D414E00` | `MAN\0` | + +Ledger objects IDs are calculated in a similar way, but they use a 2-byte prefix called a "space key" instead of a prefix in the form described here. + +### Account Sequence + +### Ledger Index + +#### Specifying Ledgers + +Many API methods require you to specify an instance of the ledger, with the data retrieved being considered up-to-date as of that particular version of the shared ledger. The commands that accept a ledger version all work the same way. There are three ways you can specify which ledger you want to use: + +1. Specify a ledger by its Ledger Index in the `ledger_index` parameter. Each closed ledger has a ledger index that is 1 higher than the previous ledger. (The very first ledger had ledger index 1.) + + ``` + "ledger_index": 61546724 + ``` +2. Specify a ledger by its Hash value in the `ledger_hash` parameter. + + ``` + "ledger_hash": "8BB204CE37CFA7A021A16B5F6143400831C4D1779E6FE538D9AC561ABBF4A929" + ``` +3. Specify a ledger by one of the following shortcuts, in the `ledger_index` parameter: + * `validated` for the most recent ledger that has been validated by consensus + + ``` + "ledger_index": "validated" + ``` + * `closed` for the most recent ledger that has been closed for modifications and proposed for validation + * `current` for the server's current working version of the ledger. + +There is also a deprecated `ledger` parameter which accepts any of the above three formats. _Do not_ use this parameter; it may be removed without further notice. + +If you do not specify a ledger, the server decides which ledger to use to serve the request. By default, the server chooses the `current` (in-progress) ledger. In Reporting Mode, the server uses the most recent validated ledger instead. Do not provide more than one field specifying ledgers. + +**Note:** Do not rely on the default behavior for specifying a ledger; it is subject to change. Always specify a ledger version in the request if you can. + +Reporting Mode does not record ledger data until it has been validated. If you make a request to a Reporting Mode server for the `current` or `closed` ledger, the server forwards the request to a P2P Mode server. If you request a ledger index or hash that is not validated, a Reporting Mode server responds with a `lgrNotFound` error. + +### Specifying Currency Amounts + +There are two kinds of currencies in Xahau: XAH and tokens. These two types of currencies are specified in different formats, with different precision and rounding behavior. + +Some fields, such as the destination `Amount` of a \[Payment transaction]\[], can be either type. Some fields only accept XAH specifically, such as the `Fee` field (transaction cost). + +XAH is specified as a string containing an integer number of "drops" of XAH, where 1 million drops equals 1 XAH. Tokens are instead specified as an object with fields for the decimal amount, currency code, and issuer. For example: + +* **XAH** - To specify an `Amount` field with a value of 13.1 XAH: + + ``` + "Amount": "13100000" + ``` +* **Token** - To specify an `Amount` field with a value of 13.1 FOO issued by or to `rf1B...`: + + ``` + "Amount": { + "value": "13.1", + "currency": "FOO", + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + } + ``` + +For more information, see Currency Formats. + +### Specifying Time + +The `xahaud` server and its APIs represent time as an unsigned integer. This number measures the number of seconds since the "Ripple Epoch" of January 1, 2000 (00:00 UTC). This is like the way the [Unix epoch](http://en.wikipedia.org/wiki/Unix_time) works, except the Ripple Epoch is 946684800 seconds after the Unix Epoch. + +Don't convert Ripple Epoch times to UNIX Epoch times in 32-bit variables: this could lead to integer overflows. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/index.mdx b/src/content/docs/docs/protocol-reference/ledger-data/index.mdx new file mode 100644 index 0000000..7893622 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/index.mdx @@ -0,0 +1,20 @@ +--- +title: Ledger Data +--- +Each ledger version in the XRP Ledger is made up of three parts: + +* **Ledger Header**: Metadata about this ledger version itself. +* **Transaction Set**: All the transactions that were executed to create this ledger version. +* **State Data**: The complete record of objects representing accounts, settings, and balances as of this ledger version. (This is also called the "account state".) + +### State Data + +Each ledger version's state data is a set of **ledger objects**, sometimes called _ledger entries_, which collectively represent all settings, balances, and relationships at a given point in time. To store or retrieve an object in the state data, the protocol uses that object's unique [**Ledger Object ID**](ledger-object-ids.md). + +In the peer protocol, ledger objects have a [canonical binary format](../binary-format.md). In `xahaud` APIs, ledger objects are represented as JSON objects. + +A ledger object's data fields depend on the type of object; the Xahau Ledger supports the following types: + +* [Ledger Header](ledger-header.md) +* [Ledger Entry Common Fields](ledger-object-ids.md) +* [Ledger Entry Types](ledger-objects-types/) diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-header.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-header.mdx new file mode 100644 index 0000000..f97fb35 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-header.mdx @@ -0,0 +1,31 @@ +--- +title: Ledger Header +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/ledger/ReadView.h#L71) + +Every ledger version has a unique header that describes the contents. You can look up a ledger's header information with the \[ledger method]\[]. The contents of the ledger header are as follows: + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ----------------------- | --------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ledger_index` | String | UInt32 | The \[ledger index]\[Ledger Index] of the ledger. Some API methods display this as a quoted integer; some display it as a native JSON number. | +| `ledger_hash` | String | Hash256 | The \[SHA-512Half]\[] of this ledger version. This serves as a unique identifier for this ledger and all its contents. | +| `account_hash` | String | Hash256 | The \[SHA-512Half]\[] of this ledger's state tree information. | +| `close_time` | Number | UInt32 | The approximate time this ledger version closed, as the number of seconds since the Ripple Epoch of 2000-01-01 00:00:00. This value is rounded based on the `close_time_resolution`. | +| `closed` | Boolean | Boolean | If `true`, this ledger version is no longer accepting new transactions. (However, unless this ledger version is validated, it might be replaced by a different ledger version with a different set of transactions.) | +| `parent_hash` | String | Hash256 | The `ledger_hash` value of the previous ledger version that is the direct predecessor of this one. If there are different versions of the previous ledger index, this indicates from which one the ledger was derived. | +| `total_coins` | String | UInt64 | The total number of \[drops of XAH]\[] owned by accounts in the ledger. This omits XAH that has been destroyed by transaction fees. The actual amount of XAH in circulation is lower because some accounts are "black holes" whose keys are not known by anyone. | +| `transaction_hash` | String | Hash256 | The \[SHA-512Half]\[] of the transactions included in this ledger. | +| `close_time_resolution` | Number | Uint8 | An integer in the range \[2,120] indicating the maximum number of seconds by which the `close_time` could be rounded. | +| `closeFlags` | (Omitted) | UInt8 | A bit-map of flags relating to the closing of this ledger. | + +### Ledger Index + +### Close Flags + +The ledger has only one flag defined for `closeFlags`: **`sLCF_NoConsensusTime`** (value `1`). If this flag is enabled, it means that validators had different close times for the ledger, but built otherwise the same ledger, so they declared consensus while "agreeing to disagree" on the close time. In this case, official `close_time` value of the ledger is 1 second after that of the parent ledger. + +The `closeFlags` field is not included in any JSON representations of a ledger, but is included in the binary representation of a ledger, and is one of the fields that determine the ledger's hash. + +### See Also + +For ledger basics, see Ledgers. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-object-ids.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-object-ids.mdx new file mode 100644 index 0000000..50be57d --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-object-ids.mdx @@ -0,0 +1,23 @@ +--- +title: Ledger Object IDs +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/Indexes.cpp) + +Each object in a ledger's state data has a unique ID. The ID is derived by hashing important contents of the object, along with a [namespace identifier](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/LedgerFormats.h#L99). The ledger object type determines which namespace identifier to use and which contents to include in the hash. This ensures every ID is unique. To calculate the hash, `xahaud` uses SHA-512 and then truncates the result to the first 256 bits. This algorithm, informally called **SHA-512Half**, provides an output that has comparable security to SHA-256, but runs faster on 64-bit processors. + +Generally, a ledger object's ID is returned as the `index` field in JSON, at the same level as the object's contents. In transaction metadata, the ledger object's ID in JSON is `LedgerIndex`. + +**Tip:** The `index` or `LedgerIndex` field of an object in the ledger is the ledger object ID. This is not the same as a \[ledger index]\[]. + +include_svg("img/ledger-object-ids.svg", "Diagram: xahaud uses SHA-512Half to generate IDs for ledger objects. The space key prevents IDs for different object types from colliding.") + +### Flags + +Flags are on/off settings, which are represented as binary values that are combined into a single number using bitwise-OR operations. The bit values for the flags in ledger entries are different than the values used to enable or disable those flags in a transaction. Ledger state flags have names that begin with **`lsf`**. + +The possible values for the flags field vary based on the ledger entry type. Some ledger entry types have no flags defined. In these cases, the `Flags` field always has the value `0`. + +### See Also + +* For more information how Xahau creates and uses hashes, see Hashes. +* For ledger basics, see Ledgers. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/accountroot.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/accountroot.mdx new file mode 100644 index 0000000..9f15d34 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/accountroot.mdx @@ -0,0 +1,81 @@ +--- +title: AccountRoot +--- +[\[Source\]](https://github.com/Xahau/xahaud/blob/264280edd79b7f764536e02459f33f66a59c0531/src/ripple/protocol/impl/LedgerFormats.cpp#L36-L60) + +An `AccountRoot` ledger entry type describes a single account, its settings, and XAH balance. + +### Example JSON + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "AccountTxnID": "0D5FB50FA65C9FE1538FD7E398FFFE9D1908DFA4576D8D7A020040686F93C77D", + "AccountIndex": "59", + "Balance": "148446663", + "Domain": "6D64756F31332E636F6D", + "EmailHash": "98B4375E1D753E5B91627516F6D70977", + "Flags": 8388608, + "LedgerEntryType": "AccountRoot", + "MessageKey": "0000000000000000000000070000000300", + "OwnerCount": 3, + "PreviousTxnID": "0D5FB50FA65C9FE1538FD7E398FFFE9D1908DFA4576D8D7A020040686F93C77D", + "PreviousTxnLgrSeq": 14091160, + "Sequence": 336, + "TransferRate": 1004999999, + "index": "13F1A95D7AAB7108D5CE7EEAF504B2894B8C674E6D68499076441C4837282BF8" +} +``` + +### Fields + +An `AccountRoot` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ---------------------- | --------- | ------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | Yes | The identifying (classic) address of this account. | +| `Sequence` | Number | UInt32 | Yes | The sequence number of the next valid transaction for this account. | +| `Balance` | String | Amount | No | The account's current \[XAH balance in drops]\[XAH, in drops], represented as a string. | +| `OwnerCount` | Number | UInt32 | Yes | The number of objects this account owns in the ledger, which contributes to its owner reserve. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `AccountTxnID` | String | Hash256 | No | The identifying hash of the transaction most recently sent by this account. This field must be enabled to use the `AccountTxnID` transaction field. To enable it, send an AccountSet transaction with the `asfAccountTxnID` flag enabled. | +| `RegularKey` | String | AccountID | No | The address of a key pair that can be used to sign transactions for this account instead of the master key. Use a \[SetRegularKey transaction]\[] to change this value. | +| `EmailHash` | String | Hash128 | No | The md5 hash of an email address. Clients can use this to look up an avatar through services such as [Gravatar](https://en.gravatar.com/). | +| `WalletLocator` | String | Hash256 | No | An arbitrary 256-bit value that users can set. | +| `WalletSize` | Number | UInt32 | No | Unused. (The code supports this field but there is no way to set it.) | +| `MessageKey` | String | Blob | No | A public key that may be used to send encrypted messages to this account. In JSON, uses hexadecimal. Must be exactly 33 bytes, with the first byte indicating the key type: `0x02` or `0x03` for secp256k1 keys, `0xED` for Ed25519 keys. | +| `TransferRate` | Number | UInt32 | No | A transfer fee to charge other users for sending currency issued by this account to each other. | +| `Domain` | String | Blob | No | A domain associated with this account. In JSON, this is the hexadecimal for the ASCII representation of the domain. [Cannot be more than 256 bytes in length.](https://github.com/Xahau/xahaud/blob/55dc7a252e08a0b02cd5aa39e9b4777af3eafe77/src/ripple/app/tx/impl/SetAccount.h#L34) | +| `TickSize` | Number | UInt8 | No | How many significant digits to use for exchange rates of Offers involving currencies issued by this address. Valid values are `3` to `15`, inclusive. _(Added by the \[TickSize amendment]\[].)_ | +| `TicketCount` | Number | UInt32 | No | How many Tickets this account owns in the ledger. This is updated automatically to ensure that the account stays within the hard limit of 250 Tickets at a time. This field is omitted if the account has zero Tickets. _(Added by the \[TicketBatch amendment]\[].)_ | +| `NFTokenMinter` | String | AccountID | No | Another account that can mint non-fungible tokens on behalf of this account. _(Added by the \[NonFungibleTokensV1_1 amendment]\[])_ | +| `MintedNFTokens` | Number | UInt32 | No | How many total non-fungible tokens have been minted by and on behalf of this account. _(Added by the \[NonFungibleTokensV1_1 amendment]\[])_ | +| `BurnedNFTokens` | Number | UInt32 | No | How many total of this account's issued non-fungible tokens have been burned. This number is always equal or less than `MintedNFTokens`. | +| `HookStateCount` | Number | UInt32 | No | The number of states on the Hook. | +| `HookNamespaces` | Array | Vector256 | No | A unique value to prevent state conflicts between multiple Hooks installed on the same XAHL account. | +| `RewardLgrFirst` | Number | UInt32 | No | The ledger number of the last ClaimReward transaction. | +| `RewardLgrLast` | Number | UInt32 | No | The ledger sequence number of the last transaction in or out of your account. | +| `RewardTime` | Number | UInt32 | No | The ledger time the last reward was claimed. | +| `RewardAccumulator` | String | UInt64 | No | The area under of the balance-time graph for your account since last ClaimReward transaction. | +| `FirstNFTokenSequence` | Number | UInt32 | No | The account's \[Sequence Number]\[] at the time it minted its first non-fungible-token. _(Added by the \[fixNFTokenRemint amendment]\[] :not_enabled:)_ | +| `ImportSequence` | Number | UInt32 | No | The current sequence number from the importing account on the XAHL Ledger. | +| `GovernanceFlags` | String | Hash256 | No | | +| `GovernanceMarks` | String | Hash256 | No | | +| `AccountIndex` | String | UInt64 | No | The account's \[Index Number]\[]. _(Added by the \[xahauGenesis amendment]\[] :enabled:)_ | +| `TouchCount` | String | UInt64 | No | An incrementing counter for every time the ledger entry is "touched". | + +### AccountRoot Flags + +There are several options which can be either enabled or disabled for an account. These options can be changed with an \[AccountSet transaction]\[]. In the ledger, flags are represented as binary values that can be combined with bitwise-or operations. The bit values for the flags in the ledger are different than the values used to enable or disable those flags in a transaction. Ledger flags have names that begin with **`lsf`**. + +fAccountRoot objects can have the following flag values: + +
Flag NameHex ValueDecimal ValueCorresponding AccountSet FlagDescription
lsfDefaultRipple0x008000008388608asfDefaultRippleEnable rippling on this addresses's trust lines by default. Required for issuing addresses; discouraged for others.
lsfDepositAuth0x0100000016777216asfDepositAuthThis account has DepositAuth enabled, meaning it can only receive funds from transactions it sends, and from preauthorized accounts. (Added by the [DepositAuth amendment][])
lsfDisableMaster0x001000001048576asfDisableMasterDisallows use of the master key to sign transactions for this account.
lsfDisallowIncomingCheck0x08000000134217728asfDisallowIncomingCheckThis account blocks incoming Checks.
lsfDisallowIncomingNFTokenOffer0x0400000067108864asfDisallowIncomingNFTokenOfferThis account blocks incoming NFTokenOffers.
lsfDisallowIncomingPayChan0x10000000268435456asfDisallowIncomingPayChanThis account blocks incoming Payment Channels.
lsfDisallowIncomingTrustline0x20000000536870912asfDisallowIncomingTrustlineThis account blocks incoming trust lines.
lsfDisallowIncomingRemit0x800000002147483648asfDisallowIncomingRemitThis account blocks incoming remit transactions.
lsfDisallowXRP0x00080000524288asfDisallowXRPClient applications should not send XAH to this account. (Advisory; not enforced by the protocol.)
lsfGlobalFreeze0x004000004194304asfGlobalFreezeAll assets issued by this account are frozen.
lsfNoFreeze0x002000002097152asfNoFreezeThis account cannot freeze trust lines connected to it. Once enabled, cannot be disabled.
lsfPasswordSpent0x0001000065536(None)This account has used its free SetRegularKey transaction.
lsfRequireAuth0x00040000262144asfRequireAuthThis account must individually approve other users for those users to hold this account's tokens.
lsfRequireDestTag0x00020000131072asfRequireDestRequires incoming payments to specify a Destination Tag.
lsfTshCollect0x0200000033554432asfTshCollectThe TSH pays for the execution of their own Hook Chain.
lsfURITokenIssuer0x0400000067108864asfURITokenIssuerThis account cannot be deleted after it has issued a URIToken.
+ +### AccountRoot ID Format + +The ID of an AccountRoot object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Account space key (`0x0061`) +* The AccountID of the account diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/amendments.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/amendments.mdx new file mode 100644 index 0000000..1145254 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/amendments.mdx @@ -0,0 +1,60 @@ +--- +title: Amendments +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L138-L144) + +The `Amendments` object type contains a list of Amendments that are currently active. Each ledger version contains **at most one** `Amendments` object. + +### Example JSON + +```json +{ + "Majorities": [ + { + "Majority": { + "Amendment": "1562511F573A19AE9BD103B5D6B9E01B3B46805AEC5D3C4805C902B514399146", + "CloseTime": 535589001 + } + } + ], + "Amendments": [ + "42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE", + "4C97EBA926031A7CF7D7B36FDE3ED66DDA5421192D63DE53FFB46E43B9DC8373", + "6781F8368C4771B83E8B821D88F580202BCB4228075297B19E4FDC5233F1EFDC", + "740352F2412A9909880C23A559FCECEDA3BE2126FED62FC7660D628A06927F11" + ], + "Flags": 0, + "LedgerEntryType": "Amendments", + "index": "7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4" +} +``` + +### Fields + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Amendments` | Array | Vector256 | No | Array of 256-bit amendment IDs for all currently enabled amendments. If omitted, there are no enabled amendments. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `Amendments` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0066`, mapped to the string `Amendments`, indicates that this object describes the status of amendments to Xahau. | +| `Majorities` | Array | STArray | No | Array of objects describing the status of amendments that have majority support but are not yet enabled. If omitted, there are no pending amendments with majority support. | + +Each member of the `Majorities` field, if it is present, is an object with one field, `Majority`, whose contents are a nested object with the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Description | +| ----------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------- | +| `Amendment` | String | Hash256 | The Amendment ID of the pending amendment. | +| `CloseTime` | Number | UInt32 | The `close_time` field of the ledger version where this amendment most recently gained a majority. | + +In the amendment process, a consensus of validators adds a new amendment to the `Majorities` field using an \[EnableAmendment]\[] pseudo-transaction with the `tfGotMajority` flag when 80% or more of validators support it. If support for a pending amendment goes below 80%, an \[EnableAmendment]\[] pseudo-transaction with the `tfLostMajority` flag removes the amendment from the `Majorities` array. If an amendment remains in the `Majorities` field for at least 2 weeks, an \[EnableAmendment]\[] pseudo-transaction with no flags removes it from `Majorities` and permanently adds it to the `Amendments` field. + +**Note:** Technically, all transactions in a ledger are processed based on which amendments are enabled in the ledger version immediately before it. While applying transactions to a ledger version where an amendment becomes enabled, the rules don't change mid-ledger. After the ledger is closed, the next ledger uses the new rules as defined by any new amendments that apply. + +### Amendments ID Format + +The `Amendments` object ID is the hash of the `Amendments` space key (`0x0066`) only. This means that the ID of the `Amendments` object in a ledger is always: + +``` +7DB0788C020F02780A673DC74757F23823FA3014C1866E72CC4CD8B226CD6EF4 +``` + +(Don't mix up the ID of the `Amendments` ledger object type with the Amendment ID of an individual amendment.) diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/check.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/check.mdx new file mode 100644 index 0000000..6ca0175 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/check.mdx @@ -0,0 +1,58 @@ +--- +title: Check +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L157-L170) + +_(Added by the \[Checks amendment]\[].)_ + +A `Check` object describes a check, similar to a paper personal check, which can be cashed by its destination to get money from its sender. (The potential payment has already been approved by its sender, but no money moves until it is cashed. Unlike an Escrow, the money for a Check is not set aside, so cashing the Check could fail due to lack of funds.) + +### Example JSON + +```json +{ + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "Destination": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + "DestinationNode": "0000000000000000", + "DestinationTag": 1, + "Expiration": 570113521, + "Flags": 0, + "InvoiceID": "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291", + "LedgerEntryType": "Check", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924", + "PreviousTxnLgrSeq": 6, + "SendMax": "100000000", + "Sequence": 2, + "index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" +} +``` + +### Fields + +A `Check` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | ---------------- | ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | Account | Yes | The sender of the Check. Cashing the Check debits this address's balance. | +| `Destination` | String | Account | Yes | The intended recipient of the Check. Only this address can cash the Check, using a \[CheckCash transaction]\[]. | +| `DestinationNode` | String | UInt64 | No | A hint indicating which page of the destination's owner directory links to this object, in case the directory consists of multiple pages. | +| `DestinationTag` | Number | UInt32 | No | An arbitrary tag to further specify the destination for this Check, such as a hosted recipient at the destination address. | +| `Expiration` | Number | UInt32 | No | Indicates the time after which this Check is considered expired. See \[Specifying Time]\[] for details. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `Check` objects. The value is always `0`. | +| `InvoiceID` | String | Hash256 | No | Arbitrary 256-bit hash provided by the sender as a specific reason or identifier for this Check. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0043`, mapped to the string `Check`, indicates that this object is a Check object. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. **Note:** The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account`. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `SendMax` | String or Object | Amount | Yes | The maximum amount of currency this Check can debit the sender. If the Check is successfully cashed, the destination is credited in the same currency for up to this amount. | +| `Sequence` | Number | UInt32 | Yes | The sequence number of the \[CheckCreate transaction]\[] that created this check. | +| `SourceTag` | Number | UInt32 | No | An arbitrary tag to further specify the source for this Check, such as a hosted recipient at the sender's address. | + +### Check ID Format + +The ID of a `Check` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Check space key (`0x0043`) +* The AccountID of the sender of the \[CheckCreate transaction]\[] that created the `Check` object +* The `Sequence` number of the \[CheckCreate transaction]\[] that created the `Check` object. If the CheckCreate transaction used a Ticket, use the `TicketSequence` value instead. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/deposit-pre-auth.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/deposit-pre-auth.mdx new file mode 100644 index 0000000..46ba0aa --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/deposit-pre-auth.mdx @@ -0,0 +1,45 @@ +--- +title: Deposit Pre Auth +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L172-L178) + +A `DepositPreauth` object tracks a preauthorization from one account to another. \[DepositPreauth transactions]\[] create these objects. + +This has no effect on the processing of transactions unless the account that provided the preauthorization requires Deposit Authorization. In that case, the account that was preauthorized can send payments and other transactions directly to the account that provided the preauthorization. Preauthorizations are one-directional and have no effect on payments going the opposite direction. + +### Example JSON + +```json +{ + "LedgerEntryType": "DepositPreauth", + "Account": "rsUiUMpnrgxQp24dJYZDhmV4bE3aBtQyt8", + "Authorize": "rEhxGqkqPPSxQ3P25J66ft5TwpzV14k2de", + "Flags": 0, + "OwnerNode": "0000000000000000", + "PreviousTxnID": "3E8964D5A86B3CD6B9ECB33310D4E073D64C865A5B866200AD2B7E29F8326702", + "PreviousTxnLgrSeq": 7, + "index": "4A255038CC3ADCC1A9C91509279B59908251728D0DAADB248FFE297D0F7E068C" +} +``` + +### Fields + +A `DepositPreauth` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | --------- | ------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | Account | Yes | The account that granted the preauthorization. (The destination of the preauthorized payments.) | +| `Authorize` | String | Account | Yes | The account that received the preauthorization. (The sender of the preauthorized payments.) | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `DepositPreauth` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0070`, mapped to the string `DepositPreauth`, indicates that this is a DepositPreauth object. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the sender's owner directory links to this object, in case the directory consists of multiple pages. **Note:** The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account`. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | + +### DepositPreauth ID Format + +The ID of a `DepositPreauth` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The DepositPreauth space key (`0x0070`) +* The AccountID of the owner of this object (the sender of the \[DepositPreauth transaction]\[] that created this object; in other words, the one that granted the preauthorization) +* The AccountID of the preauthorized account (the `Authorized` field of the \[DepositPreauth transaction]\[] that created this object; in other words, the one that received the preauthorization) diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/directory-node.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/directory-node.mdx new file mode 100644 index 0000000..3a8c266 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/directory-node.mdx @@ -0,0 +1,96 @@ +--- +title: Directory Node +--- +[\[Source\]](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L44) + +The `DirectoryNode` object type provides a list of links to other objects in the ledger's state tree. A single conceptual _Directory_ takes the form of a doubly linked list, with one or more DirectoryNode objects each containing up to 32 IDs of other objects. The first object is called the root of the directory, and all objects other than the root object can be added or deleted as necessary. + +There are two kinds of Directories: + +* **Owner directories** list other objects owned by an account, such as `RippleState` (trust line) or `Offer` objects. +* **Offer directories** list the offers available in the decentralized exchange. A single Offer directory contains all the offers that have the same exchange rate for the same token (currency code and issuer). + +### Example JSON + +_Offer Directory_ + +```json +{ + "ExchangeRate": "4F069BA8FF484000", + "Flags": 0, + "Indexes": [ + "AD7EAE148287EF12D213A251015F86E6D4BD34B3C4A0A1ED9A17198373F908AD" + ], + "LedgerEntryType": "DirectoryNode", + "RootIndex": "1BBEF97EDE88D40CEE2ADE6FEF121166AFE80D99EBADB01A4F069BA8FF484000", + "TakerGetsCurrency": "0000000000000000000000000000000000000000", + "TakerGetsIssuer": "0000000000000000000000000000000000000000", + "TakerPaysCurrency": "0000000000000000000000004A50590000000000", + "TakerPaysIssuer": "5BBC0F22F61D9224A110650CFE21CC0C4BE13098", + "index": "1BBEF97EDE88D40CEE2ADE6FEF121166AFE80D99EBADB01A4F069BA8FF484000" +} +``` + +_Owner Directory_ + +```json +{ + "Flags": 0, + "Indexes": [ + "AD7EAE148287EF12D213A251015F86E6D4BD34B3C4A0A1ED9A17198373F908AD", + "E83BBB58949A8303DF07172B16FB8EFBA66B9191F3836EC27A4568ED5997BAC5" + ], + "ReferenceCount": "1", + "LedgerEntryType": "DirectoryNode", + "Owner": "rpR95n1iFkTqpoy1e878f4Z1pVHVtWKMNQ", + "RootIndex": "193C591BF62482468422313F9D3274B5927CA80B4DD3707E42015DD609E39C94", + "index": "193C591BF62482468422313F9D3274B5927CA80B4DD3707E42015DD609E39C94" +} +``` + +### Fields + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | --------- | ------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Owner` | String | AccountID | No | (Owner Directories only) The address of the account that owns the objects in this directory. | +| `TakerGetsCurrency` | String | Hash160 | No | (Offer Directories only) The currency code of the `TakerGets` amount from the offers in this directory. | +| `TakerGetsIssuer` | String | Hash160 | No | (Offer Directories only) The issuer of the `TakerGets` amount from the offers in this directory. | +| `TakerPaysCurrency` | String | Hash160 | No | (Offer Directories only) The currency code of the `TakerPays` amount from the offers in this directory. | +| `TakerPaysIssuer` | String | Hash160 | No | (Offer Directories only) The issuer of the `TakerPays` amount from the offers in this directory. | +| `ExchangeRate` | String | UInt64 | No | (Offer Directories only) **DEPRECATED**. Do not use. | +| `ReferenceCount` | String | UInt64 | No | Reference counting in the ledger reduces storage burden and fees by allowing multiple installations of the same Hook to point to the same object on the ledger, only removing it when no accounts have the Hook installed. | +| `Indexes` | Array | Vector256 | Yes | The contents of this Directory: an array of IDs of other objects. | +| `IndexNext` | Number | UInt64 | No | If this Directory consists of multiple pages, this ID links to the next object in the chain, wrapping around at the end. | +| `IndexPrevious` | Number | UInt64 | No | If this Directory consists of multiple pages, this ID links to the previous object in the chain, wrapping around at the beginning. | +| `NFTokenID` | String | Hash256 | No | Unused | + +### Directory ID Formats + +There are three different formulas for creating the ID of a DirectoryNode, depending on which of the following the DirectoryNode represents: + +* The first page (also called the root) of an Owner Directory +* The first page of an Offer Directory +* Later pages of either type + +**The first page of an Owner Directory** has an ID that is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Owner Directory space key (`0x004F`) +* The AccountID from the `Owner` field. + +**The first page of an Offer Directory** has a special ID: the higher 192 bits define the order book, and the remaining 64 bits define the exchange rate of the offers in that directory. (The ID is big-endian, so the book is in the more significant bits, which come first, and the quality is in the less significant bits which come last.) + +This provides a way to iterate through an order book from best offers to worst. Specifically: the first 192 bits are the first 192 bits of the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Book Directory space key (`0x0042`) +* The 160-bit currency code from the `TakerPaysCurrency` +* The 160-bit currency code from the `TakerGetsCurrency` +* The AccountID from the `TakerPaysIssuer` +* The AccountID from the `TakerGetsIssuer` + +The lower 64 bits of an Offer Directory's ID represent the `TakerPays` amount divided by `TakerGets` amount from the offer(s) in that directory as a 64-bit number in Xahau's internal amount format. + +**If the DirectoryNode is not the first page in the Directory** (regardless of whether it is an Owner Directory or an Offer Directory), then it has an ID that is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The DirectoryNode space key (`0x0064`) +* The ID of the root DirectoryNode +* The page number of this object. (Since 0 is the root DirectoryNode, this value is an integer 1 or higher.) diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/emitted-txn.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/emitted-txn.mdx new file mode 100644 index 0000000..42d5b08 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/emitted-txn.mdx @@ -0,0 +1,61 @@ +--- +title: Emitted Txn +--- +_(Added by the \[Hooks amendment]\[].)_ + +An `EmittedTxn` object describes a transaction that has been emitted by a hook. The object contains all the fields of the original transaction, along with additional details about the emission. + +### Example JSON + +```json +{ + "Account": "rMPwD1b8dJUaqZHaBgEvFx4ENhtpPVvDsv", + "Amount": "999999", + "Destination": "rfCarbonVNTuXckX6x2qTMFmFSnm6dEWGX", + "DestinationTag": 0, + "EmitDetails": { + "EmitBurden": "1", + "EmitCallback": "rMPwD1b8dJUaqZHaBgEvFx4ENhtpPVvDsv", + "EmitGeneration": 1, + "EmitHookHash": "A9B5411F4A4368008B4736EEE47A34B0EFCBE74016B9B94CC6208FBC0BF5C0C2", + "EmitNonce": "6B2A27D6864903A479614581A79D18E8C8ADCE01E3440C6E993BE07298ADC2A4", + "EmitParentTxnID": "9763EB6B74AEF0F55F642243AD51F48490594434439002A6142E545E47318D56" + }, + "Fee": "31", + "FirstLedgerSequence": 7186113, + "Flags": 2147483648, + "LastLedgerSequence": 7186117, + "Sequence": 0, + "SigningPubKey": "000000000000000000000000000000000000000000000000000000000000000000", + "SourceTag": 0, + "TransactionType": "Payment" +} +``` + +### Fields + +An `EmittedTxn` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `EmitDetails` | Object | Object | Yes | Contains details about the emission. This includes the generation of the emission, the burden of the emission, the callback address, the hash of the hook that emitted the transaction, the nonce of the emission, and the ID of the parent transaction. | +| `TransactionType` | String | UInt16 | Yes | The type of the transaction that was emitted. | +| `Account` | String | Account | Yes | The account that emitted the transaction. | +| `Fee` | String | Amount | Yes | The fee paid for the transaction. | +| `Sequence` | Number | UInt32 | Yes | The sequence number of the transaction. | +| `SigningPubKey` | String | Blob | Yes | The public key that signs the transaction. | + +The `EmittedTxn` object also contains all the fields of the original transaction. + +### EmitDetails Fields + +An `EmitDetails` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `EmitGeneration` | Number | UInt32 | Yes | This field keeps track of a chain of emitted transactions that in turn cause other transactions to be emitted. | +| `EmitBurden` | String | UInt64 | Yes | This field is a heuristic for detecting forkbombs. Fees are based on burden and will increase exponentially when a chain reaction is started to prevent the network becoming overun by self-reinforcing emitted transactions. | +| `EmitParentTxnID` | String | Hash256 | Yes | The Hook Execution that emitted the transaction is connected to the Originating Transaction. Therefore this field is always required for the efficient tracing of behaviour. | +| `EmitNonce` | String | Hash256 | Yes | Emitted Transactions would be identical with the same fields and therefore have identical transaction hashes if a nonce were not used. However every node on the network needs to agree on the nonce, so a special Hook API to produce a deterministic nonce is made available. | +| `EmitCallback` | String | AccountID | No | This field is used by xahld when it needs to intitate a callback, such that it knows which Hook and account to initate the callback on. Callbacks happen when an emitted transaction is accepted into a ledger. | +| `EmitHookHash` | String | Hash256 | Yes | The SHA512H of the Hook at the time it was executed. | diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/escrow.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/escrow.mdx new file mode 100644 index 0000000..8c445cb --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/escrow.mdx @@ -0,0 +1,67 @@ +--- +title: Escrow +--- +[\[Source\]](https://github.com/ripple/rippled/blob/c6b6d82a754fe449cc533e18659df483c10a5c98/src/ripple/protocol/impl/LedgerFormats.cpp#L90-L101) + +_(Added by the \[Escrow amendment]\[].)_ + +The `Escrow` object type represents a held payment of XAH or IOU waiting to be executed or canceled. An \[EscrowCreate transaction]\[] creates an `Escrow` object in the ledger. A successful \[EscrowFinish]\[] or \[EscrowCancel]\[] transaction deletes the object. + +If the `Escrow` object has a [_crypto-condition_](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02), the payment can only succeed if an EscrowFinish transaction provides the corresponding _fulfillment_ that satisfies the condition. (The only supported crypto-condition type is [PREIMAGE-SHA-256](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1).) If the `Escrow` object has a `FinishAfter` time, the held payment can only execute after that time. + +An `Escrow` object is associated with two addresses: + +* The owner, who provides the XAH or IOU when creating the `Escrow` object. If the held payment is canceled, the XAH or IOU returns to the owner. +* The destination, where the XAH or IOU is paid when the held payment succeeds. The destination can be the same as the owner. + +### Example JSON + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Amount": "10000", + "CancelAfter": 545440232, + "Condition": "A0258020A82A88B2DF843A54F58772E4A3861866ECDB4157645DD9AE528C1D3AEEDABAB6810120", + "Destination": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "DestinationTag": 23480, + "FinishAfter": 545354132, + "Flags": 0, + "LedgerEntryType": "Escrow", + "OwnerNode": "0000000000000000", + "DestinationNode": "0000000000000000", + "PreviousTxnID": "C44F2EB84196B9AD820313DBEBA6316A15C9A2D35787579ED172B87A30131DA7", + "PreviousTxnLgrSeq": 28991004, + "SourceTag": 11747, + "index": "DC5F3851D8A1AB622F957761E5963BC5BD439D5C24AC6AD7AC4523F0640244AC" +} +``` + +### Fields + +An `Escrow` object has the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | ---------------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | Yes | The address of the owner (sender) of this held payment. This is the account that provided the amount, and gets it back if the held payment is canceled. | +| `Amount` | String or Object | Amount | Yes | The amount to be delivered by the held payment. | +| `CancelAfter` | Number | UInt32 | No | The held payment can be canceled if and only if this field is present _and_ the time it specifies has passed. Specifically, this is specified as \[seconds since the Ripple Epoch]\[] and it "has passed" if it's earlier than the close time of the previous validated ledger. | +| `Condition` | String | Blob | No | A [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1), as hexadecimal. If present, the \[EscrowFinish transaction]\[] must contain a fulfillment that satisfies this condition. | +| `Destination` | String | AccountID | Yes | The destination address where the amount is paid if the held payment is successful. | +| `DestinationNode` | String | UInt64 | No | A hint indicating which page of the destination's owner directory links to this object, in case the directory consists of multiple pages. Omitted on escrows created before enabling the \[fix1523 amendment]\[]. | +| `DestinationTag` | Number | UInt32 | No | An arbitrary tag to further specify the destination for this held payment, such as a hosted recipient at the destination address. | +| `FinishAfter` | Number | UInt32 | No | The time, in \[seconds since the Ripple Epoch]\[], after which this held payment can be finished. Any \[EscrowFinish transaction]\[] before this time fails. (Specifically, this is compared with the close time of the previous validated ledger.) | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `Escrow` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0075`, mapped to the string `Escrow`, indicates that this object is an `Escrow` object. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner directory links to this object, in case the directory consists of multiple pages. **Note:** The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account`. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `SourceTag` | Number | UInt32 | No | An arbitrary tag to further specify the source for this held payment, such as a hosted recipient at the owner's address. | +| `TransferRate` | Number | UInt32 | No | | + +### Escrow ID Format + +The ID of an `Escrow` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Escrow space key (`0x0075`) +* The AccountID of the sender of the \[EscrowCreate transaction]\[] that created the `Escrow` object +* The Sequence number of the \[EscrowCreate transaction]\[] that created the `Escrow` object If the EscrowCreate transaction used a Ticket, use the `TicketSequence` value instead. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/fee-settings.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/fee-settings.mdx new file mode 100644 index 0000000..d5e163c --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/fee-settings.mdx @@ -0,0 +1,64 @@ +--- +title: Fee Settings +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L115-L120) + +The `FeeSettings` object type contains the current base transaction cost and reserve amounts as determined by fee voting. Each ledger version contains **at most one** `FeeSettings` object. + +### Example JSON + +Example `FeeSettings` object: + +```json +{ + "BaseFee": "000000000000000A", + "Flags": 0, + "LedgerEntryType": "FeeSettings", + "ReferenceFeeUnits": 10, + "ReserveBase": 20000000, + "ReserveIncrement": 5000000, + "XahauActivationLgrSeq": 0, + "NetworkID": 21337, + "AccountCount": 0, + "index": "4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A651" +} +``` + +### Fields + +The `FeeSettings` object has the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------------- | --------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `BaseFee` | String | UInt64 | Yes | The transaction cost of the "reference transaction" in drops of XAH as hexadecimal. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `FeeSettings` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0073`, mapped to the string `FeeSettings`, indicates that this object contains the ledger's fee settings. | +| `ReferenceFeeUnits` | Number | UInt32 | Yes | The `BaseFee` translated into "fee units". | +| `ReserveBase` | Number | UInt32 | Yes | The base reserve for an account in Xahau, as drops of XAH. | +| `ReserveIncrement` | Number | UInt32 | Yes | The incremental owner reserve for owning objects, as drops of XAH. | +| `XahauActivationLgrSeq` | Number | UInt32 | No | The ledger index where Xahau genesis was activated. | +| `AccountCount` | Number | UInt32 | No | The number of accounts created on the Xahau network. | +| `NetworkID` | Number | UInt32 | No | The ID of the network | + +**Warning:** The JSON format for this ledger object type is unusual. The `BaseFee`, `ReserveBase`, and `ReserveIncrement` indicate drops of XAH but _**not**_ in the usual format for \[specifying XAH]\[Currency Amount]. + +If the _\[XAHFees amendment]\[]_ is enabled, the `FeeSettings` object has these fields instead: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------------- | --------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | +| `BaseFeeDrops` | String | Amount | Yes | The transaction cost of the "reference transaction" in drops of XAH. | +| `Flags` | Number | UInt32 | Yes | A bitmap of boolean flags enabled for this object. Currently, the protocol defines no flags for `FeeSettings` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0073`, mapped to the string `FeeSettings`, indicates that this object contains the ledger's fee settings. | +| `ReserveBaseDrops` | String | Amount | Yes | The base reserve for an account in the XAH Ledger, as drops of XAH. | +| `ReserveIncrementDrops` | String | Amount | Yes | The incremental owner reserve for owning objects, as drops of XAH. | +| `XahauActivationLgrSeq` | Number | UInt32 | No | The ledger index where Xahau genesis was activated. | +| `AccountCount` | Number | UInt32 | No | The number of accounts created on the Xahau network. | +| `NetworkID` | Number | UInt32 | No | | + +### FeeSettings ID Format + +The `FeeSettings` object ID is the hash of the `FeeSettings` space key (`0x0065`) only. This means that the ID of the `FeeSettings` object in a ledger is always: + +``` +4BC50C9B0D8515D3EAAE1E74B29A95804346C491EE1A95BF25E4AAB854A6A651 +``` diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook-definition.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook-definition.mdx new file mode 100644 index 0000000..734463e --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook-definition.mdx @@ -0,0 +1,58 @@ +--- +title: Hook Definition +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L157-L170) + +_(Added by the \[Hooks amendment]\[].)_ + +A `HookDefinition` object describes a hook, which is a piece of code that is executed in response to certain transactions. The hook can modify the transaction, emit new transactions, or perform other actions. + +### Example JSON + +```json +{ + "HookHash": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", + "HookOn": "0000000000000000000000000000000000000000000000000000000000000000", + "HookNamespace": "0000000000000000000000000000000000000000000000000000000000000000", + "HookParameters": { + "HookParameter": { + "HookParameterName": "DEADBEEF", + "HookParameterValue": "DEADBEEF", + } + }, + "HookApiVersion": 1, + "CreateCode": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924", + "HookSetTxnID": "0000000000000000", + "ReferenceCount": "6", + "Fee": "100000000", + "HookCallbackFee": "200000000", + "LedgerEntryType": "HookDefinition", + "index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" +} +``` + +### Fields + +A `HookDefinition` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------- | +| `HookHash` | String | Hash256 | Yes | The unique identifier of the hook. | +| `HookOn` | String | Hash256 | Yes | The transaction/s on which the hook is triggered. | +| `HookCanEmit` | String | Hash256 | No | The transaction/s which the hook can emit. | +| `HookNamespace` | String | Hash256 | Yes | The namespace of the hook. | +| `HookParameters` | String | Vector | Yes | The parameters that the hook accepts. | +| `HookApiVersion` | Number | UInt16 | Yes | The version of the hook API that the hook uses. | +| `CreateCode` | String | VL | Yes | The code that is executed when the hook is created. | +| `HookSetTxnID` | String | Hash256 | Yes | The ID of the transaction that set the hook. | +| `ReferenceCount` | String | UInt64 | Yes | The number of references to the hook. | +| `Fee` | String | Amount | Yes | The fee for executing the hook. | +| `HookCallbackFee` | String | Amount | No | The fee for executing the hook's callback function. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0043`, mapped to the string `HookDefinition`, indicates that this object is a HookDefinition object. | + +#### Hook Definition ID Format + +The ID of a `HookDefinition` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The HookDefinition space key (`0x0044`) +* The `HookHash` of the hook diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook-state.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook-state.mdx new file mode 100644 index 0000000..e78faf6 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook-state.mdx @@ -0,0 +1,42 @@ +--- +title: Hook State +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L157-L170) + +_(Added by the \[Hooks amendment]\[].)_ + +A `HookState` object describes the state of a hook, which is a piece of code running on Xahau that can interact with transactions. The `HookState` object stores the state of the hook, which can be modified by the hook's code. + +### Example JSON + +```json +{ + "OwnerNode": "0000000000000000", + "HookStateKey": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", + "HookStateData": "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291", + "LedgerEntryType": "HookState", + "index": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924" +} +``` + +### Fields + +A `HookState` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner's directory links to this object, in case the directory consists of multiple pages. | +| `HookStateKey` | String | Hash256 | Yes | The key that uniquely identifies this hook state. | +| `HookStateData` | String | VL | Yes | The data stored by the hook. This can be any data that the hook's code decides to store. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0043`, mapped to the string `HookState`, indicates that this object is a HookState object. | + +#### HookState ID Format + +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/Indexes.cpp#L193-L200) + +The ID of a `HookState` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The HookState space key (`0x0076`) +* The AccountID of the account that owns the hook +* The `HookStateKey` of the `HookState` object +* The `HookNamespace` of the hook. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook.mdx new file mode 100644 index 0000000..7238950 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/hook.mdx @@ -0,0 +1,57 @@ +--- +title: Hook +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L157-L170) + +_(Added by the \[Hooks amendment]\[].)_ + +A `Hook` object describes a smart contract, which can be triggered by a transaction to perform predefined operations. The operations are defined by the `Hook` creator and can interact with the ledger and transactions. + +### Example JSON + +```json +{ + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924", + "PreviousTxnLgrSeq": 6, + "Hooks": [ + { + "HookHash": "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291", + "HookParameters": [] + } + ], + "LedgerEntryType": "Hook", + "index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" +} +``` + +### Fields + +A `Hook` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | --------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | Account | Yes | The account that created the Hook. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner's directory links to this object, in case the directory consists of multiple pages. | +| `PreviousTxnID` | String | Hash256 | Yes | The ID of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[ledger index]\[] of the ledger that contains the transaction that most recently modified this object. | +| `Hooks` | Array | Array | Yes | An array of hook objects. Each object has the following fields: `HookHash`, `CreateCode`, `HookGrants`, `HookNamespace`, `HookParameters`, `HookOn`, `HookApiVersion`, `Flags`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0043`, mapped to the string `Hook`, indicates that this object is a Hook object. | + +### Hook Fields + +The following fields are used in the hook object: + +| Field | JSON Type | Internal Type | Description | +| ---------------- | --------- | ------------- | ------------------------------ | +| `HookHash` | String | Hash256 | The hash of the hook. | +| `HookParameters` | Array | Array | The parameters of the hook. | +| `Flags` | Number | UInt32 | Additional flags for the hook. | + +#### Hook ID Format + +The ID of a `Hook` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Hook space key (`0x0048`) +* The AccountID of the sender of the \[SetHook transaction]\[] that created the `Hook` object diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/import-vl-sequence.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/import-vl-sequence.mdx new file mode 100644 index 0000000..b068661 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/import-vl-sequence.mdx @@ -0,0 +1,36 @@ +--- +title: Import VL Sequence +--- +_(Added by the \[Import amendment]\[].)_ + +The `ImportVLSequence` helps track and validate the order of operations during the import process. It is used to ensure that the correct sequence of events occurs and to handle any discrepancies or updates to the dUNL on the "burning" ledger. + +### Example JSON + +```json +{ + "LedgerEntryType": "ImportVLSequence", + "Flags": 0, + "ImportSequence": 2023102101, + "PublicKey": "n9LigbVAi4pQc6pU2KJvQZV5wqJ8C3sVvZvBZUopchH8vqa6PEKy", + "index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" +} +``` + +### Fields + +A `ImportVLSequence` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | --------------------------------------------------------------------------------------------------------------------- | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0049`, mapped to the string `ImportVLSequence`, indicates that this object is a ImportVLSequence object. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags. No flags are defined for the `ImportVLSequence` object type, so this value is always `0`. | +| `ImportSequence` | Number | UInt32 | Yes | The current sequence number of the dUNL list on the "burning" ledger. | +| `PublicKey` | String | Blob | Yes | The `PublicKey` of the dUNL list from the "burning" ledger. | + +#### Import VL Sequence ID Format + +The ID of a `ImportVLSequence` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Import VL Sequence space key (`0x0049`) +* The Public Key of the Import Validator List diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/index.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/index.mdx new file mode 100644 index 0000000..6b1b5cb --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/index.mdx @@ -0,0 +1,21 @@ +--- +title: Ledger Objects Types +--- +import { Aside } from '@astrojs/starlight/components'; + +## Ledger Entry Common Fields + +[\[Source\]](https://github.com/Xahau/xahaud/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp) + +Every entry in a ledger's state data has the same set of common fields, plus additional fields based on the ledger entry type. Field names are case-sensitive. The common fields for all ledger entries are: + +| Field | JSON Type | Internal Type | Required? | Description | +| ------------------------ | --------- | ------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `index` or `LedgerIndex` | String | Hash256 | No | The unique ID for this ledger entry. In JSON, this field is represented with different names depending on the context and API method. (Note, even though this is specified as "optional" in the code, every ledger entry should have one unless it's legacy data from very early in the XRP Ledger's history.) | +| `LedgerEntryType` | String | UInt16 | Yes | The type of ledger entry. Valid ledger entry types include `AccountRoot`, `Offer`, `RippleState`, and others. | +| `Flags` | Number | UInt32 | Yes | Set of bit-flags for this ledger entry. | +| `Remarks` | Array | STArray | No | Array of remark objects to set, update, or delete (see Remarks Format) | + + diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ledger-hashes.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ledger-hashes.mdx new file mode 100644 index 0000000..02a2acb --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ledger-hashes.mdx @@ -0,0 +1,72 @@ +--- +title: Ledger Hashes +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L104-L108) + +(Not to be confused with the \["ledger hash" string data type]\[Hash], which uniquely identifies a ledger version. This section describes the `LedgerHashes` ledger object type.) + +The `LedgerHashes` object type contains a history of prior ledgers that led up to this ledger version, in the form of their hashes. Objects of this ledger type are modified automatically when closing a ledger. (This is one of the only times a ledger's state data is modified without a transaction or pseudo-transaction.) The `LedgerHashes` objects exist to make it possible to look up a previous ledger's hash with only the current ledger version and at most one lookup of a previous ledger version. + +There are two kinds of `LedgerHashes` object. Both types have the same fields. Each ledger version contains: + +* Exactly one "recent history" `LedgerHashes` object +* A number of "previous history" `LedgerHashes` objects based on the current ledger index (that is, the length of the ledger history). Specifically, Xahau adds a new "previous history" object every 65536 ledger versions. + +**Note:** As an exception, a new genesis ledger has no `LedgerHashes` objects at all, because it has no ledger history. + +Example `LedgerHashes` object (trimmed for length): + +```json +{ + "LedgerEntryType": "LedgerHashes", + "Flags": 0, + "FirstLedgerSequence": 2, + "LastLedgerSequence": 33872029, + "Hashes": [ + "D638208ADBD04CBB10DE7B645D3AB4BA31489379411A3A347151702B6401AA78", + "254D690864E418DDD9BCAC93F41B1F53B1AE693FC5FE667CE40205C322D1BE3B", + "A2B31D28905E2DEF926362822BC412B12ABF6942B73B72A32D46ED2ABB7ACCFA", + "AB4014846DF818A4B43D6B1686D0DE0644FE711577C5AB6F0B2A21CCEE280140", + "3383784E82A8BA45F4DD5EF4EE90A1B2D3B4571317DBAC37B859836ADDE644C1", + ... (up to 256 ledger hashes) ... + ], + "index": "B4979A36CDC7F3D3D5C31A4EAE2AC7D7209DDA877588B9AFC66799692AB0D66B" +} +``` + +A `LedgerHashes` object has the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| --------------------- | ---------------- | ------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `FirstLedgerSequence` | Number | UInt32 | Yes | **DEPRECATED** Do not use. (The "recent hashes" object of the production Xahau has the value `2` in this field as a result of a previous `rippled` software. That value gets carried forward as the "recent hashes" object is updated. New "previous history" objects do not have this field, nor do "recent hashes" objects in parallel networks started with more recent versions of `rippled`.) | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `LedgerHashes` objects. The value is always `0`. | +| `Hashes` | Array of Strings | Vector256 | Yes | An array of up to 256 ledger hashes. The contents depend on which sub-type of `LedgerHashes` object this is. | +| `LastLedgerSequence` | Number | UInt32 | Yes | The \[Ledger Index]\[] of the last entry in this object's `Hashes` array. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0068`, mapped to the string `LedgerHashes`, indicates that this object is a list of ledger hashes. | + +### Recent History LedgerHashes + +There is exactly one `LedgerHashes` object of the "recent history" sub-type in every ledger after the genesis ledger. This object contains the identifying hashes of the most recent 256 ledger versions (or fewer, if the ledger history has less than 256 ledgers total) in the `Hashes` array. Whenever a new ledger is closed, part of the process of closing it involves updating the "recent history" object with the hash of the previous ledger version this ledger version is derived from (also known as this ledger version's _parent ledger_). When there are more than 256 hashes, the oldest one is removed. + +Using the "recent history" `LedgerHashes` object of a given ledger, you can get the hash of any ledger index within the 256 ledger versions before the given ledger version. + +### Previous History LedgerHashes + +The "previous history" `LedgerHashes` entries collectively contain the hash of every 256th ledger version (also called "flag ledgers") in the full history of the ledger. When the child of a flag ledger closes, the flag ledger's hash is added to the `Hashes` array of the newest "previous history" `LedgerHashes` object. Every 65536 ledgers, `rippled` creates a new `LedgerHashes` object, so that each "previous history" object has the hashes of 256 flag ledgers. + +**Note:** The oldest "previous history" `LedgerHashes` object contains only 255 entries because the genesis ledger has a ledger index of 1, not 0. + +The "previous history" `LedgerHashes` objects act as a [skip list](https://en.wikipedia.org/wiki/Skip_list) so you can get the hash of any historical flag ledger from its index. From there, you can use that flag ledger's "recent history" object to get the hash of any other ledger. + +### LedgerHashes ID Formats + +There are two formats for `LedgerHashes` object IDs, depending on whether the object is a "recent history" sub-type or a "previous history" sub-type. + +The **"recent history"** `LedgerHashes` object has an ID that is the \[SHA-512Half]\[] of the `LedgerHashes` space key (`0x0073`). In other words, the "recent history" always has the ID `B4979A36CDC7F3D3D5C31A4EAE2AC7D7209DDA877588B9AFC66799692AB0D66B`. + +The **"previous history"** `LedgerHashes` objects have an ID that is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The `LedgerHashes` space key (`0x0073`) +* The 32-bit \[Ledger Index]\[] of a flag ledger in the object's `Hashes` array, divided by 65536. + + **Tip:** Dividing by 65536 keeps the most significant 16 bits, which are the same for all the flag ledgers listed in a "previous history" object, and only those ledgers. You can use this fact to look up the `LedgerHashes` object that contains the hash of any flag ledger. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/negative-unl.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/negative-unl.mdx new file mode 100644 index 0000000..612e554 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/negative-unl.mdx @@ -0,0 +1,53 @@ +--- +title: Negative UNL +--- +_(Added by the \[NegativeUNL amendment]\[].)_ + +The `NegativeUNL` object type contains the current status of the Negative UNL, a list of trusted validators currently believed to be offline. + +Each ledger version contains **at most one** `NegativeUNL` object. If no validators are currently disabled or scheduled to be disabled, there is no `NegativeUNL` object in the ledger. + +### Example JSON + +```json +{ + "DisabledValidators": [ + { + "DisabledValidator": { + "FirstLedgerSequence": 1609728, + "PublicKey": "ED6629D456285AE3613B285F65BBFF168D695BA3921F309949AFCD2CA7AFEC16FE" + } + } + ], + "Flags": 0, + "LedgerEntryType": "NegativeUNL", + "index": "2E8A59AA9D3B5B186B0B9E0F62E6C02587CA74A4D778938E957B6357D364B244" +} +``` + +A `NegativeUNL` object has the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| --------------------- | --------- | ------------------- | --------- | --------------------------------------------------------------------------------------------------------------------- | +| `DisabledValidators` | Array | Array | No | A list of `DisabledValidator` objects (see below), each representing a trusted validator that is currently disabled. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags. No flags are defined for the NegativeUNL object type, so this value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x004E`, mapped to the string `NegativeUNL`, indicates that this object is the Negative UNL. | +| `ValidatorToDisable` | String | Blob | No | The public key of a trusted validator that is scheduled to be disabled in the next flag ledger. | +| `ValidatorToReEnable` | String | Blob | No | The public key of a trusted validator in the Negative UNL that is scheduled to be re-enabled in the next flag ledger. | + +### DisabledValidator Objects + +Each `DisabledValidator` object represents one disabled validator. In JSON, a `DisabledValidator` object has one field, `DisabledValidator`, which in turn contains another object with the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Description | +| --------------------- | --------- | ------------------- | ------------------------------------------------------------------------ | +| `FirstLedgerSequence` | Number | UInt32 | The \[ledger index]\[] when the validator was added to the Negative UNL. | +| `PublicKey` | String | Blob | The master public key of the validator, in hexadecimal. | + +### NegativeUNL ID Format + +The `NegativeUNL` object ID is the hash of the `NegativeUNL` space key (`0x004E`) only. This means that the ID of the `NegativeUNL` object in a ledger is always: + +``` +2E8A59AA9D3B5B186B0B9E0F62E6C02587CA74A4D778938E957B6357D364B244 +``` diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/offer.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/offer.mdx new file mode 100644 index 0000000..3cce2ed --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/offer.mdx @@ -0,0 +1,68 @@ +--- +title: Offer +--- +[\[Source\]](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L57) + +The `Offer` ledger entry describes an Offer to exchange currencies in Xahau's decentralized exchange. (In finance, this is more traditionally known as an _order_.) An \[OfferCreate transaction]\[] only creates an `Offer` entry in the ledger when the Offer cannot be fully executed immediately by consuming other Offers already in the ledger. + +An Offer can become unfunded through other activities in the network while remaining in the ledger. When processing transactions, the network automatically prunes any unfunded Offers that those transactions come across. (Otherwise, unfunded Offers remain because _only_ transactions can change the ledger state.) + +### Example JSON + +```json +{ + "Account": "rBqb89MRQJnMPq8wTwEbtz4kvxrEDfcYvt", + "BookDirectory": "ACC27DE91DBA86FC509069EAF4BC511D73128B780F2E54BF5E07A369E2446000", + "BookNode": "0000000000000000", + "Flags": 131072, + "LedgerEntryType": "Offer", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "F0AB71E777B2DA54B86231E19B82554EF1F8211F92ECA473121C655BFC5329BF", + "PreviousTxnLgrSeq": 14524914, + "Sequence": 866, + "TakerGets": { + "currency": "XAG", + "issuer": "r9Dr5xwkeLegBeXq6ujinjSBLQzQ1zQGjH", + "value": "37" + }, + "TakerPays": "79550000000", + "index": "96F76F27D8A327FC48753167EC04A46AA0E382E6F57F32FD12274144D00F1797" +} +``` + +### Fields + +An `Offer` object has the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | ---------------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `Account` | String | AccountID | Yes | The address of the account that owns this Offer. | +| `BookDirectory` | String | Hash256 | Yes | The ID of the Offer Directory that links to this Offer. | +| `BookNode` | String | UInt64 | Yes | A hint indicating which page of the offer directory links to this object, in case the directory consists of multiple pages. | +| `Expiration` | Number | UInt32 | No | Indicates the time after which this Offer is considered unfunded. See \[Specifying Time]\[] for details. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this offer. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x006F`, mapped to the string `Offer`, indicates that this object describes an Offer. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner directory links to this object, in case the directory consists of multiple pages. **Note:** The offer does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account`. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `Sequence` | Number | UInt32 | Yes | The `Sequence` value of the \[OfferCreate]\[] transaction that created this `Offer` object. Used in combination with the `Account` to identify this Offer. | +| `TakerPays` | String or Object | Amount | Yes | The remaining amount and type of currency requested by the Offer creator. | +| `TakerGets` | String or Object | Amount | Yes | The remaining amount and type of currency being provided by the Offer creator. | + +### Offer Flags + +There are several options that can be either enabled or disabled when an \[OfferCreate transaction]\[] creates an offer object. In the ledger, flags are represented as binary values that can be combined with bitwise-or operations. The bit values for the flags in the ledger are different than the values used to enable or disable those flags in a transaction. Ledger flags have names that begin with **`lsf`**. + +`Offer` objects can have the following flag values: + +
Flag NameHex ValueDecimal ValueCorresponding OfferCreate FlagDescription
lsfPassive0x0001000065536tfPassiveThe object was placed as a passive Offer. This has no effect on the object in the ledger.
lsfSell0x00020000131072tfSellThe object was placed as a sell Offer. This has no effect on the object in the ledger (because tfSell only matters if you get a better rate than you asked for, which cannot happen after the object enters the ledger).
+ +### Offer ID Format + +The ID of an `Offer` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The Offer space key (`0x006F`) +* The AccountID of the account placing the Offer +* The Sequence number of the \[OfferCreate transaction]\[] that created the Offer. + + If the OfferCreate transaction used a Ticket, use the `TicketSequence` value instead. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/pay-channel.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/pay-channel.mdx new file mode 100644 index 0000000..e7ec5c6 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/pay-channel.mdx @@ -0,0 +1,99 @@ +--- +title: Pay Channel +--- +[\[Source\]](https://github.com/ripple/rippled/blob/c0a0b79d2d483b318ce1d82e526bd53df83a4a2c/src/ripple/protocol/impl/LedgerFormats.cpp#L180-L198) + +_(Added by the \[PayChan amendment]\[].)_ + +The `PayChannel` object type represents a payment channel. Payment channels enable small, rapid off-ledger payments of XAH or IOU that can be later reconciled with the consensus ledger. A payment channel holds a balance of XAH or IOU that can only be paid out to a specific destination address until the channel is closed. Any unspent XAH or IOU is returned to the channel's owner (the source address that created and funded it) when the channel closes. + +The \[PaymentChannelCreate transaction]\[] type creates a `PayChannel` object. The \[PaymentChannelFund]\[] and \[PaymentChannelClaim transaction]\[] types modify existing `PayChannel` objects. + +When a payment channel expires, at first it remains on the ledger, because only new transactions can modify ledger contents. Transaction processing automatically closes a payment channel when any transaction accesses it after the expiration. To close an expired channel and return the unspent XAH or IOU to the owner, some addresses must send a new PaymentChannelClaim or PaymentChannelFund transaction accessing the channel. + +For an example of using payment channels, see the Payment Channels Tutorial. + +### Example JSON + +```json +{ + "Account": "rBqb89MRQJnMPq8wTwEbtz4kvxrEDfcYvt", + "Destination": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Amount": "4325800", + "Balance": "2323423", + "PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + "SettleDelay": 3600, + "Expiration": 536027313, + "CancelAfter": 536891313, + "SourceTag": 0, + "DestinationTag": 1002341, + "DestinationNode": "0000000000000000", + "Flags": 0, + "LedgerEntryType": "PayChannel", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "F0AB71E777B2DA54B86231E19B82554EF1F8211F92ECA473121C655BFC5329BF", + "PreviousTxnLgrSeq": 14524914, + "index": "96F76F27D8A327FC48753167EC04A46AA0E382E6F57F32FD12274144D00F1797" +} +``` + +### Fields + +A `PayChannel` object has the following fields: + +| Name | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | ---------------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | Yes | The source address that owns this payment channel. This comes from the sending address of the transaction that created the channel. | +| `Amount` | String or Object | Amount | Yes | Total amount, that has been allocated to this channel. This includes amounts that has been paid to the destination address. This is initially set by the transaction that created the channel and can be increased if the source address sends a PaymentChannelFund transaction. | +| `Balance` | String or Object | Amount | Yes | Total amount already paid out by the channel. The difference between this value and the `Amount` field is how much amount can still be paid to the destination address with PaymentChannelClaim transactions. If the channel closes, the remaining difference is returned to the source address. | +| `CancelAfter` | Number | UInt32 | No | The immutable expiration time for this payment channel, in \[seconds since the Ripple Epoch]\[]. This channel is expired if this value is present and smaller than the previous ledger's `close_time` field. This is optionally set by the transaction that created the channel, and cannot be changed. | +| `Destination` | String | AccountID | Yes | The destination address for this payment channel. While the payment channel is open, this address is the only one that can receive the amount from the channel. This comes from the `Destination` field of the transaction that created the channel. | +| `DestinationTag` | Number | UInt32 | No | An arbitrary tag to further specify the destination for this payment channel, such as a hosted recipient at the destination address. | +| `DestinationNode` | String | UInt64 | No | A hint indicating which page of the destination's owner directory links to this object, in case the directory consists of multiple pages. Omitted on payment channels created before enabling the \[fixPayChanRecipientOwnerDir amendment]\[]. | +| `Expiration` | Number | UInt32 | No | The mutable expiration time for this payment channel, in \[seconds since the Ripple Epoch]\[]. The channel is expired if this value is present and smaller than the previous ledger's `close_time` field. See Setting Channel Expiration for more details. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `PayChannel` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0078`, mapped to the string `PayChannel`, indicates that this object is a payment channel object. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the source address's owner directory links to this object, in case the directory consists of multiple pages. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `PublicKey` | String | Blob | Yes | Public key, in hexadecimal, of the key pair that can be used to sign claims against this channel. This can be any valid secp256k1 or Ed25519 public key. This is set by the transaction that created the channel and must match the public key used in claims against the channel. The channel source address can also send amounts from this channel to the destination without signed claims. | +| `SettleDelay` | Number | UInt32 | Yes | Number of seconds the source address must wait to close the channel if it still has any amount in it. Smaller values mean that the destination address has less time to redeem any outstanding claims after the source address requests to close the channel. Can be any value that fits in a 32-bit unsigned integer (0 to 2^32-1). This is set by the transaction that creates the channel. | +| `SourceTag` | Number | UInt32 | No | An arbitrary tag to further specify the source for this payment channel, such as a hosted recipient at the owner's address. | +| `TransferRate` | Number | UInt32 | No | | + +### Setting Channel Expiration + +The `Expiration` field of a payment channel is the mutable expiration time, in contrast to the immutable expiration time represented by the `CancelAfter` field. The expiration of a channel is always considered relative to the `close_time` field of the previous ledger. The `Expiration` field is omitted when a `PayChannel` object is created. There are several ways the `Expiration` field of a `PayChannel` object can be updated, which can be summarized as follows: a channel's source address can set the `Expiration` of the channel freely as long as the channel always remains open at least `SettleDelay` seconds after the first attempt to close it. + +#### Source Address + +The source address can set the `Expiration` directly with the PaymentChannelFund transaction type. The new value must not be earlier than whichever of the following values is earliest: + +* The current `Expiration` value (if one is set) +* The previous ledger's close time plus the `SettleDelay` of the channel + +In other words, the source address can always make the `Expiration` later if an expiration is already set. The source can make an `Expiration` value earlier or set an `Expiration` if one isn't currently set, as long as the new value is at least `SettleDelay` seconds in the future. If the source address attempts to set an invalid `Expiration` date, the transaction fails with the `temBAD_EXPIRATION` error code. + +The source address can also set the `Expiration` with the `tfClose` flag of the PaymentChannelClaim transaction type. If the flag is enabled, the ledger automatically sets the `Expiration` to whichever of the following values is earlier: + +* The current `Expiration` value (if one is set) +* The previous ledger's close time plus the `SettleDelay` of the channel + +The source address can remove the `Expiration` with the `tfRenew` flag of the PaymentChannelClaim transaction type. + +#### Destination Address + +The destination address cannot set the `Expiration` field. However, the destination address can use the PaymentChannelClaim's `tfClose` flag to close a channel immediately. + +#### Other Addresses + +If any other address attempts to set an `Expiration` field, the transaction fails with the `tecNO_PERMISSION` error code. However, if the channel is already expired, the transaction causes the channel to close and results in `tesSUCCESS` instead. + +### PayChannel ID Format + +The ID of a `PayChannel` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The PayChannel space key (`0x0078`) +* The AccountID of the source account +* The AccountID of the destination account +* The Sequence number of the \[PaymentChannelCreate transaction]\[] that created the channel If the PaymentChannelCreate transaction used a Ticket, use the `TicketSequence` value instead. diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state.mdx new file mode 100644 index 0000000..813d681 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ripple-state.mdx @@ -0,0 +1,118 @@ +--- +title: Ripple State +--- +[\[Source\]](https://github.com/ripple/rippled/blob/5d2d88209f1732a0f8d592012094e345cbe3e675/src/ripple/protocol/impl/LedgerFormats.cpp#L70) + +The `RippleState` object type connects two accounts in a single currency. Conceptually, a `RippleState` object represents two trust lines between the accounts, one from each side. Each account can change the settings for its side of the `RippleState` object, but the balance is a single shared value. A trust line that is entirely in its default state is considered the same as a trust line that does not exist, so `rippled` deletes `RippleState` objects when their properties are entirely default. + +### High vs. Low Account + +There can only be one `RippleState` object per currency for any given pair of accounts. Since no account is privileged in Xahau, a `RippleState` object sorts account addresses numerically, to ensure a canonical form. Whichever address is numerically lower when decoded is deemed the "low account" and the other is the "high account". The net balance of the trust line is stored from the low account's perspective. + +The "issuer" for the balance in a trust line depends on whether the balance is positive or negative. If a `RippleState` object shows a positive balance, the high account is the issuer. If the balance is negative, the low account is the issuer. Often, the issuer has its limit set to 0 and the other account has a positive limit, but this is not reliable because limits can change without affecting an existing balance. + +### Example JSON + +```json +{ + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-10" + }, + "Flags": 393216, + "HighLimit": { + "currency": "USD", + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "value": "110" + }, + "HighNode": "0000000000000000", + "LedgerEntryType": "RippleState", + "LowLimit": { + "currency": "USD", + "issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "value": "0" + }, + "LowNode": "0000000000000000", + "PreviousTxnID": "E3FE6EA3D48F0C2B639448020EA4F03D4F4F8FFDB243A852A0F59177921B4879", + "PreviousTxnLgrSeq": 14090896, + "LockCount": 1, + "LockedBalance": { + "currency": "USD", + "issuer": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "value": "10" + } + "index": "9CA88CDEDFF9252B3DE183CE35B038F57282BC9503CDFA1923EF9A95DF0D6F7B" +} +``` + +### Fields + +A `RippleState` object has the following fields: + +| Name | JSON Type | Internal Type | Required? | Description | +| ------------------- | --------- | ------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Balance` | Object | Amount | Yes | The balance of the trust line, from the perspective of the low account. A negative balance indicates that the high account holds tokens issued by the low account. The issuer in this is always set to the neutral value ACCOUNT_ONE. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean options enabled for this object. | +| `HighLimit` | Object | Amount | Yes | The limit that the high account has set on the trust line. The `issuer` is the address of the high account that set this limit. | +| `HighNode` | String | UInt64 | Yes | (Omitted in some historical ledgers) A hint indicating which page of the high account's owner directory links to this object, in case the directory consists of multiple pages. | +| `HighQualityIn` | Number | UInt32 | No | The inbound quality set by the high account, as an integer in the implied ratio `HighQualityIn`:1,000,000,000. As a special case, the value 0 is equivalent to 1 billion, or face value. | +| `HighQualityOut` | Number | UInt32 | No | The outbound quality set by the high account, as an integer in the implied ratio `HighQualityOut`:1,000,000,000. As a special case, the value 0 is equivalent to 1 billion, or face value. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0072`, mapped to the string `RippleState`, indicates that this object is a RippleState object. | +| `LowLimit` | Object | Amount | Yes | The limit that the low account has set on the trust line. The `issuer` is the address of the low account that set this limit. | +| `LowNode` | String | UInt64 | Yes | (Omitted in some historical ledgers) A hint indicating which page of the low account's owner directory links to this object, in case the directory consists of multiple pages. | +| `LowQualityIn` | Number | UInt32 | No | The inbound quality set by the low account, as an integer in the implied ratio `LowQualityIn`:1,000,000,000. As a special case, the value 0 is equivalent to 1 billion, or face value. | +| `LowQualityOut` | Number | UInt32 | No | The outbound quality set by the low account, as an integer in the implied ratio `LowQualityOut`:1,000,000,000. As a special case, the value 0 is equivalent to 1 billion, or face value. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `LockCount` | Number | UInt32 | No | The total number of lock balances on a RippleState ledger object | +| `LockedBalance` | Object | Amount | No | The current amount of locked tokens for a specific trustline | + +### RippleState Flags + +There are several options which can be either enabled or disabled for a trust line. These options can be changed with a \[TrustSet transaction]\[]. In the ledger, flags are represented as binary values that can be combined with bitwise-or operations. The bit values for the flags in the ledger are different than the values used to enable or disable those flags in a transaction. Ledger flags have names that begin with **`lsf`**. + +RippleState objects can have the following flag values: + +| Flag Name | Hex Value | Decimal Value | Corresponding TrustSet Flag | Description | +| ----------------- | ------------ | ------------- | --------------------------- | --------------------------------------------------------------------------------------------------- | +| `lsfLowReserve` | `0x00010000` | 65536 | (None) | This RippleState object contributes to the low account's owner reserve. | +| `lsfHighReserve` | `0x00020000` | 131072 | (None) | This RippleState object contributes to the high account's owner reserve. | +| `lsfLowAuth` | `0x00040000` | 262144 | `tfSetAuth` | The low account has authorized the high account to hold tokens issued by the low account. | +| `lsfHighAuth` | `0x00080000` | 524288 | `tfSetAuth` | The high account has authorized the low account to hold tokens issued by the high account. | +| `lsfLowNoRipple` | `0x00100000` | 1048576 | `tfSetNoRipple` | The low account has disabled rippling from this trust line. | +| `lsfHighNoRipple` | `0x00200000` | 2097152 | `tfSetNoRipple` | The high account has disabled rippling from this trust line. | +| `lsfLowFreeze` | `0x00400000` | 4194304 | `tfSetFreeze` | The low account has frozen the trust line, preventing the high account from transferring the asset. | +| `lsfHighFreeze` | `0x00800000` | 8388608 | `tfSetFreeze` | The high account has frozen the trust line, preventing the low account from transferring the asset. | + +### Contributing to the Owner Reserve + +If an account modifies a trust line to put it in a non-default state, then that trust line counts towards the account's owner reserve. In a RippleState object, the `lsfLowReserve` and `lsfHighReserve` flags indicate which account(s) are responsible for the owner reserve. The `rippled` server automatically sets these flags when it modifies a trust line. + +The values that count towards a trust line's non-default state are as follows: + +| High account responsible if... | Low account responsible if... | +| ------------------------------------------------------- | ------------------------------------------------------ | +| `Balance` is negative (the high account holds currency) | `Balance` is positive (the low account holds currency) | +| `HighLimit` is not `0` | `LowLimit` is not `0` | +| `LowQualityIn` is not `0` and not `1000000000` | `HighQualityIn` is not `0` and not `1000000000` | +| `LowQualityOut` is not `0` and not `1000000000` | `HighQualityOut` is not `0` and not `1000000000` | +| `lsfHighNoRipple` flag is not in its default state | `lsfLowNoRipple` flag is not in its default state | +| `lsfHighFreeze` flag is enabled | `lsfLowFreeze` flag is enabled | + +The **`lsfLowAuth`** and **`lsfHighAuth`** flags do not count against the default state, because they cannot be disabled. + +The default state of the two No Ripple flags depends on the state of the `lsfDefaultRipple` flag in their corresponding AccountRoot objects. If Default Ripple is disabled (the default), then the default state of the `lsfNoRipple` flag is _enabled_ for all of an account's trust lines. If an account enables Default Ripple, then the `lsfNoRipple` flag is _disabled_ (rippling is enabled) for an account's trust lines by default. + +**Note:** Prior to the introduction of the Default Ripple flag in `rippled` version 0.27.3 (March 10, 2015), the default state for all trust lines was with both No Ripple flags disabled (rippling enabled). + +Fortunately, `rippled` uses lazy evaluation to calculate the owner reserve. This means that even if an account changes the default state of all its trust lines by changing the Default Ripple flag, that account's reserve stays the same initially. If an account modifies a trust line, `rippled` re-evaluates whether that individual trust line is in its default state and should contribute to the owner reserve. + +### RippleState ID Format + +The ID of a RippleState object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The RippleState space key (`0x0072`) +* The AccountID of the low account +* The AccountID of the high account +* The 160-bit currency code of the trust line(s) diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/signers-list.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/signers-list.mdx new file mode 100644 index 0000000..2c8354c --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/signers-list.mdx @@ -0,0 +1,98 @@ +--- +title: Signers List +--- +[\[Source\]](https://github.com/ripple/rippled/blob/6d2e3da30696bd10e3bb11a5ff6d45d2c4dae90f/src/ripple/protocol/impl/LedgerFormats.cpp#L127) + +_(Added by the \[MultiSign amendment]\[].)_ + +The `SignerList` object type represents a list of parties that, as a group, are authorized to sign a transaction in place of an individual account. You can create, replace, or remove a signer list using a \[SignerListSet transaction]\[]. + +### Example JSON + +```json +{ + "Flags": 0, + "LedgerEntryType": "SignerList", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "5904C0DC72C58A83AEFED2FFC5386356AA83FCA6A88C89D00646E51E687CDBE4", + "PreviousTxnLgrSeq": 16061435, + "SignerEntries": [ + { + "SignerEntry": { + "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "SignerWeight": 2 + } + }, + { + "SignerEntry": { + "Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n", + "SignerWeight": 1 + } + }, + { + "SignerEntry": { + "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", + "SignerWeight": 1 + } + } + ], + "SignerListID": 0, + "SignerQuorum": 3, + "index": "A9C28A28B85CD533217F5C0A0C7767666B093FA58A0F2D80026FCC4CD932DDC7" +} +``` + +### Fields + +A `SignerList` object has the following fields: + +| Name | JSON Type | Internal Type | Required? | Description | +| ------------------- | --------- | ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Flags` | Number | UInt32 | Yes | A bit-map of Boolean flags enabled for this signer list. For more information, see SignerList Flags. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0053`, mapped to the string `SignerList`, indicates that this object is a SignerList object. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner directory links to this object, in case the directory consists of multiple pages. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `SignerEntries` | Array | Array | Yes | An array of Signer Entry objects representing the parties who are part of this signer list. | +| `SignerListID` | Number | UInt32 | Yes | An ID for this signer list. Currently always set to `0`. If a future amendment allows multiple signer lists for an account, this may change. | +| `SignerQuorum` | Number | UInt32 | Yes | A target number for signer weights. To produce a valid signature for the owner of this SignerList, the signers must provide valid signatures whose weights sum to this value or more. | + +The `SignerEntries` may be any combination of funded and unfunded addresses that use either secp256k1 or ed25519 keys. + +#### Signer Entry Object + +Each member of the `SignerEntries` field is an object that describes that signer in the list. A Signer Entry has the following fields: + +| Name | JSON Type | Internal Type | Description | +| --------------- | --------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | A Xahau address whose signature contributes to the multi-signature. It does not need to be a funded address in the ledger. | +| `SignerWeight` | Number | UInt16 | The weight of a signature from this signer. A multi-signature is only valid if the sum weight of the signatures provided meets or exceeds the signer list's `SignerQuorum` value. | +| `WalletLocator` | String | Hash256 | _(Optional)_ Arbitrary hexadecimal data. This can be used to identify the signer or for other, related purposes. _(Added by the \[ExpandedSignerList amendment]\[].)_ | + +When processing a multi-signed transaction, the server looks up the `Account` values with respect to the ledger at the time of transaction execution. If the address _does not_ correspond to a funded AccountRoot object, then only the master private key associated with that address can be used to produce a valid signature. If the account _does_ exist in the ledger, then it depends on the state of that account. If the account has a Regular Key configured, the Regular Key can be used. The account's master key can only be used if it is not disabled. A multi-signature cannot be used as part of another multi-signature. + +### SignerList Flags + +_(Added by the \[MultiSignReserve amendment]\[].)_ + +SignerList objects can have the following flag value: + +| Flag Name | Hex Value | Decimal Value | Description | +| ------------------ | ------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `lsfOneOwnerCount` | `0x00010000` | 65536 | If this flag is enabled, this SignerList counts as one item for purposes of the owner reserve. Otherwise, this list counts as N+2 items, where N is the number of signers it contains. This flag is automatically enabled if you add or update a signer list after the \[MultiSignReserve amendment]\[] is enabled. | + +### Signer Lists and Reserves + +A signer list contributes to its owner's reserve requirement. + +The \[MultiSignReserve amendment]\[] (enabled 2019-04-17) made it so each signer list counts as one object, regardless of how many members it has. As a result, the owner reserve associated with a new signer list is 2 XAH. + +A signer list created before the \[MultiSignReserve amendment]\[] itself counts as two objects, and each member of the list counts as one. As a result, the total owner reserve associated with the signer list is anywhere from 3 times to 10 times the reserve required by a single trust line (RippleState) or Offer object in the ledger. To update a signer list to use the new, reduced reserve, update the signer list by sending a \[SignerListSet transaction]\[]. + +### SignerList ID Format + +The ID of a signer list object is the SHA-512Half of the following values, concatenated in order: + +* The RippleState space key (`0x0053`) +* The AccountID of the owner of the signer list +* The `SignerListID` (currently always `0`) diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ticket.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ticket.mdx new file mode 100644 index 0000000..0a57972 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/ticket.mdx @@ -0,0 +1,44 @@ +--- +title: Ticket +--- +[\[Source\]](https://github.com/ripple/rippled/blob/76a6956138c4ecd156c5c408f136ed3d6ab7d0c1/src/ripple/protocol/impl/LedgerFormats.cpp#L155-L164) + +_(Added by the \[TicketBatch amendment]\[].)_ + +The `Ticket` object type represents a Ticket, which tracks an account \[sequence number]\[Sequence Number] that has been set aside for future use. You can create new tickets with a \[TicketCreate transaction]\[]. \[New in: rippled 1.7.0]\[] + +### Example JSON + +```json +{ + "Account": "rEhxGqkqPPSxQ3P25J66ft5TwpzV14k2de", + "Flags": 0, + "LedgerEntryType": "Ticket", + "OwnerNode": "0000000000000000", + "PreviousTxnID": "F19AD4577212D3BEACA0F75FE1BA1644F2E854D46E8D62E9C95D18E9708CBFB1", + "PreviousTxnLgrSeq": 4, + "TicketSequence": 3 +} +``` + +### Fields + +A `Ticket` object has the following fields: + +| Name | JSON Type | Internal Type | Required? | Description | +| ------------------- | --------- | ------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | Yes | The account that owns this Ticket. | +| `Flags` | Number | UInt32 | Yes | A bit-map of boolean flags enabled for this object. Currently, the protocol defines no flags for `Ticket` objects. The value is always `0`. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0054`, mapped to the string `Ticket`, indicates that this object is a Ticket object. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner directory links to this object, in case the directory consists of multiple pages. **Note:** The object does not contain a direct link to the owner directory containing it, since that value can be derived from the `Account`. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The \[index of the ledger]\[Ledger Index] that contains the transaction that most recently modified this object. | +| `TicketSequence` | Number | UInt32 | Yes | The \[Sequence Number]\[] this Ticket sets aside. | + +### Ticket ID Format + +The ID of a Ticket object is the SHA-512Half of the following values, concatenated in order: + +* The Ticket space key (`0x0054`) +* The AccountID of the owner of the Ticket +* The `TicketSequence` number of the Ticket diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/unl-report.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/unl-report.mdx new file mode 100644 index 0000000..be49225 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/unl-report.mdx @@ -0,0 +1,63 @@ +--- +title: UNL Report +--- +_(Added by the \[Hooks amendment]\[].)_ + +A `UNLReport` object describes a report of the Unique Node List (UNL) which is a list of validator nodes that are trusted by the network to validate transactions. + +### Example JSON + +```json +{ + "LedgerEntryType": "UNLReport", + "PreviousTxnID": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924", + "PreviousTxnLgrSeq": 6, + "ImportVLKeys": [ + { + "PublicKey": "n9LigbVAi4pQc6pU2KJvQZV5wqJ8C3sVvZvBZUopchH8vqa6PEKy", + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo" + } + ], + "ActiveValidators": [ + { + "PublicKey": "n9LigbVAi4pQc6pU2KJvQZV5wqJ8C3sVvZvBZUopchH8vqa6PEKy", + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo" + } + ], + "index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" +} +``` + +### Fields + +A `UNLReport` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | --------- | ------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0073`, mapped to the string `UNLReport`, indicates that this object is a UNLReport object. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The index of the ledger that contains the transaction that most recently modified this object. | +| `ImportVLKeys` | Array | Array | No | An array of objects, each representing a validator key that has been imported. Each object has a `PublicKey` field and an optional `Account` field. | +| `ActiveValidators` | Array | Array | No | An array of objects, each representing an active validator. Each object has a `PublicKey` field and an optional `Account` field. | + +### ImportVLKey Fields + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------- | --------- | ------------------- | --------- | ------------------------------------------------------------------------------- | +| `PublicKey` | String | VL | Yes | The public key of the imported validator. | +| `Account` | String | Account | No | The account associated with the imported validator key. This field is optional. | + +### ActiveValidator Fields + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------- | --------- | ------------------- | --------- | ------------------------------------------------------------------------- | +| `PublicKey` | String | VL | Yes | The public key of the active validator. | +| `Account` | String | Account | No | The account associated with the active validator. This field is optional. | + +### UNLReport ID Format + +The `UNLReport` object ID is the hash of the `UNLReport` space key (`0x0052`) only. This means that the ID of the `UNLReport` object in a ledger is always: + +``` +61E32E7A24A238F1C619D5F9DDCC41A94B33B66C0163F7EFCC8A19C9FD6F28DC +``` diff --git a/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/uritoken.mdx b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/uritoken.mdx new file mode 100644 index 0000000..40b87b6 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/ledger-data/ledger-objects-types/uritoken.mdx @@ -0,0 +1,59 @@ +--- +title: URIToken +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/impl/LedgerFormats.cpp#L157-L170) + +_(Added by the \[URI Token amendment]\[].)_ + +A `URIToken` object describes a URI token, which can be used to represent a unique resource identifier in the ledger. + +### Example JSON + +```json +{ + "Owner": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "OwnerNode": "0000000000000000", + "Issuer": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + "URI": "DEADBEEF", + "Digest": "46060241FABCF692D4D934BA2A6C4427CD4279083E38C77CBE642243E43BE291", + "Amount": "100000000", + "Destination": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "PreviousTxnID": "5463C6E08862A1FAE5EDAC12D70ADB16546A1F674930521295BC082494B62924", + "PreviousTxnLgrSeq": 6, + "LedgerEntryType": "URIToken", + "index": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0" +} +``` + +### Fields + +A `URIToken` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ------------------- | ---------------- | ------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `Owner` | String | Account | Yes | The owner of the URI Token. | +| `OwnerNode` | String | UInt64 | Yes | A hint indicating which page of the owner's directory links to this object, in case the directory consists of multiple pages. | +| `Issuer` | String | Account | Yes | The issuer of the URI Token. | +| `URI` | String | VL | Yes | The URI represented by this token. | +| `Digest` | String | Hash256 | No | Arbitrary 256-bit hash provided by the owner as a specific identifier for this URI Token. | +| `Amount` | String or Object | Amount | No | The amount of the URI Token. | +| `Destination` | String | Account | No | The intended recipient of the URI Token. | +| `PreviousTxnID` | String | Hash256 | Yes | The identifying hash of the transaction that most recently modified this object. | +| `PreviousTxnLgrSeq` | Number | UInt32 | Yes | The index of the ledger that contains the transaction that most recently modified this object. | +| `LedgerEntryType` | String | UInt16 | Yes | The value `0x0073`, mapped to the string `URIToken`, indicates that this object is a URI Token object. | + +### URIToken Flags + +`URIToken` objects can have the following flag values: + +| Flag Name | Hex Value | Decimal Value | Corresponding URITokenMint Flag | Description | +| ------------- | ------------ | ------------- | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| `lsfBurnable` | `0x00000001` | 1 | `tfBurnable` | The issuer (or an entity authorized by the issuer) to destroy the minted `URIToken`. (The `URIToken`'s owner can _always_ do so.) | + +### URIToken ID Format + +The ID of a `URIToken` object is the \[SHA-512Half]\[] of the following values, concatenated in order: + +* The URI Token space key (`0x0055`) +* The AccountID of the issuer of the URI Token +* The URI represented by the URI Token diff --git a/src/content/docs/docs/protocol-reference/transactions/index.mdx b/src/content/docs/docs/protocol-reference/transactions/index.mdx new file mode 100644 index 0000000..f135fda --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/index.mdx @@ -0,0 +1,6 @@ +--- +title: Transactions +--- +## Transaction Reference + +A _Transaction_ is the only way to cause changes in Xahau. Transactions' outcomes are only final if signed, submitted, and accepted into a validated ledger version following the consensus process. Some ledger rules also generate _pseudo-transactions_, which aren't signed or submitted, but still must be accepted by consensus. Transactions that fail are also included in ledgers because they modify balances of XAH to pay for the anti-spam \[transaction cost]\[]. diff --git a/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/emitfailure.mdx b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/emitfailure.mdx new file mode 100644 index 0000000..c649efa --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/emitfailure.mdx @@ -0,0 +1,4 @@ +--- +title: EmitFailure +--- +TBD \ No newline at end of file diff --git a/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/enableamendment.mdx b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/enableamendment.mdx new file mode 100644 index 0000000..d08e273 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/enableamendment.mdx @@ -0,0 +1,38 @@ +--- +title: EnableAmendment +--- +An `EnableAmendment` pseudo-transaction marks a change in the status of a proposed amendment when it: + +* Gains supermajority approval from validators. +* Loses supermajority approval. +* Is enabled on Xahau protocol. + +### Example JSON + +```json +{ + "Account": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", + "Amendment": "42426C4D4F1009EE67080A9B7965B44656D7714D104A72F9B4369F97ABF044EE", + "Fee": "0", + "LedgerSequence": 21225473, + "Sequence": 0, + "SigningPubKey": "", + "TransactionType": "EnableAmendment" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Amendment` | String | Hash256 | A unique identifier for the amendment. This is not intended to be a human-readable name. See Amendments for a list of known amendments. | +| `LedgerSequence` | Number | UInt32 | The \[ledger index]\[] where this pseudo-transaction appears. This distinguishes the pseudo-transaction from other occurrences of the same change. | + +### EnableAmendment Flags + +The `Flags` value of the EnableAmendment pseudo-transaction indicates the status of the amendment at the time of the ledger including the pseudo-transaction. + +A `Flags` value of `0` (no flags) or an omitted `Flags` field indicates that the amendment has been enabled, and applies to all ledgers afterward. Other `Flags` values are as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| ---------------- | ------------ | ------------- | -------------------------------------------------------------------------------------------------------------- | +| `tfGotMajority` | `0x00010000` | 65536 | Support for this amendment increased to at least 80% of trusted validators starting with this ledger version. | +| `tfLostMajority` | `0x00020000` | 131072 | Support for this amendment decreased to less than 80% of trusted validators starting with this ledger version. | diff --git a/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/index.mdx b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/index.mdx new file mode 100644 index 0000000..6671479 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/index.mdx @@ -0,0 +1,26 @@ +--- +title: Pseudo Transaction Types +--- +Pseudo-transactions are never submitted by users, nor propagated through the network. Instead, a server may choose to inject pseudo-transactions in a proposed ledger directly according to specific protocol rules. If enough servers propose the exact same pseudo-transaction, the consensus process approves it, and the pseudo-transaction is included in that ledger's transaction data. + +### Special Values for Common Fields + +Some of the required \[common fields]\[] for normal transactions do not make sense for pseudo-transactions. Pseudo-transactions use following special values for these common fields: + +| Field | JSON Type | \[Internal Type]\[] | Value | +| --------------- | --------- | ------------------- | ------------------- | +| `Account` | String | AccountID | ACCOUNT_ZERO | +| `Fee` | String | Amount | `0` | +| `Sequence` | Number | UInt32 | `0` | +| `SigningPubKey` | String | Blob | `""` (Empty string) | +| `TxnSignature` | String | Blob | `""` (Empty string) | + +Pseudo-transactions use the following common fields as normal: + +* `TransactionType` +* `Flags` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ----------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `TransactionType` | String | UInt16 | _(Required)_ The type of transaction. | +| `Flags` | Number | UInt32 | _(Optional)_ A set of bit-flags for this transaction. The meaning of specific flags varies based on the transaction type. | diff --git a/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/setfee.mdx b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/setfee.mdx new file mode 100644 index 0000000..e7cdbc9 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/setfee.mdx @@ -0,0 +1,42 @@ +--- +title: SetFee +--- +A `SetFee` pseudo-transaction marks a change in transaction cost or reserve requirements as a result of Fee Voting. + +**Note:** You cannot send a pseudo-transaction, but you may find one when processing ledgers. + +### Example JSON + +```json +{ + "Account": "rrrrrrrrrrrrrrrrrrrrrhoLvTp", + "BaseFee": "000000000000000A", + "Fee": "0", + "ReferenceFeeUnits": 10, + "ReserveBase": 20000000, + "ReserveIncrement": 5000000, + "Sequence": 0, + "SigningPubKey": "", + "TransactionType": "SetFee", + "date": 439578860, + "hash": "1C15FEA3E1D50F96B6598607FC773FF1F6E0125F30160144BE0C5CBC52F5151B", + "ledger_index": 3721729, +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `BaseFee` | String | UInt64 | The charge, in drops of XAH, for the reference transaction, as hex. (This is the transaction cost before scaling for load.) | +| `ReferenceFeeUnits` | Unsigned Integer | UInt32 | The cost, in fee units, of the reference transaction | +| `ReserveBase` | Unsigned Integer | UInt32 | The base reserve, in drops | +| `ReserveIncrement` | Unsigned Integer | UInt32 | The incremental reserve, in drops | +| `LedgerSequence` | Number | UInt32 | _(Omitted for some historical `SetFee` pseudo-transactions)_ The index of the ledger version where this pseudo-transaction appears. This distinguishes the pseudo-transaction from other occurrences of the same change. | + +If the _\[XAHFees amendment]\[]_ is enabled, `SetFee` pseudo-transactions use these fields instead: + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ----------------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `BaseFeeDrops` | String | Amount | The charge, in drops of XAH, for the reference transaction. (This is the transaction cost before scaling for load.) | +| `ReserveBaseDrops` | String | Amount | The base reserve, in drops | +| `ReserveIncrementDrops` | String | Amount | The incremental reserve, in drops | +| `LedgerSequence` | Number | UInt32 | _(Omitted for some historical `SetFee` pseudo-transactions)_ The index of the ledger version where this pseudo-transaction appears. This distinguishes the pseudo-transaction from other occurrences of the same change. | diff --git a/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/unlmodify.mdx b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/unlmodify.mdx new file mode 100644 index 0000000..35601e0 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/unlmodify.mdx @@ -0,0 +1,30 @@ +--- +title: UNLModify +--- +_(Added by the \[NegativeUNL amendment]\[].)_ + +A `UNLModify` pseudo-transaction marks a change to the Negative UNL, indicating that a trusted validator has gone offline or come back online. + +**Note:** You cannot send a pseudo-transaction, but you may find one when processing ledgers. + +### Example JSON + +```json +{ + "Account": "", + "Fee": "0", + "LedgerSequence": 1600000, + "Sequence": 0, + "SigningPubKey": "", + "TransactionType": "UNLModify", + "UNLModifyDisabling": 1, + "UNLModifyValidator": "ED6629D456285AE3613B285F65BBFF168D695BA3921F309949AFCD2CA7AFEC16FE", +} +``` + +| Name | JSON Type | \[Internal Type]\[] | Description | +| -------------------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `TransactionType` | String | UInt16 | The value `0x0066`, mapped to the string `UNLModify`, indicates that this object is an `UNLModify` pseudo-transaction. | +| `LedgerSequence` | Number | UInt32 | The \[ledger index]\[] where this pseudo-transaction appears. This distinguishes the pseudo-transaction from other occurrences of the same change. | +| `UNLModifyDisabling` | Number | UInt8 | If `1`, this change represents adding a validator to the Negative UNL. If `0`, this change represents removing a validator from the Negative UNL. (No other values are allowed.) | +| `UNLModifyValidator` | String | Blob | The validator to add or remove, as identified by its master public key. | diff --git a/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/unlreport.mdx b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/unlreport.mdx new file mode 100644 index 0000000..6156d6b --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/pseudo-transaction-types/unlreport.mdx @@ -0,0 +1,4 @@ +--- +title: UNLReport +--- +TBD \ No newline at end of file diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-common-fields.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-common-fields.mdx new file mode 100644 index 0000000..522e9d0 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-common-fields.mdx @@ -0,0 +1,177 @@ +--- +title: Transaction Common Fields +--- + +Every transaction has the same set of common fields, plus additional fields based on the transaction type. Field names are case-sensitive. The common fields for all transactions are: + +| Field | JSON Type | \[Internal Type]\[] | Description | +| -------------------- | ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `Account` | String | AccountID | _(Required)_ The unique address of the account that initiated the transaction. | +| `TransactionType` | String | UInt16 | _(Required)_ The type of transaction. Valid transaction types include: `Payment`, `OfferCreate`, `TrustSet`, and many others. | +| `Fee` | String | Amount | _(Required; auto-fillable)_ Integer amount of XAH, in drops, to be destroyed as a cost for distributing this transaction to the network. Some transaction types have different minimum requirements. See \[Transaction Cost]\[] for details. | +| `Sequence` | Number | UInt32 | _(Required; auto-fillable)_ The sequence number of the account sending the transaction. A transaction is only valid if the `Sequence` number is exactly 1 greater than the previous transaction from the same account. The special case `0` means the transaction is using a Ticket instead _(Added by the \[TicketBatch amendment]\[].)_. | +| `AccountTxnID` | String | Hash256 | _(Optional)_ Hash value identifying another transaction. If provided, this transaction is only valid if the sending account's previously-sent transaction matches the provided hash. | +| `Flags` | Number | UInt32 | _(Optional)_ Set of bit-flags for this transaction. | +| `LastLedgerSequence` | Number | UInt32 | _(Optional; strongly recommended)_ Highest ledger index this transaction can appear in. Specifying this field places a strict upper limit on how long the transaction can wait to be validated or rejected. See Reliable Transaction Submission for more details. | +| `Memos` | Array of Objects | Array | _(Optional)_ Additional arbitrary information used to identify this transaction. | +| `NetworkID` | Number | UInt32 | _(Network-specific)_ The network ID of the chain this transaction is intended for. **MUST BE OMITTED** for Mainnet and some test networks. **REQUIRED** on chains whose network ID is 1025 or higher. | +| `Signers` | Array | Array | _(Optional)_ Array of objects that represent a multi-signature which authorizes this transaction. | +| `SourceTag` | Number | UInt32 | _(Optional)_ Arbitrary integer used to identify the reason for this payment, or a sender on whose behalf this transaction is made. Conventionally, a refund should specify the initial payment's `SourceTag` as the refund payment's `DestinationTag`. | +| `SigningPubKey` | String | Blob | _(Automatically added when signing)_ Hex representation of the public key that corresponds to the private key used to sign this transaction. If an empty string, indicates a multi-signature is present in the `Signers` field instead. | +| `TicketSequence` | Number | UInt32 | _(Optional)_ The sequence number of the ticket to use in place of a `Sequence` number. If this is provided, `Sequence` must be `0`. Cannot be used with `AccountTxnID`. | +| `TxnSignature` | String | Blob | _(Automatically added when signing)_ The signature that verifies this transaction as originating from the account it says it is from. | +| `EmitDetails` | Object | Object | Contains details about the emission. This includes the generation of the emission, the burden of the emission, the callback address, the hash of the hook that emitted the transaction, the nonce of the emission, and the ID of the parent transaction. | +| `HookParameters` | Array | Array | The hook parameters of the tx. | + +\[Removed in: rippled 0.28.0]\[]: The `PreviousTxnID` field of transactions was replaced by the `AccountTxnID` field. This String / Hash256 field is present in some historical transactions. This is unrelated to the field also named `PreviousTxnID` in some ledger objects. + +### AccountTxnID + +The `AccountTxnID` field lets you chain your transactions together, so that a current transaction is not valid unless the previous transaction sent from the same account has a specific \[transaction hash]\[identifying hash]. + +Unlike the `PreviousTxnID` field, which tracks the last transaction to _modify_ an account (regardless of sender), the `AccountTxnID` tracks the last transaction _sent by_ an account. To use `AccountTxnID`, you must first enable the `asfAccountTxnID` flag, so that the ledger keeps track of the ID for the account's previous transaction. (`PreviousTxnID`, by comparison, is always tracked.) + +One situation in which this is useful is if you have a primary system for submitting transactions and a passive backup system. If the passive backup system becomes disconnected from the primary, but the primary is not fully dead, and they both begin operating at the same time, you could potentially have serious problems like some transactions sending twice and others not at all. Chaining your transactions together with `AccountTxnID` ensures that, even if both systems are active, only one of them can submit valid transactions at a time. + +The `AccountTxnID` field cannot be used on transactions that use Tickets. Transactions that use `AccountTxnID` cannot be placed in the transaction queue. + +### Auto-fillable Fields + +Some fields can be automatically filled in before a transaction is signed, either by a `xahaud` server or by a client library. Auto-filling values requires an active connection to Xahau to get the latest state, so it cannot be done offline. The details can vary by library, but auto-filling always provides suitable values for at least the following fields: + +* `Fee` - Automatically fill in the \[Transaction Cost]\[] based on the network. + + **Note:** When using `xahaud`'s \[sign command]\[], you can limit the maximum possible auto-filled value, using the `fee_mult_max` and `fee_mult_div` parameters.) +* `Sequence` - Automatically use the next sequence number for the account sending the transaction. + +For a production system, we recommend _not_ leaving these fields to be filled by the server. For example, if transaction costs become high due to a temporary spike in network load, you may want to wait for the cost to decrease before sending some transactions, instead of paying the temporarily-high cost. + +The `Paths` field of the \[Payment transaction]\[] type can also be automatically filled in. + +### Flags Field + +The `Flags` field can contain various options that affect how a transaction should behave. The options are represented as binary values that can be combined with bitwise-or operations to set multiple flags at once. + +To check whether a transaction has a given flag enabled, use the bitwise-and operator on the flag's value and the `Flags` field. A result of zero indicates the flag is disabled, and a result equal to the flag value indicates the flag is enabled. (If you got any other result, you did something wrong.) + +Most flags only have meaning for a specific transaction type. The same bitwise value may be reused for flags on different transaction types, so it is important to pay attention to the `TransactionType` field when setting and reading flags. + +Bits that are not defined as flags MUST be 0. (The \[fix1543 amendment]\[] enforces this rule on some transaction types. Most transaction types enforce this rule by default.) + +#### Global Flags + +The only flag that applies globally to all transactions is as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| --------------------- | ------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| `tfFullyCanonicalSig` | `0x80000000` | 2147483648 | **DEPRECATED** No effect. (If the \[RequireFullyCanonicalSig amendment]\[] is not enabled, this flag enforces a fully-canonical signature.) | + +When using the \[sign method]\[] (or \[submit method]\[] in "sign-and-submit" mode), `xahaud` adds a `Flags` field with `tfFullyCanonicalSig` enabled unless the `Flags` field is already present. The `tfFullyCanonicalSig` flag is not automatically enabled if `Flags` is explicitly specified. The flag is not automatically enabled when using the \[sign_for method]\[] to add a signature to a multi-signed transaction. + +**Note:** The `tfFullyCanonicalSig` flag was used from 2014 until 2020 to protect against transaction malleability while maintaining compatibility with legacy signing software. The \[RequireFullyCanonicalSig amendment]\[] ended compatibility with such legacy software and made the protections the default for all transactions. If you are using a parallel network that does not have RequireFullyCanonicalSig enabled, you should always enable the `tfFullyCanonicalSig` flag to protect against transaction malleability. + +#### Flag Ranges + +A transaction's `Flags` field can contain flags that apply at different levels or contexts. Flags for each context are limited to the following ranges: + +| Range Name | Bit Mask | Description | +| ---------------- | ------------ | ---------------------------------------------------------------------------------------------- | +| Universal Flags | `0xff000000` | Flags that apply equally to all transaction types. | +| Type-based Flags | `0x00ff0000` | Flags with different meanings depending on the transaction type that uses them. | +| Reserved Flags | `0x0000ffff` | Flags that are not currently defined. A transaction is only valid if these flags are disabled. | + +**Note:** The \[AccountSet transaction]\[] type has its own non-bitwise flags, which serve a similar purpose to type-based flags. Ledger objects also have a `Flags` field with different bitwise flag definitions. + +### Memos Field + +The `Memos` field includes arbitrary messaging data with the transaction. It is presented as an array of objects. Each object has only one field, `Memo`, which in turn contains another object with _one or more_ of the following fields: + +| Field | Type | \[Internal Type]\[] | Description | +| ------------ | ------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `MemoData` | String | Blob | Arbitrary hex value, conventionally containing the content of the memo. | +| `MemoFormat` | String | Blob | Hex value representing characters allowed in URLs. Conventionally containing information on how the memo is encoded, for example as a [MIME type](http://www.iana.org/assignments/media-types/media-types.xhtml). | +| `MemoType` | String | Blob | Hex value representing characters allowed in URLs. Conventionally, a unique relation (according to [RFC 5988](http://tools.ietf.org/html/rfc5988#section-4)) that defines the format of this memo. | + +The `MemoType` and `MemoFormat` fields should only consist of the following characters: `ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=%` + +The `Memos` field is limited to no more than 1 KB in size (when serialized in binary format). + +Example of a transaction with a Memos field: + +```json +{ + "TransactionType": "Payment", + "Account": "rMmTCjGFRWPz8S2zAUUoNVSQHxtRQD4eCx", + "Destination": "r3kmLJN5D28dHuH8vZNUZpMC43pEHpaocV", + "Memos": [ + { + "Memo": { + "MemoType": "687474703a2f2f6578616d706c652e636f6d2f6d656d6f2f67656e65726963", + "MemoData": "72656e74" + } + } + ], + "Amount": "1" +} +``` + +### NetworkID Field + +\[New in: rippled 1.11.0]\[] + +The `NetworkID` field is a protection against "cross-chain" transaction replay attacks, preventing the same transaction from being copied over and executing on a parallel network that it wasn't intended for. For compatibility with existing chains, the `NetworkID` field must be omitted on any network with a Network ID of 1024 or less, but must be included on any network with a Network ID of 1025 or greater. The following table shows the status and values for various known networks: + +| Network | ID | `NetworkID` Field | +| ------------------------------- | ----- | ---------------------------------------------------- | +| Mainnet | 0 | Disallowed | +| Testnet | 1 | Disallowed | +| Devnet | 2 | Disallowed | +| AMM Devnet | 25 | Disallowed | +| Sidechains Devnet Locking Chain | 2551 | Disallowed, but will become required after an update | +| Sidechains Devnet Issuing Chain | 2552 | Disallowed, but will become required after an update | +| Xahau Testnet | 21338 | Required | +| Xahau Mainnet | 21337 | Required | + +Transaction replay attacks are theoretically possible, but require specific conditions on the second network. All of the following must be true: + +* The transaction's sender is a funded account on the second network. +* The sender's `Sequence` number on the second network matches the transaction's `Sequence`, or the transaction uses a Ticket that's available on the second network. +* Either the transaction does not have a `LastLedgerSequence` field, or it specifies a value that is higher than the current ledger index on the second ledger. + * Mainnet generally has a higher ledger index than test networks or sidechains, so it is easier to replay Mainnet transactions on a sidechain or test network than the other way around, when transactions use `LastLedgerSequence` as intended. +* Either the networks both have IDs of 1024 or less, both networks use the same ID, or the second network does not require the `NetworkID` field. + +### Signers Field + +The `Signers` field contains a multi-signature, which has signatures from up to 8 key pairs, that together should authorize the transaction. The `Signers` list is an array of objects, each with one field, `Signer`. The `Signer` field has the following nested fields: + +| Field | Type | \[Internal Type]\[] | Description | +| --------------- | ------ | ------------------- | ----------------------------------------------------------------------------- | +| `Account` | String | AccountID | The address associated with this signature, as it appears in the signer list. | +| `TxnSignature` | String | Blob | A signature for this transaction, verifiable using the `SigningPubKey`. | +| `SigningPubKey` | String | Blob | The public key used to create this signature. | + +The `SigningPubKey` must be a key that is associated with the `Account` address. If the referenced `Account` is a funded account in the ledger, then the `SigningPubKey` can be that account's current Regular Key if one is set. It could also be that account's Master Key, unless the `lsfDisableMaster` flag is enabled. If the referenced `Account` address is not a funded account in the ledger, then the `SigningPubKey` must be the master key associated with that address. + +Because signature verification is a compute-intensive task, multi-signed transactions cost additional XAH to relay to the network. Each signature included in the multi-signature increases the \[transaction cost]\[] required for the transaction. For example, if the current minimum transaction cost to relay a transaction to the network is `10000` drops, then a multi-signed transaction with 3 entries in the `Signers` array would need a `Fee` value of at least `40000` drops to relay. + +### EmitDetails Fields + +An `EmitDetails` object has the following fields: + +| Field | JSON Type | \[Internal Type]\[] | Required? | Description | +| ----------------- | --------- | ------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `EmitGeneration` | Number | UInt32 | Yes | This field keeps track of a chain of emitted transactions that in turn cause other transactions to be emitted. | +| `EmitBurden` | String | UInt64 | Yes | This field is a heuristic for detecting forkbombs. Fees are based on burden and will increase exponentially when a chain reaction is started to prevent the network becoming overun by self-reinforcing emitted transactions. | +| `EmitParentTxnID` | String | Hash256 | Yes | The Hook Execution that emitted the transaction is connected to the Originating Transaction. Therefore this field is always required for the efficient tracing of behaviour. | +| `EmitNonce` | String | Hash256 | Yes | Emitted Transactions would be identical with the same fields and therefore have identical transaction hashes if a nonce were not used. However every node on the network needs to agree on the nonce, so a special Hook API to produce a deterministic nonce is made available. | +| `EmitCallback` | String | AccountID | No | This field is used by xahld when it needs to intitate a callback, such that it knows which Hook and account to initate the callback on. Callbacks happen when an emitted transaction is accepted into a ledger. | +| `EmitHookHash` | String | Hash256 | Yes | The SHA512H of the Hook at the time it was executed. | + +### Hook Parameters + +The `HookParameters` field is an array of objects that specify the parameters of the hook. Each parameter object has the following fields: + +| Field | JSON Type | Internal Type | Description | +| ------- | --------- | ------------- | --------------------------- | +| `Name` | String | Blob | The name of the parameter. | +| `Value` | String | Blob | The value of the parameter. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-metadata.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-metadata.mdx new file mode 100644 index 0000000..614f522 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-metadata.mdx @@ -0,0 +1,556 @@ +--- +title: Transaction Metadata +--- +Transaction metadata is a section of data that gets added to a transaction after it is processed. Any transaction that gets included in a ledger has metadata, regardless of whether it is successful. The transaction metadata describes the outcome of the transaction in detail. + +:::caution +The changes described in transaction metadata are only final if the transaction is in a validated ledger version. +::: + +
+ +Example Metadata + +The following JSON object shows the metadata for [a complex cross-currency payment](https://xrpcharts.ripple.com/#/transactions/8C55AFC2A2AA42B5CE624AEECDB3ACFDD1E5379D4E5BF74A8460C5E97EF8706B): + +```json +{ + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "r9ZoLsJHzMMJLpvsViWQ4Jgx17N8cz1997", + "Balance": "77349986", + "Flags": 0, + "OwnerCount": 2, + "Sequence": 9 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "1E7E658C2D3DF91EFAE5A12573284AD6F526B8F64DD12F013C6F889EF45BEA97", + "PreviousFields": { + "OwnerCount": 3 + }, + "PreviousTxnID": "55C11248ACEFC2EFD59755BF88867783AC18EA078517108F942069C2FBE4CF5C", + "PreviousTxnLgrSeq": 35707468 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2298.927882138068" + }, + "Flags": 1114112, + "HighLimit": { + "currency": "USD", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "value": "0" + }, + "HighNode": "000000000000006B", + "LowLimit": { + "currency": "USD", + "issuer": "rpvvAvaZ7TXHkNLM8UJwCTU6yBU2jDTJ1P", + "value": "1000000000" + }, + "LowNode": "0000000000000007" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "220DDA7164F3F41F3C5223FA3125D4CD368EBB4FB954B5FBFFB6D1EA6DACDD5E", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2297.927882138068" + } + }, + "PreviousTxnID": "1DB2F9C67C3F42F7B8AB02BA2264254A78A201EC8A9974A1CACEFD51545B1263", + "PreviousTxnLgrSeq": 43081739 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "33403.80553244443" + }, + "Flags": 1114112, + "HighLimit": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "0" + }, + "HighNode": "0000000000001A40", + "LowLimit": { + "currency": "USD", + "issuer": "rd5Sx93pCMgfxwBuofjen2csoFYmY8VrT", + "value": "1000000000" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "38569918AF54B520463CFDDD00EB5ADD8768039BD94E61A5E25C387EA4FDC9A3", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "33402.80752845242" + } + }, + "PreviousTxnID": "38A0E82ADC2DA6C6D59929B73E9812CD1E1384E452FD23D0717EA0037E2FC9E3", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq", + "BookDirectory": "4627DFFCFF8B5A265EDBD8AE8C14A52325DBFEDAF4F5C32E5B09B13AC59DBA5E", + "BookNode": "0000000000000000", + "Flags": 0, + "OwnerNode": "0000000000000000", + "Sequence": 407556, + "TakerGets": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "75.1379833998197" + }, + "TakerPays": "204986996" + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "557BDD35E40EAFFE0AC98108A0F4AC4BB812A168CFD5B4E35475F42A60ABD9C8", + "PreviousFields": { + "TakerGets": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "76.1399833998197" + }, + "TakerPays": "207720593" + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "r9KG7Du7aFmABzMvDnwuvPaEoMu4Eurwok", + "Balance": "8080207629", + "Flags": 0, + "OwnerCount": 6, + "Sequence": 1578765 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "5A667CB5FBAB4143EDEFBD6EDDD4B6D19C905209C8EE16486D5D7CD6CB083E78", + "PreviousFields": { + "Balance": "8080152531", + "Sequence": 1578764 + }, + "PreviousTxnID": "E3CDFD288620871455634DC1E56439136AACA1DDBCE987BE12F97486AB477375", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "DeletedNode": { + "FinalFields": { + "Account": "r9ZoLsJHzMMJLpvsViWQ4Jgx17N8cz1997", + "BookDirectory": "A6D5D1C1CC92D56FDDFD4434FB10BD31F63EB991DA3C756653071AFD498D0000", + "BookNode": "0000000000000000", + "Flags": 0, + "OwnerNode": "0000000000000000", + "PreviousTxnID": "DB028A461E98B0398CAD65F2871B381A6D0B9A21662CA5B033438D83C518C0F2", + "PreviousTxnLgrSeq": 35686129, + "Sequence": 7, + "TakerGets": { + "currency": "EUR", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "2.5" + }, + "TakerPays": { + "currency": "ETH", + "issuer": "rcA8X3TVMST1n3CJeAdGk1RdRCHii7N2h", + "value": "0.05" + } + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "6AA7E5121FEB456F0A899E3D6F25D62ABB408BB67B91C9270E13714401ED72B5" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rd5Sx93pCMgfxwBuofjen2csoFYmY8VrT", + "Balance": "8251028196", + "Flags": 0, + "OwnerCount": 4, + "Sequence": 274 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "6F830A1B38F827CD4BEC946A40F1E2DF726FC22AFC3918FD621567AF17F49F3A", + "PreviousFields": { + "Balance": "8253816902" + }, + "PreviousTxnID": "38A0E82ADC2DA6C6D59929B73E9812CD1E1384E452FD23D0717EA0037E2FC9E3", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rd5Sx93pCMgfxwBuofjen2csoFYmY8VrT", + "BookDirectory": "79C54A4EBD69AB2EADCE313042F36092BE432423CC6A4F784E0CB6D74F25A336", + "BookNode": "0000000000000000", + "Flags": 0, + "OwnerNode": "0000000000000000", + "Sequence": 273, + "TakerGets": "8246341599", + "TakerPays": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "2951.147613535471" + } + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "7FD1EAAE17B7D68AE640FFC56CECC3999B4F938EFFF6EA6887B6CC8BD9DBDC63", + "PreviousFields": { + "TakerGets": "8249130305", + "TakerPays": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "2952.145617527486" + } + }, + "PreviousTxnID": "38A0E82ADC2DA6C6D59929B73E9812CD1E1384E452FD23D0717EA0037E2FC9E3", + "PreviousTxnLgrSeq": 43251694 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-11.68225001668339" + }, + "Flags": 131072, + "HighLimit": { + "currency": "USD", + "issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "value": "5000" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "0" + }, + "LowNode": "000000000000004A" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "826CF5BFD28F3934B518D0BDF3231259CBD3FD0946E3C3CA0C97D2C75D2D1A09", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-10.68225001668339" + } + }, + "PreviousTxnID": "28B271F7C27C1A267F32FFCD8B1795C5D3B1DC761AD705E3A480139AA8B61B09", + "PreviousTxnLgrSeq": 43237130 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq", + "Balance": "8276201534", + "Flags": 0, + "OwnerCount": 5, + "Sequence": 407558 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "880C6FB7B9C0083211F950E4449AD45895C0EC1114B5112CE1320AC7275E3237", + "PreviousFields": { + "Balance": "8273467937" + }, + "PreviousTxnID": "CB4B54942F11510A47D2731C3260429093F24016B366CBF15D8EC4B705372F02", + "PreviousTxnLgrSeq": 43251683 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-6557.745685633666" + }, + "Flags": 2228224, + "HighLimit": { + "currency": "USD", + "issuer": "rBndiPPKs9k5rjBb7HsEiqXKrz8AfUnqWq", + "value": "1000000000" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "USD", + "issuer": "rvYAfWj5gh67oV6fW32ZzP3Aw4Eubs59B", + "value": "0" + }, + "LowNode": "0000000000000512" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "8A9FEE5192E334195314B5C162BC78F7452ADB14E06839D48943BAE05EE1967F", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "-6558.747685633666" + } + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "GCB", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "9990651675.348776" + }, + "Flags": 3211264, + "HighLimit": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "0" + }, + "HighNode": "0000000000000000", + "LowLimit": { + "currency": "GCB", + "issuer": "r9KG7Du7aFmABzMvDnwuvPaEoMu4Eurwok", + "value": "10000000000" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "A2B41EE7818A5756B6A2276BDBB3CE0ED3A3B350787FD6B76E5EA1354A8F20D2", + "PreviousFields": { + "Balance": { + "currency": "GCB", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "9990651678.137482" + } + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "DeletedNode": { + "FinalFields": { + "ExchangeRate": "53071AFD498D0000", + "Flags": 0, + "RootIndex": "A6D5D1C1CC92D56FDDFD4434FB10BD31F63EB991DA3C756653071AFD498D0000", + "TakerGetsCurrency": "0000000000000000000000004555520000000000", + "TakerGetsIssuer": "2ADB0B3959D60A6E6991F729E1918B7163925230", + "TakerPaysCurrency": "0000000000000000000000004554480000000000", + "TakerPaysIssuer": "06CC4A6D023E68AA3499C6DE3E9F2DC52B8BA254" + }, + "LedgerEntryType": "DirectoryNode", + "LedgerIndex": "A6D5D1C1CC92D56FDDFD4434FB10BD31F63EB991DA3C756653071AFD498D0000" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Flags": 0, + "Owner": "r9ZoLsJHzMMJLpvsViWQ4Jgx17N8cz1997", + "RootIndex": "A83C1B192A27582EDB320EBD7A3FE58D7042CE04B67A2B3D87FDD63D871E12D7" + }, + "LedgerEntryType": "DirectoryNode", + "LedgerIndex": "A83C1B192A27582EDB320EBD7A3FE58D7042CE04B67A2B3D87FDD63D871E12D7" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "0" + }, + "Flags": 65536, + "HighLimit": { + "currency": "USD", + "issuer": "rLEsXccBGNR3UPuPu2hUXPjziKC3qKSBun", + "value": "0" + }, + "HighNode": "0000000000000002", + "LowLimit": { + "currency": "USD", + "issuer": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "value": "1" + }, + "LowNode": "0000000000000000" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "C493ABA2619D0FC6355BA862BC8312DF8266FBE76AFBA9636E857F7EAC874A99", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "1" + } + }, + "PreviousTxnID": "28B271F7C27C1A267F32FFCD8B1795C5D3B1DC761AD705E3A480139AA8B61B09", + "PreviousTxnLgrSeq": 43237130 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "r9KG7Du7aFmABzMvDnwuvPaEoMu4Eurwok", + "BookDirectory": "E6E8A9842EA2ED1FD5D0599343692CE1EBF977AEA751B7DC5B038D7EA4C68000", + "BookNode": "0000000000000000", + "Flags": 65536, + "OwnerNode": "0000000000000000", + "Sequence": 39018, + "TakerGets": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "9990651675.348776" + }, + "TakerPays": "9990651675348776" + }, + "LedgerEntryType": "Offer", + "LedgerIndex": "C939B9B2C5803DD6D89B792E72470F79CBE9F9E999691789E0B68C3808BDDD8E", + "PreviousFields": { + "TakerGets": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "9990651678.137482" + }, + "TakerPays": "9990651678137482" + }, + "PreviousTxnID": "961C575073788979815F103D065CEE449D2EA6EFE8FC8C33C26EC08586925D90", + "PreviousTxnLgrSeq": 43251680 + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2963.413395452545" + }, + "Flags": 65536, + "HighLimit": { + "currency": "USD", + "issuer": "rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq", + "value": "0" + }, + "HighNode": "0000000000001A97", + "LowLimit": { + "currency": "USD", + "issuer": "rpvvAvaZ7TXHkNLM8UJwCTU6yBU2jDTJ1P", + "value": "0" + }, + "LowNode": "0000000000000007" + }, + "LedgerEntryType": "RippleState", + "LedgerIndex": "E4D1FBD5CB72A1D3EE38C21F3BCB13E454FCB469CD01C1366E0008A031E6A7FC", + "PreviousFields": { + "Balance": { + "currency": "USD", + "issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji", + "value": "2964.413395452545" + } + }, + "PreviousTxnID": "1DB2F9C67C3F42F7B8AB02BA2264254A78A201EC8A9974A1CACEFD51545B1263", + "PreviousTxnLgrSeq": 43081739 + } + } + ], + "DeliveredAmount": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "2.788706" + }, + "TransactionIndex": 38, + "TransactionResult": "tesSUCCESS", + "delivered_amount": { + "currency": "GCB", + "issuer": "rHaans8PtgwbacHvXAL3u6TG28gTAtCwr8", + "value": "2.788706" + } +} +``` + + + +
+ +### AffectedNodes + +The `AffectedNodes` array contains a complete list of the objects in the ledger that this transaction modified in some way. Each entry in this array is an object with one top-level field indicating what type it is: + +* `CreatedNode` indicates that the transaction created a new object in the ledger. +* `DeletedNode` indicates that the transaction removed an object from the ledger. +* `ModifiedNode` indicates that the transaction modified an existing object in the ledger. + +The value of each of these fields is a JSON object describing the changes made to the ledger object. + +#### CreatedNode Fields + +A `CreatedNode` object contains the following fields: + +| Field | Value | Description | +| ----------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `LedgerEntryType` | String | The type of ledger object that was created. | +| `LedgerIndex` | String - \[Hash]\[] | The ID of this ledger object in the ledger's state tree. **Note:** This is **not the same** as a ledger index, even though the field name is very similar. | +| `NewFields` | Object | The content fields of the newly-created ledger object. Which fields are present depends on what type of ledger object was created. | + +#### DeletedNode Fields + +A `DeletedNode` object contains the following fields: + +| Field | Value | Description | +| ----------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `LedgerEntryType` | String | The type of ledger object that was deleted. | +| `LedgerIndex` | String - \[Hash]\[] | The ID of this ledger object in the ledger's state tree. **Note:** This is **not the same** as a ledger index, even though the field name is very similar. | +| `FinalFields` | Object | The content fields of the ledger object immediately before it was deleted. Which fields are present depends on what type of ledger object was created. | + +#### ModifiedNode Fields + +A `ModifiedNode` object contains the following fields: + +| Field | Value | Description | +| ------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `LedgerEntryType` | String | The type of ledger object that was deleted. | +| `LedgerIndex` | String - \[Hash]\[] | The ID of this ledger object in the ledger's state tree. **Note:** This is **not the same** as a ledger index, even though the field name is very similar. | +| `FinalFields` | Object | The content fields of the ledger object after applying any changes from this transaction. Which fields are present depends on what type of ledger object was created. This omits the `PreviousTxnID` and `PreviousTxnLgrSeq` fields, even though most types of ledger objects have them. | +| `PreviousFields` | Object | The previous values for all fields of the object that were changed as a result of this transaction. If the transaction _only added_ fields to the object, this field is an empty object. | +| `PreviousTxnID` | String - \[Hash]\[] | _(May be omitted)_ The \[identifying hash]\[] of the previous transaction to modify this ledger object. Omitted for ledger object types that do not have a `PreviousTxnID` field. | +| `PreviousTxnLgrSeq` | Number - \[Ledger Index]\[] | _(May be omitted)_ The \[Ledger Index]\[] of the ledger version containing the previous transaction to modify this ledger object. Omitted for ledger object types that do not have a `PreviousTxnLgrSeq` field. | + +**Note:** If the modified ledger object has `PreviousTxnID` and `PreviousTxnLgrSeq` fields, the transaction always updates them with the transaction's own identifying hash and the index of the ledger version that included the transaction, but these fields' new value is not listed in the `FinalFields` of the `ModifiedNode` object, and their previous values are listed at the top level of the `ModifiedNode` object rather than in the nested `PreviousFields` object. + +### delivered_amount + +The `Amount` of a \[Payment transaction]\[] indicates the amount to deliver to the `Destination`, so if the transaction was successful, then the destination received that much -- **except if the transaction was a partial payment**. (In that case, any positive amount up to `Amount` might have arrived.) Rather than choosing whether or not to trust the `Amount` field, you should use the `delivered_amount` field of the metadata to see how much actually reached its destination. + +The `rippled` server provides a `delivered_amount` field in JSON transaction metadata for all successful Payment transactions. This field is formatted like a normal currency amount. However, the delivered amount is not available for transactions that meet both of the following criteria: + +* Is a partial payment + +If the tx is a partial payment, then `delivered_amount` contains the string value `unavailable` instead of an actual amount. If this happens, you can only figure out the actual delivered amount by reading the `AffectedNodes` in the transaction's metadata. + +**Note:** The `delivered_amount` field is generated on-demand for the request, and is not included in the binary format for transaction metadata, nor is it used when calculating the hash of the transaction metadata. + +See also: Partial Payments diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/index.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/index.mdx new file mode 100644 index 0000000..90e40ec --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/index.mdx @@ -0,0 +1,45 @@ +--- +title: Transaction Results +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/protocol/TER.h) + +The `rippled` server summarizes transaction results with result codes, which appear in fields such as `engine_result` and `meta.TransactionResult`. These codes are grouped into several categories with different prefixes: + +| Category | Prefix | Description | +| --------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Claimed cost only | `tec` | The transaction did not achieve its intended purpose, but the transaction cost was destroyed. This result is only final in a validated ledger. | +| Failure | `tef` | The transaction cannot be applied to the server's current (in-progress) ledger or any later one. It may have already been applied, or the condition of the ledger makes it impossible to apply in the future. | +| Local error | `tel` | The `rippled` server had an error due to local conditions, such as high load. You may get a different response if you resubmit to a different server or at a different time. | +| Malformed transaction | `tem` | The transaction was not valid, due to improper syntax, conflicting options, a bad signature, or something else. | +| Retry | `ter` | The transaction could not be applied, but it could apply successfully in a future ledger. | +| Success | `tes` | (Not an error) The transaction succeeded. This result only final in a validated ledger. | + +The `rippled` server automatically retries failed transactions. It is important not to assume that a transaction has completely failed based on a tentative failure result. A transaction may later succeed unless its success or failure is final. + +**Warning:** Transactions' provisional result codes may differ from their final result. Transactions that provisionally succeeded may eventually fail and transactions that provisionally failed may eventually succeed. Transactions that provisionally failed may also eventually fail with a different code. See the finality of results for how to know when a transaction's result is final. + +The distinction between a local error (`tel`) and a malformed transaction (`tem`) is a matter of protocol-level rules. For example, the protocol sets no limit on the maximum number of paths that can be included in a transaction. However, a server may define a finite limit of paths it can process. If two different servers are configured differently, then one of them may return a `tel` error for a transaction with many paths, while the other server could successfully process the transaction. If enough servers are able to process the transaction so that it survives consensus, then it can still be included in a validated ledger. + +By contrast, a `tem` error implies that no server anywhere can apply the transaction, regardless of settings. Either the transaction breaks the rules of the protocol, it is unacceptably ambiguous, or it is completely nonsensical. The only way a malformed transaction could become valid is through changes in the protocol; for example, if a new feature is adopted, then transactions using that feature could be considered malformed by servers that are running older software which predates that feature. + +### Immediate Response + +The response from the \[submit method]\[] contains a provisional result from the `rippled` server indicating what happened during the local processing of the transaction. + +The response from `submit` contains the following fields: + +| Field | Value | Description | +| ----------------------- | -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `engine_result` | String | A code indicating the outcome of the transaction, such as `tecPATH_DRY`. | +| `engine_result_code` | Signed Integer | A number that corresponds to the `engine_result`. The exact values are subject to change without notice. | +| `engine_result_message` | String | A human-readable message explaining what happened. This message is intended for developers to diagnose problems, and is subject to change without notice. | + +If nothing went wrong when submitting and applying the transaction locally, the response looks like this: + +```js + "engine_result": "tesSUCCESS", + "engine_result_code": 0, + "engine_result_message": "The transaction was applied. Only final in a validated ledger." +``` + +**Note:** A successful result at this stage does not indicate that the transaction has completely succeeded; only that it was successfully applied to the provisional version of the ledger kept by the local server. Failed results at this stage are also provisional and may change. See Finality of Results for details. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/tec-codes.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tec-codes.mdx new file mode 100644 index 0000000..200f5fc --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tec-codes.mdx @@ -0,0 +1,60 @@ +--- +title: TEC Codes +--- +These codes indicate that the transaction failed, but it was applied to a ledger to apply the transaction cost. They have numerical values in the range 100 to 199. It is recommended to use the text code, not the numeric value. + +Transactions with `tec` codes destroy the XAH paid as a transaction cost and consume a sequence number. For the most part, the transactions take no other action, but there are some exceptions. For example, a transaction that results in `tecOVERSIZE` still cleans up some unfunded offers. Always look at the transaction metadata to see precisely what a transaction did. + +**Caution:** A transaction that provisionally failed with a `tec` code may still succeed or fail with a different code after being reapplied. The result is final when it appears in a validated ledger version. For more information, see Finality of Results and Reliable Transaction Submission. + +| Code | Value | Explanation | +| ---------------------------------- | ----- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tecCANT_ACCEPT_OWN_NFTOKEN_OFFER` | 157 | The transaction tried to accept an offer that was placed by the same account to buy or sell a non-fungible token. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecCLAIM` | 100 | Unspecified failure, with transaction cost destroyed. | +| `tecCRYPTOCONDITION_ERROR` | 146 | This \[EscrowCreate]\[] or \[EscrowFinish]\[] transaction contained a malformed or mismatched crypto-condition. | +| `tecDIR_FULL` | 121 | The transaction tried to add an object (such as a trust line, Check, Escrow, or Payment Channel) to an account's owner directory, but that account cannot own any more objects in the ledger. | +| `tecDUPLICATE` | 149 | The transaction tried to create an object (such as a \[DepositPreauth]\[] authorization) that already exists. | +| `tecDST_TAG_NEEDED` | 143 | The \[Payment transaction]\[] omitted a destination tag, but the destination account has the `lsfRequireDestTag` flag enabled. \[New in: rippled 0.28.0]\[] | +| `tecEXPIRED` | 148 | The transaction tried to create an object (such as an Offer or a Check) whose provided Expiration time has already passed. | +| `tecFAILED_PROCESSING` | 105 | An unspecified error occurred when processing the transaction. | +| `tecFROZEN` | 137 | The \[OfferCreate transaction]\[] failed because one or both of the assets involved are subject to a global freeze. | +| `tecHAS_OBLIGATIONS` | 151 | The \[AccountDelete transaction]\[] failed because the account to be deleted owns objects that cannot be deleted. See Deletion of Accounts for details. | +| `tecINSUF_RESERVE_LINE` | 122 | The transaction failed because the sending account does not have enough XAH to create a new trust line. (See: Reserves) This error occurs when the counterparty already has a trust line in a non-default state to the sending account for the same currency. (See `tecNO_LINE_INSUF_RESERVE` for the other case.) | +| `tecINSUF_RESERVE_OFFER` | 123 | The transaction failed because the sending account does not have enough XAH to create a new Offer. (See: Reserves) | +| `tecINSUFF_FEE` | 136 | The transaction failed because the sending account does not have enough XAH to pay the transaction cost that it specified. (In this case, the transaction processing destroys all of the sender's XAH even though that amount is lower than the specified transaction cost.) This result only occurs if the account's balance decreases _after_ this transaction has been distributed to enough of the network to be included in a consensus set. Otherwise, the transaction fails with `terINSUF_FEE_B` before being distributed. | +| `tecINSUFFICIENT_FUNDS` | 158 | One of the accounts involved does not hold enough of a necessary asset. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecINSUFFICIENT_PAYMENT` | 161 | The amount specified is not enough to pay all fees involved in the transaction. For example, when trading a non-fungible token, the buy amount may not be enough to pay both the broker fee and the sell amount. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecINSUFFICIENT_RESERVE` | 141 | The transaction would increase the reserve requirement higher than the sending account's balance. \[SignerListSet]\[], \[PaymentChannelCreate]\[], \[PaymentChannelFund]\[], and \[EscrowCreate]\[] can return this error code. See Signer Lists and Reserves for more information. | +| `tecINTERNAL` | 144 | Unspecified internal error, with transaction cost applied. This error code should not normally be returned. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues). | +| `tecINVARIANT_FAILED` | 147 | An invariant check failed when trying to execute this transaction. Added by the \[EnforceInvariants amendment]\[]. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues). | +| `tecKILLED` | 150 | The \[OfferCreate transaction]\[] specified the `tfFillOrKill` flag and could not be filled, so it was killed. _(Added by the \[fix1578 amendment]\[].)_ | +| `tecMAX_SEQUENCE_REACHED` | 153 | A sequence number field is already at its maximum. This includes the `MintedNFTokens` field. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecNEED_MASTER_KEY` | 142 | This transaction tried to cause changes that require the master key, such as disabling the master key or giving up the ability to freeze balances. \[New in: rippled 0.28.0]\[] | +| `tecNFTOKEN_BUY_SELL_MISMATCH` | 155 | The \[NFTokenAcceptOffer transaction]\[] attempted to match incompatible offers to buy and sell a non-fungible token. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecNFTOKEN_OFFER_TYPE_MISMATCH` | 156 | One or more of the offers specified in the transaction was not the right type of offer. (For example, a buy offer was specified in the `NFTokenSellOffer` field.) _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecNO_ALTERNATIVE_KEY` | 130 | The transaction tried to remove the only available method of authorizing transactions. This could be a \[SetRegularKey transaction]\[] to remove the regular key, a \[SignerListSet transaction]\[] to delete a SignerList, or an \[AccountSet transaction]\[] to disable the master key. (Prior to `rippled` 0.30.0, this was called `tecMASTER_DISABLED`.) | +| `tecNO_AUTH` | 134 | The transaction failed because it needs to add a balance on a trust line to an account with the `lsfRequireAuth` flag enabled, and that trust line has not been authorized. If the trust line does not exist at all, `tecNO_LINE` occurs instead. | +| `tecNO_DST` | 124 | The account on the receiving end of the transaction does not exist. This includes Payment and TrustSet transaction types. (It could be created if it received enough XAH.) | +| `tecNO_DST_INSUF_NATIVE` | 125 | The account on the receiving end of the transaction does not exist, and the transaction is not sending enough XAH to create it. | +| `tecNO_ENTRY` | 140 | The transaction tried to modify a ledger object, such as a Check, Payment Channel, or Deposit Preauthorization, but the specified object does not exist. It may have already been deleted by a previous transaction or the transaction may have an incorrect value in an ID field such as `CheckID`, `Channel`, `Unauthorize`. | +| `tecNO_ISSUER` | 133 | The account specified in the `issuer` field of a currency amount does not exist. | +| `tecNO_LINE` | 135 | The `TakerPays` field of the \[OfferCreate transaction]\[] specifies an asset whose issuer has `lsfRequireAuth` enabled, and the account making the offer does not have a trust line for that asset. (Normally, making an offer implicitly creates a trust line if necessary, but in this case it does not bother because you cannot hold the asset without authorization.) If the trust line exists, but is not authorized, `tecNO_AUTH` occurs instead. | +| `tecNO_LINE_INSUF_RESERVE` | 126 | The transaction failed because the sending account does not have enough XAH to create a new trust line. (See: Reserves) This error occurs when the counterparty does not have a trust line to this account for the same currency. (See `tecINSUF_RESERVE_LINE` for the other case.) | +| `tecNO_LINE_REDUNDANT` | 127 | The transaction failed because it tried to set a trust line to its default state, but the trust line did not exist. | +| `tecNO_PERMISSION` | 139 | The sender does not have permission to do this operation. For example, the \[EscrowFinish transaction]\[] tried to release a held payment before its `FinishAfter` time, someone tried to use \[PaymentChannelFund]\[] on a channel the sender does not own, or a \[Payment]\[] tried to deliver funds to an account with the "DepositAuth" flag enabled. | +| `tecNO_REGULAR_KEY` | 131 | The \[AccountSet transaction]\[] tried to disable the master key, but the account does not have another way to authorize transactions. If multi-signing is enabled, this code is deprecated and `tecNO_ALTERNATIVE_KEY` is used instead. | +| `tecNO_SUITABLE_NFTOKEN_PAGE` | 154 | The transaction tried to mint or acquire a non-fungible token but the account receiving the `NFToken` does not have a directory page that can hold it. This situation is rare. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecNO_TARGET` | 138 | The transaction referenced an Escrow or PayChannel ledger object that doesn't exist, either because it never existed or it has already been deleted. (For example, another \[EscrowFinish transaction]\[] has already executed the held payment.) Alternatively, the destination account has `asfDisallowXAH` set so it cannot be the destination of this \[PaymentChannelCreate]\[] or \[EscrowCreate]\[] transaction. | +| `tecOBJECT_NOT_FOUND` | 160 | One of the objects specified by this transaction did not exist in the ledger. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tecOVERSIZE` | 145 | This transaction could not be processed, because the server created an excessively large amount of metadata when it tried to apply the transaction. \[New in: rippled 0.29.0-hf1]\[] | +| `tecOWNERS` | 132 | The transaction cannot succeed because the sender already owns objects in the ledger. For example, an account cannot enable the `lsfRequireAuth` flag if it has any trust lines or available offers. | +| `tecPATH_DRY` | 128 | The transaction failed because the provided paths did not have enough liquidity to send anything at all. This could mean that the source and destination accounts are not linked by trust lines. | +| `tecPATH_PARTIAL` | 101 | The transaction failed because the provided paths did not have enough liquidity to send the full amount. | +| `tecTOO_SOON` | 152 | The \[AccountDelete transaction]\[] failed because the account to be deleted had a `Sequence` number that is too high. The current ledger index must be at least 256 higher than the account's sequence number. | +| `tecUNFUNDED` | 129 | The transaction failed because the account does not hold enough XAH to pay the amount in the transaction _and_ satisfy the additional reserve necessary to execute this transaction. | +| `tecUNFUNDED_ADD` | 102 | **DEPRECATED.** | +| `tecUNFUNDED_PAYMENT` | 104 | The transaction failed because the sending account is trying to send more XAH than it holds, not counting the reserve. | +| `tecUNFUNDED_OFFER` | 103 | The \[OfferCreate transaction]\[] failed because the account creating the offer does not have any of the `TakerGets` currency. | +| `tecREQUIRES_FLAG` | 169 | The SetHook transaction]\[] failed because of an incorrect Flag and Field combination. | +| `tecPRECISION_LOSS` | 170 | The transaction failed because the result would end with significant precision loss. | + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/tef-codes.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tef-codes.mdx new file mode 100644 index 0000000..3bddec6 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tef-codes.mdx @@ -0,0 +1,33 @@ +--- +title: TEF Codes +--- +These codes indicate that the transaction failed and was not included in a ledger, but the transaction could have succeeded in some theoretical ledger. Typically this means that the transaction can no longer succeed in any future ledger. They have numerical values in the range of -199 to -100. The exact code for any given error is subject to change, so don't rely on it. + +**Caution:** Transactions with `tef` codes are not applied to ledgers and cannot cause any changes to the Xahau state. However, a transaction that provisionally failed may still succeed or fail with a different code after being reapplied. For more information, see Finality of Results and Reliable Transaction Submission. + +| Code | Explanation | +| -------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tefALREADY` | The same exact transaction has already been applied. | +| `tefBAD_ADD_AUTH` | **DEPRECATED.** | +| `tefBAD_AUTH` | The key used to sign this account is not authorized to modify this account. (It could be authorized if the account had the same key set as the Regular Key.) | +| `tefBAD_AUTH_MASTER` | The single signature provided to authorize this transaction does not match the master key, but no regular key is associated with this address. | +| `tefBAD_LEDGER` | While processing the transaction, the ledger was discovered in an unexpected state. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues) to get it fixed. | +| `tefBAD_QUORUM` | The transaction was multi-signed, but the total weights of all included signatures did not meet the quorum. | +| `tefBAD_SIGNATURE` | The transaction was multi-signed, but contained a signature for an address not part of a SignerList associated with the sending account. | +| `tefCREATED` | **DEPRECATED.** | +| `tefEXCEPTION` | While processing the transaction, the server entered an unexpected state. This may be caused by unexpected inputs, for example if the binary data for the transaction is grossly malformed. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues) to get it fixed. | +| `tefFAILURE` | Unspecified failure in applying the transaction. | +| `tefINTERNAL` | When trying to apply the transaction, the server entered an unexpected state. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues) to get it fixed. | +| `tefINVARIANT_FAILED` | An invariant check failed when trying to claim the transaction cost. Added by the \[EnforceInvariants amendment]\[]. If you can reproduce this error, please [report an issue](https://github.com/ripple/rippled/issues). | +| `tefMASTER_DISABLED` | The transaction was signed with the account's master key, but the account has the `lsfDisableMaster` field set. | +| `tefMAX_LEDGER` | The transaction included a `LastLedgerSequence` parameter, but the current ledger's sequence number is already higher than the specified value. | +| `tefNFTOKEN_IS_NOT_TRANSFERABLE` | The transaction attempted to send a non-fungible token to another account, but the `NFToken` has the `lsfTransferable` flag disabled and the transfer would not be to or from the issuer. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `tefNO_AUTH_REQUIRED` | The \[TrustSet transaction]\[] tried to mark a trust line as authorized, but the `lsfRequireAuth` flag is not enabled for the corresponding account, so authorization is not necessary. | +| `tefNO_TICKET` | The transaction attempted to use a Ticket, but the specified `TicketSequence` number does not exist in the ledger, and cannot be created in the future because it is earlier than the sender's current sequence number. | +| `tefNOT_MULTI_SIGNING` | The transaction was multi-signed, but the sending account has no SignerList defined. | +| `tefPAST_SEQ` | The sequence number of the transaction is lower than the current sequence number of the account sending the transaction. | +| `tefTOO_BIG` | The transaction would affect too many objects in the ledger. For example, this was an \[AccountDelete transaction]\[] but the account to be deleted owns over 1000 objects in the ledger. | +| `tefWRONG_PRIOR` | The transaction contained an `AccountTxnID` field (or the deprecated `PreviousTxnID` field), but the transaction specified there does not match the account's previous transaction. | +| `tefPAST_IMPORT_SEQ` | The transaction failed because the import sequence number has already been used. | +| `tefPAST_IMPORT_VL_SEQ` | The transaction failed because the import validator list sequence number has already been used. | + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/tel-codes.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tel-codes.mdx new file mode 100644 index 0000000..ca30aeb --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tel-codes.mdx @@ -0,0 +1,29 @@ +--- +title: TEL Codes +--- +These codes indicate an error in the local server processing the transaction; it is possible that another server with a different configuration or load level could process the transaction successfully. They have numerical values in the range of -399 to -300. The exact code for any given error is subject to change, so don't rely on it. + +**Caution:** Transactions with `tel` codes are not applied to ledgers and cannot cause any changes to the Xahau state. However, these transactions may be automatically cached and retried later. Transactions that provisionally failed may still succeed or fail with a different code after being reapplied. For more information, see Finality of Results and Reliable Transaction Submission. + +| Code | Explanation | +| -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `telBAD_DOMAIN` | The transaction specified a domain value (for example, the `Domain` field of an \[AccountSet transaction]\[]) that cannot be used, probably because it is too long to store in the ledger. | +| `telBAD_PATH_COUNT` | The transaction contains too many paths for the local server to process. | +| `telBAD_PUBLIC_KEY` | The transaction specified a public key value (for example, as the `MessageKey` field of an \[AccountSet transaction]\[]) that cannot be used, probably because it is not the right length. | +| `telCAN_NOT_QUEUE` | The transaction did not meet the open ledger cost, but this server did not queue this transaction because it did not meet the queuing restrictions. For example, a transaction returns this code when the sender already has 10 other transactions in the queue. You can try again later or sign and submit a replacement transaction with a higher transaction cost in the `Fee` field. | +| `telCAN_NOT_QUEUE_BALANCE` | The transaction did not meet the open ledger cost and also was not added to the transaction queue because the sum of potential XAH costs of already-queued transactions is greater than the expected balance of the account. You can try again later, or try submitting to a different server. \[New in: rippled 0.70.2]\[] | +| `telCAN_NOT_QUEUE_BLOCKS` | The transaction did not meet the open ledger cost and also was not added to the transaction queue. This transaction could not replace an existing transaction in the queue because it would block already-queued transactions from the same sender by changing authorization methods. (This includes all \[SetRegularKey]\[] and \[SignerListSet]\[] transactions, as well as \[AccountSet]\[] transactions that change the `RequireAuth`/`OptionalAuth`, `DisableMaster`, or `AccountTxnID` flags.) You can try again later, or try submitting to a different server. \[New in: rippled 0.70.2]\[] | +| `telCAN_NOT_QUEUE_BLOCKED` | The transaction did not meet the open ledger cost and also was not added to the transaction queue because a transaction queued ahead of it from the same sender blocks it. (This includes all \[SetRegularKey]\[] and \[SignerListSet]\[] transactions, as well as \[AccountSet]\[] transactions that change the `RequireAuth`/`OptionalAuth`, `DisableMaster`, or `AccountTxnID` flags.) You can try again later, or try submitting to a different server. \[New in: rippled 0.70.2]\[] | +| `telCAN_NOT_QUEUE_FEE` | The transaction did not meet the open ledger cost and also was not added to the transaction queue. This code occurs when a transaction with the same sender and sequence number already exists in the queue and the new one does not pay a large enough transaction cost to replace the existing transaction. To replace a transaction in the queue, the new transaction must have a `Fee` value that is at least 25% more, as measured in fee levels. You can increase the `Fee` and try again, send this with a higher `Sequence` number so it doesn't replace an existing transaction, or try sending to another server. \[New in: rippled 0.70.2]\[] | +| `telCAN_NOT_QUEUE_FULL` | The transaction did not meet the open ledger cost and the server did not queue this transaction because this server's transaction queue is full. You could increase the `Fee` and try again, try again later, or try submitting to a different server. The new transaction must have a higher transaction cost, as measured in fee levels, than the transaction in the queue with the smallest transaction cost. \[New in: rippled 0.70.2]\[] | +| `telFAILED_PROCESSING` | An unspecified error occurred when processing the transaction. | +| `telINSUF_FEE_P` | The `Fee` from the transaction is not high enough to meet the server's current transaction cost requirement, which is derived from its load level and network-level requirements. If the individual server is too busy to process your transaction right now, it may cache the transaction and automatically retry later. | +| `telLOCAL_ERROR` | Unspecified local error. | +| `telNO_DST`_`PARTIAL` | The transaction is an XAH payment that would fund a new account, but the `tfPartialPayment` flag was enabled. This is disallowed. | +| `telWRONG_NETWORK` | The transaction specifies the wrong `NetworkID` value for the current network. Either specify the correct the `NetworkID` value for the intended network, or submit the transaction to a server that is connected to the correct network. | +| `tel_REQUIRES_NETWORK_ID` | The transaction does not specify a `NetworkID` field, but the current network requires one. If the transaction was intended for a network that requires `NetworkID`, add the field and try again. If the transaction was intended for a different network, submit it to a server that is connected to the correct network. | +| `telNETWORK_ID_MAKES_TX_NON_CANONICAL` | The transaction specified a `NetworkID` field, but the current network requires that the `NetworkID` is not submitted. | +| `telNON_LOCAL_EMITTED_TXN` | The emitted transaction cannot be applied because it was not generated locally. | +| `telIMPORT_VL_KEY_NOT_RECOGNISED` | The transaction was signed on a different network or the transaction was submitted to the wrong network. For `Import` transactions the validations must match the vl keys on receiving network. | +| `telCAN_NOT_QUEUE_IMPORT` | `Import` transaction was not able to be directly applied and cannot be queued. | + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/tem-codes.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tem-codes.mdx new file mode 100644 index 0000000..742b391 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tem-codes.mdx @@ -0,0 +1,46 @@ +--- +title: TEM Codes +--- +These codes indicate that the transaction was malformed, and cannot succeed according to the Xahau protocol. They have numerical values in the range of -299 to -200. The exact code for any given error is subject to change, so don't rely on it. + +**Tip:** Transactions with `tem` codes are not applied to ledgers, and cannot cause any changes to the Xahau state. A `tem` result is final unless the rules for a valid transaction change. (For example, using functionality from an Amendment before that amendment is enabled results in `temDISABLED`; such a transaction could succeed later if it becomes valid when the amendment is enabled.) + +| Code | Explanation | +| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `temBAD_AMOUNT` | An amount specified by the transaction (for example the destination `Amount` or `SendMax` values of a \[Payment]\[]) was invalid, possibly because it was a negative number. | +| `temBAD_AUTH_MASTER` | The key used to sign this transaction does not match the master key for the account sending it, and the account does not have a Regular Key set. | +| `temBAD_CURRENCY` | The transaction improperly specified a currency field. See \[Specifying Currency Amounts]\[Currency Amount] for the correct format. | +| `temBAD_EXPIRATION` | The transaction improperly specified an expiration value, for example as part of an \[OfferCreate transaction]\[]. Alternatively, the transaction did not specify a required expiration value, for example as part of an \[EscrowCreate transaction]\[]. | +| `temBAD_FEE` | The transaction improperly specified its `Fee` value, for example by listing a non-XAH currency or some negative amount of XAH. | +| `temBAD_ISSUER` | The transaction improperly specified the `issuer` field of some currency included in the request. | +| `temBAD_LIMIT` | The \[TrustSet transaction]\[] improperly specified the `LimitAmount` value of a trust line. | +| `temBAD_NFTOKEN_TRANSFER_FEE` | The \[NFTokenMint transaction]\[] improperly specified the `TransferFee` field of the transaction. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `temBAD_OFFER` | The \[OfferCreate transaction]\[] specifies an invalid offer, such as offering to trade XAH for itself, or offering a negative amount. | +| `temBAD_PATH` | The \[Payment transaction]\[] specifies one or more Paths improperly, for example including an issuer for XAH, or specifying an account differently. | +| `temBAD_PATH_LOOP` | One of the Paths in the \[Payment transaction]\[] was flagged as a loop, so it cannot be processed in a bounded amount of time. | +| `temBAD_SEND_NATIVE_LIMIT` | The \[Payment transaction]\[] used the `tfLimitQuality` flag in a direct XAH-to-XAH payment, even though XAH-to-XAH payments do not involve any conversions. | +| `temBAD_SEND_NATIVE_MAX` | The \[Payment transaction]\[] included a `SendMax` field in a direct XAH-to-XAH payment, even though sending XAH should never require `SendMax`. (XAH is only valid in `SendMax` if the destination `Amount` is not XAH.) | +| `temBAD_SEND_NATIVE_NO_DIRECT` | The \[Payment transaction]\[] used the `tfNoDirectRipple` flag for a direct XAH-to-XAH payment, even though XAH-to-XAH payments are always direct. | +| `temBAD_SEND_NATIVE_PARTIAL` | The \[Payment transaction]\[] used the `tfPartialPayment` flag for a direct XAH-to-XAH payment, even though XAH-to-XAH payments should always deliver the full amount. | +| `temBAD_SEND_NATIVE_PATHS` | The \[Payment transaction]\[] included `Paths` while sending XAH, even though XAH-to-XAH payments should always be direct. | +| `temBAD_SEQUENCE` | The transaction is references a sequence number that is higher than its own `Sequence` number, for example trying to cancel an offer that would have to be placed after the transaction that cancels it. | +| `temBAD_SIGNATURE` | The signature to authorize this transaction is either missing, or formed in a way that is not a properly-formed signature. (See `tecNO_PERMISSION` for the case where the signature is properly formed, but not authorized for this account.) | +| `temBAD_SRC_ACCOUNT` | The `Account` on whose behalf this transaction is being sent (the "source account") is not a properly-formed account address. | +| `temBAD_TRANSFER_RATE` | The `TransferRate` field of an AccountSet transaction is not properly formatted or out of the acceptable range. | +| `temCANNOT_PREAUTH_SELF` | The sender of the \[DepositPreauth transaction]\[] was also specified as the account to preauthorize. You cannot preauthorize yourself. | +| `temDST_IS_SRC` | The transaction improperly specified a destination address as the `Account` sending the transaction. This includes trust lines (where the destination address is the `issuer` field of `LimitAmount`) and payment channels (where the destination address is the `Destination` field). | +| `temDST_NEEDED` | The transaction improperly omitted a destination. This could be the `Destination` field of a \[Payment transaction]\[], or the `issuer` sub-field of the `LimitAmount` field fo a `TrustSet` transaction. | +| `temINVALID` | The transaction is otherwise invalid. For example, the transaction ID may not be the right format, the signature may not be formed properly, or something else went wrong in understanding the transaction. | +| `temINVALID_COUNT` | The transaction includes a `TicketCount` field, but the number of Tickets specified is invalid. | +| `temINVALID_FLAG` | The transaction includes a Flag that does not exist, or includes a contradictory combination of flags. | +| `temMALFORMED` | Unspecified problem with the format of the transaction. | +| `temREDUNDANT` | The transaction would do nothing; for example, it is sending a payment directly to the sending account, or creating an offer to buy and sell the same currency from the same issuer. | +| `temREDUNDANT_SEND_MAX` | \[Removed in: rippled 0.28.0]\[] | +| `temRIPPLE_EMPTY` | The \[Payment transaction]\[] includes an empty `Paths` field, but paths are necessary to complete this payment. | +| `temBAD_WEIGHT` | The \[SignerListSet transaction]\[] includes a `SignerWeight` that is invalid, for example a zero or negative value. | +| `temBAD_SIGNER` | The \[SignerListSet transaction]\[] includes a signer who is invalid. For example, there may be duplicate entries, or the owner of the SignerList may also be a member. | +| `temBAD_QUORUM` | The \[SignerListSet transaction]\[] has an invalid `SignerQuorum` value. Either the value is not greater than zero, or it is more than the sum of all signers in the list. | +| `temUNCERTAIN` | Used internally only. This code should never be returned. | +| `temUNKNOWN` | Used internally only. This code should never be returned. | +| `temDISABLED` | The transaction requires logic that is disabled. Typically this means you are trying to use an amendment that is not enabled for the current ledger. | +| `temHOOK_DATA_TOO_LARGE` | The transaction `CreateCode` field contains more than 256 bytes. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/ter-codes.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/ter-codes.mdx new file mode 100644 index 0000000..e5cd3c1 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/ter-codes.mdx @@ -0,0 +1,22 @@ +--- +title: TER Codes +--- +These codes indicate that the transaction failed, but it could apply successfully in the future, usually if some other hypothetical transaction applies first. They have numerical values in the range of -99 to -1. The exact code for any given error is subject to change, so don't rely on it. + +**Caution:** Transactions with `ter` codes are not applied to the current ledger and cannot cause any changes to the Xahau state. However, a transaction that provisionally failed may still succeed or fail with a different code after being automatically reapplied. For more information, see Finality of Results and Reliable Transaction Submission. + +| Code | Explanation | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `terFUNDS_SPENT` | **DEPRECATED.** | +| `terINSUF_FEE_B` | The account sending the transaction does not have enough XAH to pay the `Fee` specified in the transaction. | +| `terLAST` | Used internally only. This code should never be returned. | +| `terNO_ACCOUNT` | The address sending the transaction is not funded in the ledger (yet). | +| `terNO_AUTH` | The transaction would involve adding currency issued by an account with `lsfRequireAuth` enabled to a trust line that is not authorized. For example, you placed an offer to buy a currency you aren't authorized to hold. | +| `terNO_LINE` | Used internally only. This code should never be returned. | +| `terNO_RIPPLE` | Used internally only. This code should never be returned. | +| `terOWNERS` | The transaction requires that account sending it has a nonzero "owners count", so the transaction cannot succeed. For example, an account cannot enable the `lsfRequireAuth` flag if it has any trust lines or available offers. | +| `terPRE_SEQ` | The `Sequence` number of the current transaction is higher than the current sequence number of the account sending the transaction. | +| `terPRE_TICKET` | The transaction attempted to use a Ticket, but the specified `TicketSequence` number does not exist in the ledger. However, the Ticket could still be created by another transaction. | +| `terRETRY` | Unspecified retriable error. | +| `terQUEUED` | The transaction met the load-scaled transaction cost but did not meet the open ledger requirement, so the transaction has been queued for a future ledger. | +| `terNO_HOOK` | The transaction attempted to use a `HookHash` that doesn't exist on the ledger. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-results/tes-codes.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tes-codes.mdx new file mode 100644 index 0000000..a88cc66 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-results/tes-codes.mdx @@ -0,0 +1,11 @@ +--- +title: TES Codes +--- +The codes `tesSUCCESS` and `tesPARTIAL` are the only codes that indicates a transaction succeeded. This does not always mean it accomplished what you expected it to do. (For example, an \[OfferCancel]\[] can "succeed" even if there is no offer for it to cancel.) + +The `tesPARTIAL` code indicates that a transaction has partially succeeded. Specifically, it is used in scenarios where an operation, such as deleting hook state records, exceeds a certain limit (e.g., 512 or 1024 records). In such cases, the transaction deletes up to the limit and then requires you to submit additional transactions with new sequence numbers to continue the deletion process until all records are removed. This ensures that large operations are broken down into manageable parts. + +| Code | Explanation | +| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tesSUCCESS` | The transaction was applied and forwarded to other servers. If this appears in a validated ledger, then the transaction's success is final. | +| `tesPARTIAL` | The transaction partially succeeded and requires additional transactions to complete large operations, such as deleting more than a set limit of records. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/accountdelete.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/accountdelete.mdx new file mode 100644 index 0000000..4d06af3 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/accountdelete.mdx @@ -0,0 +1,57 @@ +--- +title: AccountDelete +description: >- + An AccountDelete transaction deletes an account and any objects it owns in + Xahau, if possible, sending the account's remaining XAH to a specified + destination account. +--- +import { Aside } from '@astrojs/starlight/components'; + +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/DeleteAccount.cpp)] + +_Added by the DeletableAccounts amendment_ + + + +### Example + +```json +{ + "TransactionType": "AccountDelete", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + "DestinationTag": 13, + "Fee": "2000000", + "Sequence": 2470665, + "Flags": 2147483648 +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | ---------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Destination` | String - \[Address]\[] | AccountID | The address of an account to receive any leftover XAH after deleting the sending account. Must be a funded account in the ledger, and must not be the sending account. | +| `DestinationTag` | Number | UInt32 | _(Optional)_ Arbitrary destination tag that identifies a hosted recipient or other information for the recipient of the deleted account's leftover XAH. | + +### Special Transaction Cost + +As an additional deterrent against ledger spam, the AccountDelete transaction requires a much higher than usual transaction cost: instead of the standard minimum of 0.00001 XAH, AccountDelete must destroy at least the owner reserve amount, currently 2 XRP. This discourages excessive creation of new accounts because the reserve requirement cannot be fully recouped by deleting the account. + +The transaction cost always applies when a transaction is included in a validated ledger, even if the transaction fails to delete the account. (See Error Cases.) To greatly reduce the chances of paying the high transaction cost if the account cannot be deleted, submit the transaction with `fail_hard` enabled. + +### Error Cases + +Besides errors that can occur for all transactions, AccountDelete transactions can result in the following transaction result codes: + +| Error Code | Description | +| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `temDISABLED` | Occurs if the DeletableAccounts amendment is not enabled. | +| `temDST_IS_SRC` | Occurs if the `Destination` matches the sender of the transaction (`Account` field). | +| `tecDST_TAG_NEEDED` | Occurs if the `Destination` account requires a destination tag, but the `DestinationTag` field was not provided. | +| `tecNO_DST` | Occurs if the `Destination` account is not a funded account in the ledger. | +| `tecNO_PERMISSION` | Occurs if the `Destination` account requires deposit authorization and the sender is not preauthorized. | +| `tecTOO_SOON` | Occurs if the sender's `Sequence` number is too high. The transaction's `Sequence` number plus 256 must be less than the current \[Ledger Index]\[]. This prevents replay of old transactions if this account is resurrected after it is deleted. | +| `tecHAS_OBLIGATIONS` | Occurs if the account to be deleted is connected to objects that cannot be deleted in the ledger. (This includes objects created by other accounts, such as escrows and for example NFT's minted, [even if owned by another account](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/DeleteAccount.cpp#L197).) | +| `tefTOO_BIG` | Occurs if the sending account is linked to more than 1000 objects in the ledger. The transaction could succeed on retry if some of those objects were deleted separately first. | + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/accountset.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/accountset.mdx new file mode 100644 index 0000000..1ae1f53 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/accountset.mdx @@ -0,0 +1,113 @@ +--- +title: AccountSet +description: An AccountSet transaction modifies the properties of an account in Xahau. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/SetAccount.cpp)] + +### Example + +```json +{ + "TransactionType": "AccountSet", + "Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Fee": "12", + "Sequence": 5, + "Domain": "6578616D706C652E636F6D", + "SetFlag": 5, + "MessageKey": "03AB40A0490F9B7ED8DF29D246BF2D6269820A0EE7742ACDD457BEA7C7D0931EDB" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------------- | --------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ClearFlag` | Number | UInt32 | _(Optional)_ Unique identifier of a flag to disable for this account. | +| `Domain` | String | Blob | _(Optional)_ The domain that owns this account, as a string of hex representing the ASCII for the domain in lowercase. [Cannot be more than 256 bytes in length.](https://github.com/Xahau/xahaud/blob/55dc7a252e08a0b02cd5aa39e9b4777af3eafe77/src/ripple/app/tx/impl/SetAccount.h#L34) | +| `EmailHash` | String | Hash128 | _(Optional)_ An arbitrary 128-bit value. Conventionally, clients treat this as the md5 hash of an email address to use for displaying a [Gravatar](http://en.gravatar.com/site/implement/hash/) image. | +| `MessageKey` | String | Blob | _(Optional)_ Public key for sending encrypted messages to this account. To set the key, it must be exactly 33 bytes, with the first byte indicating the key type: `0x02` or `0x03` for secp256k1 keys, `0xED` for Ed25519 keys. To remove the key, use an empty value. | +| `NFTokenMinter` | String | Blob | _(Optional)_ Another account that can mint NFTokens for you. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `SetFlag` | Number | UInt32 | _(Optional)_ Integer flag to enable for this account. | +| `TransferRate` | Number | UInt32 | _(Optional)_ The fee to charge when users transfer this account's tokens, represented as billionths of a unit. Cannot be more than `2000000000` or less than `1000000000`, except for the special case `0` meaning no fee. | +| `TickSize` | Number | UInt8 | _(Optional)_ Tick size to use for offers involving a currency issued by this address. The exchange rates of those offers is rounded to this many significant digits. Valid values are `3` to `15` inclusive, or `0` to disable. _(Added by the \[TickSize amendment]\[])_ | +| `WalletLocator` | String | Hash256 | _(Optional)_ An arbitrary 256-bit value. If specified, the value is stored as part of the account but has no inherent meaning or requirements. | +| `WalletSize` | Number | UInt32 | _(Optional)_ Not used. This field is valid in AccountSet transactions but does nothing. | + +If none of these options are provided, then the AccountSet transaction has no effect (beyond destroying the transaction cost). See Cancel or Skip a Transaction for more details. + +### Domain + +The `Domain` field is represented as the hex string of the lowercase ASCII of the domain. For example, the domain _example.com_ would be represented as `"6578616D706C652E636F6D"`. + +To remove the `Domain` field from an account, send an AccountSet with the Domain set to an empty string. + +You can put any domain in your account's `Domain` field. To prove that an account and domain belong to the same person or business, you need a "two-way link": + +* Accounts you own should have a domain you own in the `Domain` field. +* At that domain, host an xah-ledger.toml file listing accounts you own, and optionally other information about how you use Xahau. + +### AccountSet Flags + +There are several options which can be either enabled or disabled for an account. Account options are represented by different types of flags depending on the situation: + +* The `AccountSet` transaction type has several "AccountSet Flags" (prefixed **`asf`**) that can enable an option when passed as the `SetFlag` parameter, or disable an option when passed as the `ClearFlag` parameter. Newer options have only this style of flag. You can enable up to one `asf` flag per transaction, and disable up to one `asf` flag per transaction. +* The `AccountSet` transaction type has several transaction flags (prefixed **`tf`**) that can be used to enable or disable specific account options when passed in the `Flags` parameter. You can enable and disable a combination of settings in one transaction using multiple `tf` flags, but not all settings have `tf` flags. +* The `AccountRoot` ledger object type has several ledger-state-flags (prefixed **`lsf`**) which represent the state of particular account options within a particular ledger. These settings apply until a transaction changes them. + +To enable or disable Account Flags, use the `SetFlag` and `ClearFlag` parameters of an AccountSet transaction. AccountSet flags have names that begin with **`asf`**. + +All flags are disabled by default. + +The available AccountSet flags are: + +| Flag Name | Decimal Value | Corresponding Ledger Flag | Description | +| --------------------------------- | ------------- | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `asfAccountTxnID` | 5 | (None) | Track the ID of this account's most recent transaction. Required for `AccountTxnID` | +| `asfAuthorizedNFTokenMinter` | 10 | (None) | Enable to allow another account to mint non-fungible tokens (NFTokens) on this account's behalf. Specify the authorized account in the `NFTokenMinter` field of the AccountRoot object. To remove an authorized minter, enable this flag and omit the `NFTokenMinter` field. _(Added by the \[NonFungibleTokensV1_1 amendment]\[].)_ | +| `asfDefaultRipple` | 8 | `lsfDefaultRipple` | Enable rippling on this account's trust lines by default. | +| `asfDepositAuth` | 9 | `lsfDepositAuth` | Enable Deposit Authorization on this account. _(Added by the \[DepositAuth amendment]\[].)_ | +| `asfDisableMaster` | 4 | `lsfDisableMaster` | Disallow use of the master key pair. Can only be enabled if the account has configured another way to sign transactions, such as a Regular Key or a Signer List. | +| `asfDisallowIncomingCheck` | 13 | `lsfDisallowIncomingCheck` | Block incoming Checks. _Added by the \[DisallowIncoming amendment]\[]._ | +| `asfDisallowIncomingNFTokenOffer` | 12 | `lsfDisallowIncomingNFTokenOffer` | Block incoming NFTokenOffers. _Added by the \[DisallowIncoming amendment]\[]._ | +| `asfDisallowIncomingPayChan` | 14 | `lsfDisallowIncomingPayChan` | Block incoming Payment Channels. _Added by the \[DisallowIncoming amendment]\[]._ | +| `asfDisallowIncomingTrustline` | 15 | `lsfDisallowIncomingTrustline` | Block incoming trust lines._Added by the \[DisallowIncoming amendment]\[]._ | +| `asfDisallowIncomingRemit` | 16 | `lsfDisallowIncomingRemit` | Block incoming Remit txn._Added by the \[Remit amendment]\[]._ | +| `asfDisallowXRP` | 3 | `lsfDisallowXRP` | XAH should not be sent to this account. (Advisory; not enforced by Xahau protocol.) | +| `asfGlobalFreeze` | 7 | `lsfGlobalFreeze` | Freeze all assets issued by this account. | +| `asfNoFreeze` | 6 | `lsfNoFreeze` | Permanently give up the ability to freeze individual trust lines or disable Global Freeze. This flag can never be disabled after being enabled. | +| `asfRequireAuth` | 2 | `lsfRequireAuth` | Require authorization for users to hold balances issued by this address. Can only be enabled if the address has no trust lines connected to it. | +| `asfRequireDest` | 1 | `lsfRequireDestTag` | Require a destination tag to send transactions to this account. | +| `asfTshCollect` | 11 | `lsfTshCollect` | The TSH pays for the execution of their own Hook Chain. _Added by the \[Hooks amendment]\[]._ | + +To enable the `asfDisableMaster` or `asfNoFreeze` flags, you must authorize the transaction by signing it with the master key pair. You cannot use a regular key pair or a multi-signature. You can disable `asfDisableMaster` (that is, re-enable the master key pair) using a regular key pair or multi-signature. + +The following Transaction flags (`tf` flags), specific to the AccountSet transaction type, serve the same purpose. Due to limited space, some settings do not have associated `tf` flags, and new `tf` flags are not being added to the `AccountSet` transaction type. You can use a combination of `tf` and `asf` flags to enable multiple settings with a single transaction. + +
Flag NameHex ValueDecimal ValueReplaced by AccountSet Flag
tfRequireDestTag0x0001000065536asfRequireDest (SetFlag)
tfOptionalDestTag0x00020000131072asfRequireDest (ClearFlag)
tfRequireAuth0x00040000262144asfRequireAuth (SetFlag)
tfOptionalAuth0x00080000524288asfRequireAuth (ClearFlag)
tfDisallowXRP0x001000001048576asfDisallowXRP (SetFlag)
tfAllowXRP0x002000002097152asfDisallowXRP (ClearFlag)
+ +**Caution:** The numeric values of `tf` and `asf` flags in transactions do not match up with the values they set in the accounts "at rest" in the ledger. To read the flags of an account in the ledger, see `AccountRoot` flags. + +#### Blocking Incoming Transactions + +Incoming transactions with unclear purposes may be an inconvenience for financial institutions, who would have to recognize when a customer made a mistake, and then potentially refund accounts or adjust balances depending on the mistake. The `asfRequireDest` and `asfDisallowXRP` flags are intended to protect users from accidentally sending funds in a way that is unclear about the reason the funds were sent. + +For example, a destination tag is typically used to identify which hosted balance should be credited when a financial institution receives a payment. If the destination tag is omitted, it may be unclear which account should be credited, creating a need for refunds, among other problems. By using the `asfRequireDest` tag, you can ensure that every incoming payment has a destination tag, which makes it harder for others to send you an ambiguous payment by accident. + +You can protect against unwanted incoming payments for non-XAH currencies by not creating trust lines in those currencies. Since XAH does not require trust, the `asfDisallowXRP` flag is used to discourage users from sending XAH to an account. However, this flag is not enforced in Xahau protocol because it could potentially cause accounts to become unusable if they run out of XAH. Instead, client applications should disallow or discourage XAH payments to accounts with the `asfDisallowXRP` flag enabled. + +If you want to block _all_ incoming payments, you can enable Deposit Authorization. This prevents any transaction from sending money to you, even XAH, unless your account is below the reserve requirement. + +If the \[DisallowIncoming amendment]\[] :not_enabled: is enabled, you also have the option to block all incoming Checks, NFTokenOffers, Payment Channels, and trust lines. It is generally harmless to be on the receiving end of these objects, but they can block you from deleting your account and it can be confusing to have objects you didn't expect mixed in with the list of objects you created. To block incoming objects, use one or more of these account flags: + +* `asfDisallowIncomingCheck` - for Check objects +* `asfDisallowIncomingNFTOffer` - for NFTokenOffer objects +* `asfDisallowIncomingPayChan` - for PayChannel objects +* `asfDisallowIncomingTrustline` - for RippleState (trust line) objects + +When a transaction would create one of these ledger entries, if the destination account has the corresponding flag enabled, the transaction fails with the result code `tecNO_PERMISSION`. Unlike Deposit Authorization, these settings do not prevent you from receiving payments in general. Also, enabling this setting doesn't stop you from creating these types of objects yourself (unless the destination of your transaction is also using the setting, of course). + +### TransferRate + +The `TransferRate` field specifies a fee to charge whenever counterparties transfer the currency you issue. + +In the HTTP and WebSocket APIs, the transfer fee is represented as an integer, the amount that must be sent for 1 billion units to arrive. For example, a 20% transfer fee is represented as the value `1200000000`. The value cannot be less than 1000000000. (Less than that would indicate giving away money for sending transactions, which is exploitable.) You can specify `0` as a shortcut for `1000000000`, meaning no fee. + +See Transfer Fees for more information. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcancel.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcancel.mdx new file mode 100644 index 0000000..4138e10 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcancel.mdx @@ -0,0 +1,30 @@ +--- +title: CheckCancel +description: >- + Cancels an unredeemed Check, removing it from the ledger without sending any + money. The source or the destination of the check can cancel a Check at any + time using this transaction type. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[Checks amendment]\[].)_ + +### Example + +```json +{ + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "TransactionType": "CheckCancel", + "CheckID": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", + "Fee": "12" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------- | --------- | ------------------- | ---------------------------------------------------------------------------------- | +| `CheckID` | String | Hash256 | The ID of the Check ledger object to cancel, as a 64-character hexadecimal string. | + +### Error Cases + +* If the object identified by the `CheckID` does not exist or is not a Check, the transaction fails with the result `tecNO_ENTRY`. +* If the Check is not expired and the sender of the CheckCancel transaction is not the source or destination of the Check, the transaction fails with the result `tecNO_PERMISSION`. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcash.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcash.mdx new file mode 100644 index 0000000..16b2276 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcash.mdx @@ -0,0 +1,38 @@ +--- +title: CheckCash +description: >- + Attempts to redeem a Check object in the ledger to receive up to the amount + authorized by the corresponding CheckCreate transaction. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[Checks amendment]\[].)_ + +### Example + +```json +{ + "Account": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + "TransactionType": "CheckCash", + "Amount": "100000000", + "CheckID": "838766BA2B995C00744175F69A1B11E32C3DBC40E64801A4056FCBD657F57334", + "Fee": "12" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `CheckID` | String | Hash256 | The ID of the Check ledger object to cash, as a 64-character hexadecimal string. | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | _(Optional)_ Redeem the Check for exactly this amount, if possible. The currency must match that of the `SendMax` of the corresponding CheckCreate transaction. You must provide either this field or `DeliverMin`. | +| `DeliverMin` | \[Currency Amount]\[] | Amount | _(Optional)_ Redeem the Check for at least this amount and for as much as possible. The currency must match that of the `SendMax` of the corresponding CheckCreate transaction. You must provide either this field or `Amount`. | + +The transaction _**must**_ include either `Amount` or `DeliverMin`, but not both. + +### Error Cases + +* If the sender of the CheckCash transaction is not the `Destination` of the check, the transaction fails with the result code `tecNO_PERMISSION`. +* If the Check identified by the `CheckID` field does not exist, the transaction fails with the result `tecNO_ENTRY`. +* If the Check identified by the `CheckID` field has already expired, the transaction fails with the result `tecEXPIRED`. +* If the destination of the Check has the `RequireDest` flag enabled but the Check, as created, does not have a destination tag, the transaction fails with the result code `tecDST_TAG_NEEDED`. +* If the transaction specifies both `Amount` and `DeliverMin`, or omits both, the transaction fails with the result `temMALFORMED`. +* If the `Amount` or `DeliverMin` does not match the currency (and issuer, if not XAH) of the Check, the transaction fails with the result `temBAD_CURRENCY`. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcreate.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcreate.mdx new file mode 100644 index 0000000..8b1803c --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/checkcreate.mdx @@ -0,0 +1,44 @@ +--- +title: CheckCreate +description: >- + Create a Check object in the ledger, which is a deferred payment that can be + cashed by its intended destination. The sender of this transaction is the + sender of the Check. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[Checks amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "CheckCreate", + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "Destination": "rfkE1aSy9G8Upk4JssnwBxhEv5p4mn2KTy", + "SendMax": "100000000", + "Expiration": 570113521, + "InvoiceID": "6F1DFD1D0FE8A32E40E1F2C05CF1C15545BAB56B617F9C6C2D63A6B704BEF59B", + "DestinationTag": 1, + "Fee": "12" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Destination` | String | AccountID | The unique address of the account that can cash the Check. | +| `SendMax` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | Maximum amount of source currency the Check is allowed to debit the sender, including transfer fees on non-XAH currencies. The Check can only credit the destination with the same currency (from the same issuer, for non-XAH currencies). For non-XAH amounts, the nested field names MUST be lower-case. | +| `DestinationTag` | Number | UInt32 | _(Optional)_ Arbitrary tag that identifies the reason for the Check, or a hosted recipient to pay. | +| `Expiration` | Number | UInt32 | _(Optional)_ Time after which the Check is no longer valid, in \[seconds since the Ripple Epoch]\[]. | +| `InvoiceID` | String | Hash256 | _(Optional)_ Arbitrary 256-bit hash representing a specific reason or identifier for this Check. | + +### Error Cases + +* If the `Destination` account is blocking incoming Checks, the transaction fails with the result code `tecNO_PERMISSION`. +* If the `Destination` is the sender of the transaction, the transaction fails with the result code `temREDUNDANT`. +* If the `Destination` account does not exist in the ledger, the transaction fails with the result code `tecNO_DST`. +* If the `Destination` account has the `RequireDest` flag enabled but the transaction does not include a `DestinationTag` field, the transaction fails with the result code `tecDST_TAG_NEEDED`. +* If `SendMax` specifies a token which is frozen, the transaction fails with the result `tecFROZEN`. +* If the `Expiration` of the transaction is in the past, the transaction fails with the result `tecEXPIRED`. +* If the sender does not have enough XAH to meet the owner reserve after adding the Check, the transaction fails with the result `tecINSUFFICIENT_RESERVE`. +* If either the sender or the destination of the Check cannot own more objects in the ledger, the transaction fails with the result `tecDIR_FULL`. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/claimreward.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/claimreward.mdx new file mode 100644 index 0000000..d836534 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/claimreward.mdx @@ -0,0 +1,62 @@ +--- +title: ClaimReward +description: >- + A ClaimReward transaction allows an account to claim the rewards it has + accumulated. The rewards can be claimed by the account owner or by a specified + issuer. The account can also opt-out of rewards. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/ClaimReward.cpp)] + +_(Added by the \[BalanceRewards amendment]\[].)_ + +### Opt-in + Claim + +```json +{ + "TransactionType": "ClaimReward", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Issuer": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh" +} +``` + +### Opt-out + +```json +{ + "TransactionType": "ClaimReward", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Flags": 1 +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------- | --------- | ------------------- | ------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that is claiming the reward. | +| `Flags` | Number | UInt32 | _(Optional)_ Can have flag 1 set to opt-out of rewards. | +| `Issuer` | String | AccountID | _(Optional)_ The genesis account. | + +### ClaimReward Flags + +Transactions of the ClaimReward type support additional values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| ---------- | ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tfOptOut` | `0x00000001` | 1 | The `isOptOut` flag in the ClaimReward code is used to opt-out an account from rewards by removing reward-related fields from the account object in the ledger if the `sfFlags` field in the transaction is set to 1. | + +### Special Transaction Cost + +The ClaimReward transaction has a standard transaction cost, which is the minimum transaction cost required for all transactions. + +### Error Cases + +Besides errors that can occur for all transactions, ClaimReward transactions can result in the following transaction result codes: + +| Error Code | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------- | +| `temDISABLED` | Occurs if the feature is not enabled. | +| `temINVALID_FLAG` | Occurs if the flag is set to a value other than 1. | +| `temMALFORMED` | Occurs if the issuer is the same as the source account or if the flag and issuer are not correctly set. | +| `tecNO_ISSUER` | Occurs if the issuer does not exist. | +| `terNO_ACCOUNT` | Occurs if the sending account does not exist. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/depositpreauth.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/depositpreauth.mdx new file mode 100644 index 0000000..542e4e9 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/depositpreauth.mdx @@ -0,0 +1,45 @@ +--- +title: DepositPreauth +description: >- + A DepositPreauth transaction gives another account pre-approval to deliver + payments to the sender of this transaction. +--- +import { Aside } from '@astrojs/starlight/components'; + + + +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_Added by the \[DepositPreauth amendment]\[]._ + +### Example + +```json +{ + "TransactionType" : "DepositPreauth", + "Account" : "rsUiUMpnrgxQp24dJYZDhmV4bE3aBtQyt8", + "Authorize" : "rEhxGqkqPPSxQ3P25J66ft5TwpzV14k2de", + "Fee" : "10", + "Flags" : 2147483648, + "Sequence" : 2 +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------- | --------- | ------------------- | -------------------------------------------------------------------------------- | +| `Authorize` | String | AccountID | _(Optional)_ Xahau address of the sender to preauthorize. | +| `Unauthorize` | String | AccountID | _(Optional)_ Xahau address of a sender whose preauthorization should be revoked. | + +You must provide _either_ `Authorize` or `Unauthorize`, but not both. + +### Error Cases + +* An account cannot preauthorize (or unauthorize) its own address. Attempting to do so fails with the result `temCANNOT_PREAUTH_SELF`. +* Attempting to preauthorize an account which is already preauthorized fails with the result `tecDUPLICATE`. +* Attempting to unauthorize an account which is not preauthorized fails with the result `tecNO_ENTRY`. +* Attempting to preauthorize an address that is not funded in the ledger fails with the result `tecNO_TARGET`. +* Adding authorization adds a DepositPreauth object to the ledger, which counts toward the owner reserve requirement. If the sender of the transaction does not have enough XAH to pay for the increased reserve, the transaction fails with the result `tecINSUFFICIENT_RESERVE`. If the sender of the account is already at the maximum number of owned objects, the transaction fails with the result `tecDIR_FULL`. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowcancel.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowcancel.mdx new file mode 100644 index 0000000..568d1e9 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowcancel.mdx @@ -0,0 +1,42 @@ +--- +title: EscrowCancel +description: Return escrowed XAH or IOU to the sender. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_Added by the \[Escrow amendment]\[]._ + +### Cancel Using OfferSequence + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "EscrowCancel", + "Owner": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "OfferSequence": 7, +} +``` + +### Cancel Using EscrowID + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "EscrowCancel", + "Owner": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "EscrowID": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `Owner` | String | AccountID | Address of the source account that funded the escrow payment. | +| `OfferSequence` | Number | UInt32 | _(Optional)_ Transaction sequence (or Ticket number) of \[EscrowCreate transaction]\[] that created the escrow to cancel. | +| `EscrowID` | String | Hash256 | _(Optional)_ The ID of the Escrow ledger object to cancel, as a 64-character hexadecimal string. | + +Any account may submit an EscrowCancel transaction. + +* If the corresponding \[EscrowCreate transaction]\[] did not specify a `CancelAfter` time, the EscrowCancel transaction fails. +* Otherwise the EscrowCancel transaction fails if the `CancelAfter` time is after the close time of the most recently-closed ledger. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowcreate.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowcreate.mdx new file mode 100644 index 0000000..54f434d --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowcreate.mdx @@ -0,0 +1,43 @@ +--- +title: EscrowCreate +description: Sequester XAH or IOU until the escrow process either finishes or is canceled. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_Added by the \[Escrow amendment]\[]._ + +### Example + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "EscrowCreate", + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "CancelAfter": 533257958, + "FinishAfter": 533171558, + "Condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", + "DestinationTag": 23480, + "SourceTag": 11747 +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | Amount to deduct from the sender's balance and escrow. Once escrowed, the Amount can either go to the `Destination` address (after the `FinishAfter` time) or returned to the sender (after the `CancelAfter` time). | +| `Destination` | String | AccountID | Address to receive escrowed Amount. | +| `CancelAfter` | Number | UInt32 | _(Optional)_ The time, in \[seconds since the Ripple Epoch]\[], when this escrow expires. This value is immutable; the funds can only be returned to the sender after this time. | +| `FinishAfter` | Number | UInt32 | _(Optional)_ The time, in \[seconds since the Ripple Epoch]\[], when the escrowed Amount can be released to the recipient. This value is immutable; the funds cannot move until this time is reached. | +| `Condition` | String | Blob | _(Optional)_ Hex value representing a [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1). The funds can only be delivered to the recipient if this condition is fulfilled. | +| `DestinationTag` | Number | UInt32 | _(Optional)_ Arbitrary tag to further specify the destination for this escrowed payment, such as a hosted recipient at the destination address. | + +Either `CancelAfter` or `FinishAfter` must be specified. If both are included, the `FinishAfter` time must be before the `CancelAfter` time. + +With the \[fix1571 amendment]\[] enabled, you must supply `FinishAfter`, `Condition`, or both. \[New in: rippled 1.0.0]\[] + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowfinish.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowfinish.mdx new file mode 100644 index 0000000..20e5855 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/escrowfinish.mdx @@ -0,0 +1,53 @@ +--- +title: EscrowFinish +description: Deliver XAH or IOU from a held payment to the recipient. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_Added by the \[Escrow amendment]\[]._ + +### Finish with OfferSequence + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "EscrowFinish", + "Owner": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "OfferSequence": 7, + "Condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", + "Fulfillment": "A0028000" +} +``` + +### Finish with EscrowID + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "EscrowFinish", + "Owner": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "EscrowID": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", + "Condition": "A0258020E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855810100", + "Fulfillment": "A0028000" +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------------- | --------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Owner` | String | AccountID | Address of the source account that funded the held payment. | +| `OfferSequence` | Number | UInt32 | _(Optional)_ Transaction sequence of \[EscrowCreate transaction]\[] that created the held payment to finish. | +| `Condition` | String | Blob | _(Optional)_ Hex value matching the previously-supplied [PREIMAGE-SHA-256 crypto-condition](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1) of the held payment. | +| `Fulfillment` | String | Blob | _(Optional)_ Hex value of the [PREIMAGE-SHA-256 crypto-condition fulfillment](https://tools.ietf.org/html/draft-thomas-crypto-conditions-02#section-8.1.4) matching the held payment's `Condition`. | +| `EscrowID` | String | Hash256 | _(Optional)_ The ID of the Escrow ledger object to finish, as a 64-character hexadecimal string. | + +Any account may submit an EscrowFinish transaction. + +* If the held payment has a `FinishAfter` time, you cannot execute it before this time. Specifically, if the corresponding \[EscrowCreate transaction]\[] specified a `FinishAfter` time that is after the close time of the most recently-closed ledger, the EscrowFinish transaction fails. +* If the held payment has a `Condition`, you cannot execute it unless you provide a matching `Fulfillment` for the condition. +* You cannot execute a held payment after it has expired. Specifically, if the corresponding \[EscrowCreate transaction]\[] specified a `CancelAfter` time that is before the close time of the most recently-closed ledger, the EscrowFinish transaction fails. + +**Note:** The minimum transaction cost to submit an EscrowFinish transaction increases if it contains a fulfillment. If the transaction has no fulfillment, the transaction cost is the standard 10 drops. If the transaction contains a fulfillment, the transaction cost is 330 \[drops of XAH]\[] plus another 10 drops for every 16 bytes in size of the preimage. + +In non-production networks, it may be possible to delete the destination account of a pending escrow. In this case, an attempt to finish the escrow fails with the result `tecNO_TARGET`, but the escrow object remains unless it has expired normally. If another payment re-creates the destination account, the escrow can be finished successfully. The destination account of an escrow can only be deleted if the escrow was created before the fix1523 amendment became enabled. No such escrows exist in the production Xahau, so this edge case is not possible on the production Xahau. This edge case is also not possible in test networks that enable both fix1523 and Escrow amendments at the same time, which is the default when you start a new genesis ledger. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/genesismint-emitted-txn.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/genesismint-emitted-txn.mdx new file mode 100644 index 0000000..3889a90 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/genesismint-emitted-txn.mdx @@ -0,0 +1,57 @@ +--- +title: GenesisMint - (Emitted Txn) +description: >- + The GenesisMint transaction is used to mint new XAH and distribute it to + multiple accounts. This transaction can only be used by the genesis account. +--- +\[[Source](https://github.com/ripple/rippled/blob/develop/src/ripple/app/tx/impl/GenesisMint.cpp)] + +_Added by the \[XahauGenesis amendment]\[] and the \[Hooks amendment]\[]_ + +### Example + +```json +{ + "TransactionType": "GenesisMint", + "Account": "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", + "GenesisMints": [ + { + "GenesisMint": { + "Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + "Amount": "1000000000" + }, + } + ] +} +``` + +### Fields + +| Field | JSON Type | Internal Type | Description | +| ------------ | --------- | ------------- | -------------------------------------------------------------------------------- | +| Account | String | AccountID | The address of the genesis account that will mint and distribute XAH. | +| GenesisMints | Array | Array | An array of objects representing the destinations and amounts of the minted XAH. | + +### GenesisMint Object + +The GenesisMint transaction includes an array of objects called `GenesisMints`. Each object represents a destination account and the amount of XAH to be minted and distributed to that account. + +| Field | JSON Type | Internal Type | Description | +| --------------- | --------- | ------------- | -------------------------------------------------------------------------- | +| Destination | String | AccountID | The address of the account that will receive the minted XAH. | +| Amount | String | Amount | The amount of XAH to be minted and distributed to the destination account. | +| GovernanceFlags | String | Hash256 | _(Optional)_ The governance flags associated with the destination account. | +| GovernanceMarks | String | Hash256 | _(Optional)_ The governance marks associated with the destination account. | + +### Special Transaction Cost + +The GenesisMint transaction has a standard transaction cost, which is the minimum transaction cost required for all transactions. + +### Error Cases + +Besides errors that can occur for all transactions, the GenesisMint transaction can result in the following transaction result codes: + +| Error Code | Description | +| -------------- | ------------------------------------------------------------------------------------------ | +| `temDISABLED` | Occurs if the "Hooks" or "XahauGenesis" amendments are not enabled. | +| `temMALFORMED` | Occurs if the transaction is malformed, such as missing required fields or invalid values. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/import.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/import.mdx new file mode 100644 index 0000000..841b80d --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/import.mdx @@ -0,0 +1,64 @@ +--- +title: Import +description: >- + Import is a new transaction which accepts an XPOP from the XRPL Mainnet chain + (network_id=0) or Testnet (network_id=1) and provides account synchronisation. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[Import amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "Import", + "Sequence": 0, + "Fee": "0", + "Account": "rUn84CUYbNjRoTQ6mSW7BVJPSVJNLb1QLo", + "Blob" : "DEADBEEF" +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------- | --------- | ------------------- | ---------------------------------------------------- | +| `Blob` | String | Blob | Hex value representing an XPOP | +| `Issuer` | String | AccountID | (Optional) Address that can be used inside the Hook. | +| `Destination` | String | AccountID | (Optional) Address that can be used inside the Hook. | + +### Error Cases + +* If the account is Non Activated then the `Sequence` must be 0 and the `Fee` must also be 0 +* If the account is Activated then the `Sequence` and the `Fee` are calculated the standard method. +* If the `Issuer` field is present then the `Fee` must be calculated using the standard method. + +### Notes + +_It is recommended that if you use a `SignersList` or `RegularKey` to sign your transactions that you key your accounts **FIRST** before attempting to _B2M_ XAH_ . + +* If the inner (xpop) transaction is `AccountSet` the mainet existing flags will be transfered to the new network. +* If the inner (xpop) transaction is `SetRegularKey` with the `RegularKey` field omitted or empty, and a signers list does not exist for the account then the `lsfDisableMaster` flag will be set on the account. +* If the inner (xpop) transaction is `SetRegularKey` then the `lsfPasswordSpent` flag will be set on the account. +* TicketSequence is not available on `Import` + +### Importing for the Issuer + +For issuers, there are additional steps to follow before their asset holders can import transactions. + +Firstly, issuers need to install a hook. There are two options for this: `B2MNFToken` or `B2MPayment`. + +#### B2MNFToken + +A `NFTokenBurn` transaction on mainnet will result in a `URITokenMint` transaction on the network. + +> c hook: https://example.com + +#### B2MPayment + +A `Payment` transaction on mainnet to the Issuer will result in a `Payment` transaction from the Issuer on the network. + +> c hook: https://example.com + +_Please note that the process of importing for the issuer involves specific transaction types and requires careful configuration. Always ensure that the hooks are correctly set up and that the transactions are valid for the intended operations._ diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/index.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/index.mdx new file mode 100644 index 0000000..30042a9 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/index.mdx @@ -0,0 +1,12 @@ +--- +title: Transaction Types +--- +## Transaction Types + +The type of a transaction (`TransactionType` field) is the most fundamental information about a transaction. This indicates what type of operation the transaction is supposed to do. + +All transactions have certain fields in common: + +* Common Fields + +Each transaction type has additional fields relevant to the type of action it causes. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/invoke.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/invoke.mdx new file mode 100644 index 0000000..2811b81 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/invoke.mdx @@ -0,0 +1,41 @@ +--- +title: Invoke +description: >- + An Invoke transaction is used to call a hook, which is a piece of code that is + executed in response to certain ledger operations. +--- +\[[Source](https://github.com/ripple/rippled/blob/develop/src/ripple/app/tx/impl/Invoke.cpp)] + +_(Added by the \[Hooks amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "Invoke", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Blob": "697066733A2F2F4445414442454546", + "Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------- | --------- | ------------------- | -------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that is invoking the hook. | +| `Blob` | String | Blob | _(Optional)_ A blob of data that is passed to the hook. (512 byte max) | +| `Destination` | String | AccountID | _(Optional)_ The address of the account that is the target of the hook. | +| `InvoiceID` | String | Hash256 | _(Optional)_ Arbitrary 256-bit hash representing a specific reason or identifier for this payment. | + +### Special Transaction Cost + +The Invoke transaction has a standard transaction cost, plus an additional cost based on the size of the Blob and HookParameters fields. + +### Error Cases + +Besides errors that can occur for all transactions, Invoke transactions can result in the following transaction result codes: + +| Error Code | Description | +| --------------- | ------------------------------------------------------------------------ | +| `temDISABLED` | Occurs if the Hooks amendment is not enabled. | +| `temMALFORMED` | Occurs if the Blob field is larger than 128 KiB. | +| `terNO_ACCOUNT` | Occurs if the sending account or the destination account does not exist. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/offercancel.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/offercancel.mdx new file mode 100644 index 0000000..9415a18 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/offercancel.mdx @@ -0,0 +1,44 @@ +--- +title: OfferCancel +description: An OfferCancel transaction removes an Offer object from Xahau. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +### Cancel with OfferSequence + +```json +{ + "TransactionType": "OfferCancel", + "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108629, + "OfferSequence": 6, + "Sequence": 7 +} +``` + +### Cancel with OfferID + +```json +{ + "TransactionType": "OfferCancel", + "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108629, + "OfferID": "49647F0D748DC3FE26BDACBC57F251AADEFFF391403EC9BF87C97F67E9977FB0", + "Sequence": 7 +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------------- | --------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `OfferSequence` | Number | UInt32 | _(Optional)_ The sequence number (or Ticket number) of a previous OfferCreate transaction. If specified, cancel any offer object in the ledger that was created by that transaction. It is not considered an error if the offer specified does not exist. | +| `OfferID` | String | Hash256 | _(Optional)_ The ID of the Offer ledger object to cancel, as a 64-character hexadecimal string. | + +_Tip:_ To remove an old offer and replace it with a new one, you can use an \[OfferCreate transaction]\[] with an `OfferSequence` parameter, instead of using OfferCancel and another OfferCreate. + +The OfferCancel method returns `tesSUCCESS` even if it did not find an offer with the matching sequence number. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/offercreate.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/offercreate.mdx new file mode 100644 index 0000000..221c66d --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/offercreate.mdx @@ -0,0 +1,68 @@ +--- +title: OfferCreate +description: >- + An OfferCreate transaction places an [Offer](offers.html) in the + [decentralized exchange](decentralized-exchange.html). +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +### Example + +```json +{ + "TransactionType": "OfferCreate", + "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Fee": "12", + "Flags": 0, + "LastLedgerSequence": 7108682, + "Sequence": 8, + "TakerGets": "6000000", + "TakerPays": { + "currency": "GKO", + "issuer": "ruazs5h1qEsqpke88pcqnaseXdm6od2xc", + "value": "2" + } +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------- | +| `Expiration` | Number | UInt32 | _(Optional)_ Time after which the Offer is no longer active, in \[seconds since the Ripple Epoch]\[]. | +| `OfferSequence` | Number | UInt32 | _(Optional)_ An Offer to delete first, specified in the same way as \[OfferCancel]\[]. | +| `OfferID` | String | Hash256 | _(Optional)_ The ID of the Offer ledger object to cancel, as a 64-character hexadecimal string. | +| `TakerGets` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | The amount and type of currency being sold. | +| `TakerPays` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | The amount and type of currency being bought. | + +### OfferCreate Flags + +Transactions of the OfferCreate type support additional values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| --------------------- | ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tfPassive` | `0x00010000` | 65536 | If enabled, the Offer does not consume Offers that exactly match it, and instead becomes an Offer object in the ledger. It still consumes Offers that cross it. | +| `tfImmediateOrCancel` | `0x00020000` | 131072 | Treat the Offer as an [Immediate or Cancel order](http://en.wikipedia.org/wiki/Immediate_or_cancel). The Offer never creates an \[Offer object]\[] in the ledger: it only trades as much as it can by consuming existing Offers at the time the transaction is processed. If no Offers match, it executes "successfully" without trading anything. In this case, the transaction still uses the result code `tesSUCCESS`. | +| `tfFillOrKill` | `0x00040000` | 262144 | Treat the offer as a [Fill or Kill order](http://en.wikipedia.org/wiki/Fill_or_kill). The Offer never creates an \[Offer object]\[] in the ledger, and is canceled if it cannot be fully filled at the time of execution. By default, this means that the owner must receive the full `TakerPays` amount; if the `tfSell` flag is enabled, the owner must be able to spend the entire `TakerGets` amount instead. | +| `tfSell` | `0x00080000` | 524288 | Exchange the entire `TakerGets` amount, even if it means obtaining more than the `TakerPays` amount in exchange. | + +### Error Cases + +| Error Code | Description | +| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `temINVALID_FLAG` | Occurs if the transaction specifies both `tfImmediateOrCancel` and `tfFillOrKill`. | +| `tecEXPIRED` | Occurs if the transaction specifies an `Expiration` time that has already passed. | +| `tecKILLED` | Occurs if the transaction specifies `tfFillOrKill`, and the full amount cannot be filled. If the _\[ImmediateOfferKilled amendment]\[]_ is enabled, this result code also occurs when the transaction specifies `tfImmediateOrCancel` and executes without moving funds (previously, this would return `tesSUCCESS`). | +| `temBAD_EXPIRATION` | Occurs if the transaction contains an `Expiration` field that is not validly formatted. | +| `temBAD_SEQUENCE` | Occurs if the transaction contains an `OfferSequence` that is not validly formatted, or is higher than the transaction's own `Sequence` number. | +| `temBAD_OFFER` | Occurs if the Offer tries to trade XAH for XAH, or tries to trade an invalid or negative amount of a token. | +| `temREDUNDANT` | Occurs if the transaction specifies a token for the same token (same issuer and currency code). | +| `temBAD_CURRENCY` | Occurs if the transaction specifies a token with the currency code "XAH". | +| `temBAD_ISSUER` | Occurs if the transaction specifies a token with an invalid `issuer` value. | +| `tecNO_ISSUER` | Occurs if the transaction specifies a token whose `issuer` value is not a funded account in the ledger. | +| `tecFROZEN` | Occurs if the transaction involves a token on a frozen trust line (including local and global freezes). | +| `tecUNFUNDED_OFFER` | Occurs if the owner does not hold a positive amount of the `TakerGets` currency. (Exception: if `TakerGets` specifies a token that the owner issues, the transaction can succeed.) | +| `tecNO_LINE` | Occurs if the transaction involves a token whose issuer uses Authorized Trust Lines and the necessary trust line does not exist. | +| `tecNO_AUTH` | Occurs if the transaction involves a token whose issuer uses Authorized Trust Lines and the the trust line that would receive the tokens exists but has not been authorized. | +| `tecINSUF_RESERVE_OFFER` | Occurs if the owner does not have enough XAH to meet the reserve requirement of adding a new Offer object to the ledger, and the transaction did not convert any currency. (If the transaction successfully traded any amount, the transaction succeeds with the result code `tesSUCCESS`, but does not create an Offer object in the ledger for the rest.) | +| `tecDIR_FULL` | Occurs if the owner owns too many items in the ledger, or the order book contains too many Offers at the same exchange rate already. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/payment.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/payment.mdx new file mode 100644 index 0000000..b20cf76 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/payment.mdx @@ -0,0 +1,113 @@ +--- +title: Payment +description: >- + A Payment transaction represents a transfer of value from one account to + another. (Depending on the path taken, this can involve additional exchanges + of value, which occur atomically.) This transactio +--- +[\[Source\]](https://github.com/ripple/rippled/blob/5425a90f160711e46b2c1f1c93d68e5941e4bfb6/src/ripple/app/transactors/Payment.cpp) + +### Example + +```json +{ + "TransactionType" : "Payment", + "Account" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Destination" : "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Fee": "12", + "Flags": 2147483648, + "Sequence": 2, +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | The amount of currency to deliver. For non-XAH amounts, the nested field names MUST be lower-case. If the `tfPartialPayment` flag is set, deliver _up to_ this amount instead. | +| `Destination` | String | AccountID | The unique address of the account receiving the payment. | +| `DestinationTag` | Number | UInt32 | _(Optional)_ Arbitrary tag that identifies the reason for the payment to the destination, or a hosted recipient to pay. | +| `InvoiceID` | String | Hash256 | _(Optional)_ Arbitrary 256-bit hash representing a specific reason or identifier for this payment. | +| `Paths` | Array of path arrays | PathSet | (Optional, auto-fillable) Array of payment paths to be used for this transaction. Must be omitted for XAH-to-XAH transactions. | +| `SendMax` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | _(Optional)_ Highest amount of source currency this transaction is allowed to cost, including transfer fees, exchange rates, and [slippage](http://en.wikipedia.org/wiki/Slippage_\(finance\)). Does not include the XAH destroyed as a cost for submitting the transaction. For non-XAH amounts, the nested field names MUST be lower-case. Must be supplied for cross-currency/cross-issue payments. Must be omitted for XAH-to-XAH payments. | +| `DeliverMin` | \[Currency Amount]\[] | Amount | _(Optional)_ Minimum amount of destination currency this transaction should deliver. Only valid if this is a partial payment. For non-XAH amounts, the nested field names are lower-case. | + +### Types of Payments + +The Payment transaction type is a general-purpose tool that can represent several different types of abstract actions. You can identify the transaction type based on the transaction's fields, as described in the table below: + +| Payment type | `Amount` | `SendMax` | `Paths` | `Address` = `Destination`? | Description | +| ---------------------------- | ------------------------------- | ------------------------------- | ---------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Direct XAH-to-XAH Payment | String (XAH) | Omitted | Omitted | No | Transfers XAH directly from one account to another. Always delivers the exact amount. No fee applies other than the basic transaction cost. | +| Creating or redeeming tokens | Object | Object (optional) | Optional | No | Increases or decreases the amount of a non-XAH currency or asset tracked in Xahau. Transfer fees and freezes do not apply when sending and redeeming directly. | +| Cross-currency Payment | Object (non-XAH) / String (XAH) | Object (non-XAH) / String (XAH) | Usually required | No | Send tokens from one holder to another. The `Amount` or `SendMax` can be XAH or tokens, but they cannot both be XAH. These payments ripple through the issuer and can take longer paths through several intermediaries if the transaction specifies a path set. Transfer fees set by the issuer(s) apply to this type of transaction. These transactions consume offers in the decentralized exchange to connect between different currencies, or possibly even between currencies with the same currency code and different issuers. | +| Partial payment | Object (non-XAH) / String (XAH) | Object (non-XAH) / String (XAH) | Usually required | No | Sends _up to_ a specific amount of any currency. Uses the `tfPartialPayment` flag. May include a `DeliverMin` amount specifying the minimum that the transaction must deliver to be successful; if the transaction does not specify `DeliverMin`, it can succeed by delivering _any positive amount_. | +| Currency conversion | Object (non-XAH) / String (XAH) | Object (non-XAH) / String (XAH) | Required | Yes | Consumes offers in the decentralized exchange to convert one currency to another, possibly taking [arbitrage](https://en.wikipedia.org/wiki/Arbitrage) opportunities. The `Amount` and `SendMax` cannot both be XAH. Also called a _circular payment_ because it delivers money to the sender. The Data API tracks this type of transaction as an "exchange" and not a "payment". | + +### Special issuer Values for SendMax and Amount + +Most of the time, the `issuer` field of a non-XAH \[Currency Amount]\[] indicates the issuer of a token. However, when describing payments, there are special rules for the `issuer` field in the `Amount` and `SendMax` fields of a payment. + +* There is only ever one balance between two addresses for the same currency code. This means that, sometimes, the `issuer` field of an amount actually refers to a counterparty, instead of the address that issued the token. +* When the `issuer` field of the destination `Amount` field matches the `Destination` address, it is treated as a special case meaning "any issuer that the destination accepts." This includes all addresses to which the destination has trust lines with a positive limit, as well as tokens with the same currency code issued by the destination. +* When the `issuer` field of the `SendMax` field matches the source account's address, it is treated as a special case meaning "any issuer that the source can use." This includes creating new tokens on trust lines that other accounts have extended to the source account, and sending tokens the source account holds from other issuers. + +### Creating Accounts + +The Payment transaction type can create new accounts in Xahau by sending enough XAH to an unfunded address. Other transactions to unfunded addresses always fail. + +For more information, see Accounts. + +### Paths + +If present, the `Paths` field must contain a _path set_ - an array of path arrays. Each individual path represents one way value can flow from the sender to receiver through various intermediary accounts and order books. A single transaction can potentially use multiple paths, for example if the transaction exchanges currency using several different order books to achieve the best rate. + +You must omit the `Paths` field for direct payments, including: + +* An XAH-to-XAH transfer. +* A direct transfer on a trust line that connects the sender and receiver. + +If the `Paths` field is provided, the server decides at transaction processing time which paths to use, from the provided set plus a _default path_ (the most direct way possible to connect the specified accounts). This decision is deterministic and attempts to minimize costs, but it is not guaranteed to be perfect. + +The `Paths` field must not be an empty array, nor an array whose members are all empty arrays. + +For more information, see Paths. + +### Payment Flags + +Transactions of the Payment type support additional values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| ------------------ | ------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `tfNoDirectRipple` | `0x00010000` | 65536 | Do not use the default path; only use paths included in the `Paths` field. This is intended to force the transaction to take arbitrage opportunities. Most clients do not need this. | +| `tfPartialPayment` | `0x00020000` | 131072 | If the specified `Amount` cannot be sent without spending more than `SendMax`, reduce the received amount instead of failing outright. See Partial Payments for more details. | +| `tfLimitQuality` | `0x00040000` | 262144 | Only take paths where all the conversions have an input:output ratio that is equal or better than the ratio of `Amount`:`SendMax`. See Limit Quality for details. | + +### Partial Payments + +A partial payment allows a payment to succeed by reducing the amount received. Partial payments are useful for returning payments without incurring additional costs to oneself. However, partial payments can also be used to exploit integrations that naively assume the `Amount` field of a successful transaction always describes the exact amount delivered. + +A partial payment is any \[Payment transaction]\[] with the `tfPartialPayment` flag enabled. A partial payment can be successful if it delivers any positive amount greater than or equal to its `DeliverMin` field (or any positive amount at all if `DeliverMin` is not specified) without sending more than the `SendMax` value. + +The `delivered_amount` field of a payment's metadata indicates the amount of currency actually received by the destination account. + +For more information, see the full article on Partial Payments. + +### Limit Quality + +Xahau defines the "quality" of a currency exchange as the ratio of the numeric amount in to the numeric amount out. For example, if you spend $2 USD to receive £1 GBP, then the "quality" of that exchange is `0.5`. + +The `tfLimitQuality` flag allows you to set a minimum quality of conversions that you are willing to take. This limit quality is defined as the destination `Amount` divided by the `SendMax` amount (the numeric amounts only, regardless of currency). When set, the payment processing engine avoids using any paths whose quality (conversion rate) is worse (numerically lower) than the limit quality. + +By itself, the `tfLimitQuality` flag reduces the number of situations in which a transaction can succeed. Specifically, it rejects payments where some part of the payment uses an unfavorable conversion, even if the overall _average_ quality of conversions in the payment is equal or better than the limit quality. If a payment is rejected in this way, the transaction result is `tecPATH_DRY`. + +Consider the following example. If I am trying to send you 100 Chinese Yuan (`Amount` = 100 CNY) for 20 United States dollars (`SendMax` = 20 USD) or less, then the limit quality is `5`. Imagine one trader is offering ¥95 for $15 (a ratio of about `6.3` CNY per USD), but the next best offer in the market is ¥5 for $2 (a ratio of `2.5` CNY per USD). If I were to take both offers to send you 100 CNY, then it would cost me 17 USD, for an average quality of about `5.9`. + +Without the `tfLimitQuality` flag set, this transaction would succeed, because the $17 it costs me is within my specified `SendMax`. However, with the `tfLimitQuality` flag enabled, the transaction would fail instead, because the path to take the second offer has a quality of `2.5`, which is worse than the limit quality of `5`. + +The `tfLimitQuality` flag is most useful when combined with partial payments. When both `tfPartialPayment` and `tfLimitQuality` are set on a transaction, then the transaction delivers as much of the destination `Amount` as it can, without using any conversions that are worse than the limit quality. + +In the above example with a ¥95/$15 offer and a ¥5/$2 offer, the situation is different if my transaction has both `tfPartialPayment` and `tfLimitQuality` enabled. If we keep my `SendMax` of 20 USD and a destination `Amount` of 100 CNY, then the limit quality is still `5`. However, because I am doing a partial payment, the transaction sends as much as it can instead of failing if the full destination amount cannot be sent. This means that my transaction consumes the ¥95/$15 offer, whose quality is about `6.3`, but it rejects the ¥5/$2 offer because that offer's quality of `2.5` is worse than the quality limit of `5`. In the end, my transaction only delivers ¥95 instead of the full ¥100, but it avoids wasting money on poor exchange rates. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelclaim.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelclaim.mdx new file mode 100644 index 0000000..b77e385 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelclaim.mdx @@ -0,0 +1,65 @@ +--- +title: PaymentChannelClaim +description: >- + Claim Amount from a payment channel, adjust the payment channel's expiration, + or both. This transaction can be used differently depending on the transaction + sender's role in the specified channel: +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/app/tx/impl/PayChan.cpp) + +_Added by the \[PayChan amendment]\[]._ + +The **source address** of a channel can: + +* Send Amount from the channel to the destination with _or without_ a signed Claim. +* Set the channel to expire as soon as the channel's `SettleDelay` has passed. +* Clear a pending `Expiration` time. +* Close a channel immediately, with or without processing a claim first. The source address cannot close the channel immediately if the channel has Amount remaining. + +The **destination address** of a channel can: + +* Receive Amount from the channel using a signed Claim. +* Close the channel immediately after processing a Claim, refunding any unclaimed Amount to the channel's source. + +**Any address** sending this transaction can: + +* Cause a channel to be closed if its `Expiration` or `CancelAfter` time is older than the previous ledger's close time. Any validly-formed PaymentChannelClaim transaction has this effect regardless of the contents of the transaction. + +### Example + +```json +{ + "Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Signature": "30440220718D264EF05CAED7C781FF6DE298DCAC68D002562C9BF3A07C1E721B420C0DAB02203A5A4779EF4D2CCC7BC3EF886676D803A9981B928D3B8ACA483B80ECA3CD7B9B", + "PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ----------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Channel` | String | Hash256 | The unique ID of the channel, as a 64-character hexadecimal string. | +| `Balance` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | _(Optional)_ Total amount delivered by this channel after processing this claim. Required to deliver Amount. Must be more than the total amount delivered by the channel so far, but not greater than the `Amount` of the signed claim. Must be provided except when closing the channel. | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | _(Optional)_ The amount authorized by the `Signature`. This must match the amount in the signed message. This is the cumulative amount of Amount that can be dispensed by the channel, including XAH previously redeemed. | +| `Signature` | String | Blob | _(Optional)_ The signature of this claim, as hexadecimal. The signed message contains the channel ID and the amount of the claim. Required unless the sender of the transaction is the source address of the channel. | +| `PublicKey` | String | Blob | _(Optional)_ The public key used for the signature, as hexadecimal. This must match the `PublicKey` stored in the ledger for the channel. Required unless the sender of the transaction is the source address of the channel and the `Signature` field is omitted. (The transaction includes the public key so that `rippled` can check the validity of the signature before trying to apply the transaction to the ledger.) | + +If the payment channel was created before the fixPayChanRecipientOwnerDir amendment became enabled (on 2020-05-01), it is possible that the destination of the payment channel has been deleted and does not currently exist in the ledger. If the destination has been deleted, the source account cannot send XAH from the channel to the destination; instead, the transaction fails with `tecNO_DST`. (And, of course, the deleted account cannot send any transactions at all.) Other uses of this transaction type are unaffected when the destination account has been deleted, including adjusting the channel expiration, closing a channel with no Amount, or removing a channel that has passed its expiration time. + +### PaymentChannelClaim Flags + +Transactions of the PaymentChannelClaim type support additional values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| --------- | ------------ | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tfRenew` | `0x00010000` | 65536 | Clear the channel's `Expiration` time. (`Expiration` is different from the channel's immutable `CancelAfter` time.) Only the source address of the payment channel can use this flag. | +| `tfClose` | `0x00020000` | 131072 | Request to close the channel. Only the channel source and destination addresses can use this flag. This flag closes the channel immediately if it has no more Amount allocated to it after processing the current claim, or if the destination address uses it. If the source address uses this flag when the channel still holds an Amount, this schedules the channel to close after `SettleDelay` seconds have passed. (Specifically, this sets the `Expiration` of the channel to the close time of the previous ledger plus the channel's `SettleDelay` time, unless the channel already has an earlier `Expiration` time.) If the destination address uses this flag when the channel still holds an Amount, any Amount that remains after processing the claim is returned to the source address. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelcreate.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelcreate.mdx new file mode 100644 index 0000000..5fe05df --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelcreate.mdx @@ -0,0 +1,40 @@ +--- +title: PaymentChannelCreate +description: >- + Create a payment channel and fund it with an Amount. The address sending this + transaction becomes the "source address" of the payment channel. +--- +[\[Source\]](https://github.com/Xahau/xahaud/blob/master/src/ripple/app/tx/impl/PayChan.cpp) + +_Added by the \[PayChan amendment]\[]._ + +### Example + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "PaymentChannelCreate", + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Destination": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "SettleDelay": 86400, + "PublicKey": "32D2471DB72B27E3310F355BB33E339BF26F8392D5A93D3BC0FC3B566612DA0F0A", + "CancelAfter": 533171558, + "DestinationTag": 23480, + "SourceTag": 11747 +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | Amount to deduct from the sender's balance and set aside in this channel. While the channel is open, the Amount can only go to the `Destination` address. When the channel closes, any unclaimed Amount is returned to the source address's balance. | +| `Destination` | String | AccountID | Address to receive claims against this channel. This is also known as the "destination address" for the channel. Cannot be the same as the sender (`Account`). | +| `SettleDelay` | Number | UInt32 | Amount of time the source address must wait before closing the channel if it has unclaimed Amount. | +| `PublicKey` | String | Blob | The 33-byte public key of the key pair the source will use to sign claims against this channel, in hexadecimal. This can be any secp256k1 or Ed25519 public key. For more information on key pairs, see Key Derivation | +| `CancelAfter` | Number | UInt32 | _(Optional)_ The time, in \[seconds since the Ripple Epoch]\[], when this channel expires. Any transaction that would modify the channel after this time closes the channel without otherwise affecting it. This value is immutable; the channel can be closed earlier than this time but cannot remain open after this time. | +| `DestinationTag` | Number | UInt32 | _(Optional)_ Arbitrary tag to further specify the destination for this payment channel, such as a hosted recipient at the destination address. | + +If the `Destination` account is blocking incoming payment channels, the transaction fails with result code `tecNO_PERMISSION`. _(Requires the \[DisallowIncoming amendment]\[] :not_enabled:)_ diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelfund.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelfund.mdx new file mode 100644 index 0000000..7f01b4f --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/paymentchannelfund.mdx @@ -0,0 +1,46 @@ +--- +title: PaymentChannelFund +description: >- + Add additional Amount to an open payment channel, and optionally update the + expiration time of the channel. Only the source address of the channel can use + this transaction. +--- +[\[Source\]](https://github.com/ripple/rippled/blob/master/src/ripple/app/tx/impl/PayChan.cpp) + +_Added by the \[PayChan amendment]\[]._ + +### Example + +```json +{ + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "TransactionType": "PaymentChannelFund", + "Channel": "C1AE6DDDEEC05CF2978C0BAD6FE302948E9533691DC749DCDD3B9E5992CA6198", + "Amount" : { + "currency" : "USD", + "value" : "1", + "issuer" : "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn" + }, + "Expiration": 543171558 +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Channel` | String | Hash256 | The unique ID of the channel to fund, as a 64-character hexadecimal string. | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | Amount to add to the channel. Must be a positive amount. | +| `Expiration` | Number | UInt32 | _(Optional)_ New `Expiration` time to set for the channel, in \[seconds since the Ripple Epoch]\[]. This must be later than either the current time plus the `SettleDelay` of the channel, or the existing `Expiration` of the channel. After the `Expiration` time, any transaction that would access the channel closes the channel without taking its normal action. Any unspent Amount is returned to the source address when the channel closes. (`Expiration` is separate from the channel's immutable `CancelAfter` time.) For more information, see the PayChannel ledger object type. | + +### Error Cases + +Besides errors that can occur for all transactions, PaymentChannelFund transactions can result in the following transaction result codes: + +| Error Code | Description | +| ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tecINSUFFICIENT_RESERVE` | The sending account has less XAH than the reserve requirement. | +| `tecNO_DST` | The destination account of the channel has been deleted. This is only possible if the payment channel was created before the fixPayChanRecipientOwnerDir amendment became enabled (on 2020-05-01). | +| `tecNO_ENTRY` | The Payment Channel identified by the `Channel` field does not exist. | +| `tecNO_PERMISSION` | The sender of the transaction is not the source address for the channel. | +| `tecUNFUNDED` | The sending account does not have enough Amount to fund the channel with the requested amount and still meet the reserve requirement. | +| `temBAD_AMOUNT` | The `Amount` field of the transaction is invalid. The amount cannot be zero or negative. | +| `temBAD_EXPIRATION` | The `Expiration` field is invalid. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/remit.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/remit.mdx new file mode 100644 index 0000000..f678b11 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/remit.mdx @@ -0,0 +1,119 @@ +--- +title: Remit +description: >- + The Remit transaction allows the user to send multiple payment types, mint a + URIToken, transfer a list of URITokens and activate an account. +--- +import { Aside } from '@astrojs/starlight/components'; + + + +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/Remit.cpp)] + +_(Added by the \[Remit amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "Remit", + "Account": "rGvbdrdCxG2tk9ZU2673XmsjRdHCDQEpt7", + "Amounts": [ + { + "AmountEntry": { + "Amount": "1000000" + } + }, { + "AmountEntry": { + "Amount": { + "currency": "USD", + "issuer": "rExKpRKXNz25UAjbckCRtQsJFcSfjL9Er3", + "value": "1" + } + } + } + ], + "Destination": "rG1QQv2nh2gr7RCZ1P8YYcBUKCCN633jCn", + "URITokenIDs": [ + "714F206C865D334721B2F3388BEAF33AA91BC1D78C71941D10A2A653C873EDD3" + ], + "MintURIToken": { + "Digest": "6F11A4DF4EE794E2800BB361173D454BFBECB3D7506C4F4CB0EC5AE98BE43747", + "Flags": 1, + "URI": "697066733A2F2F" + } +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ---------------- | --------- | ------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that will activate the account, send the payment and/or mint/transfer the URIToken/s. | +| `Destination` | String | AccountID | The unique address of the account receiving the payment and/or URIToken/s. | +| `DestinationTag` | Number | UInt32 | _(Optional)_ A DestinationTag for deposits to a shared custody account. | +| `MintURIToken` | Object | STObject | _(Optional)_ A `MintURIToken` STObject containing the URIToken details you want to mint on the `Destination`. | +| `URITokenIDs` | Array | STArray | _(Optional)_ An array of URITokenIDs (256-bit hash) to to be transferred to the `Destination`. _Limit 32._ | +| `Amounts` | Array | STArray | _(Optional)_ An array of `AmountEntry` STObjects the account wants to send to the `Destination`. _Limit 32._ | +| `Inform` | String | AccountID | _(Optional)_ A unique address of an account that can have a hook installed and be informed when a remit occurs. | +| `Blob` | String | Blob | _(Optional)_ Arbitrary hex value that can be added to the tx for use in Hooks. | +| `InvoiceID` | String | Hash256 | _(Optional)_ Arbitrary 256-bit hash representing a specific reason or identifier for this remit. | + +### AmountEntry Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| -------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------------------------------- | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | The amount of currency the account wants to send to the `Destination`. | + +### MintURIToken Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| -------- | --------- | ------------------- | ----------------------------------------------------------- | +| `URI` | String | String | The URI associated with the minted URIToken. (256 byte max) | +| `Digest` | String | Hash256 | _(Optional)_ The digest of the URIToken. | +| `Flags` | Number | UInt32 | _(Optional)_ Flags on the mint transaction | + +### MintURIToken Flags + +The `MintURIToken` STObject supports the values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| ------------ | ------------ | ------------- | ----------------------------------------------------------------------------------------------- | +| `tfBurnable` | `0x00000001` | 1 | Allow the issuer to destroy the minted `URIToken`. (The `URIToken`'s owner can _always_ do so.) | + +### Special Transaction Cost + +The Remit transaction has a standard transaction cost, which is the minimum fee required for any transaction in Xahau. + +In addition to the minimum fee required the Remit transaction will also deduct the fees for the following: + +| Action | Fee | +| -------------------- | ---------------------------- | +| `Account Activation` | Standard Reserve Requirement | +| `Create Trustline` | Standard Reserve Requirement | +| `URIToken Mint` | Standard Reserve Requirement | +| `URIToken Transfer` | Standard Reserve Requirement | + +### Error Cases + +Besides errors that can occur for all transactions, Remit transactions can result in the following transaction result codes: + +| Error Code | Description | +| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `temINVALID_FLAG` | Occurs if any flag is specific `tfFullyCanonicalSig` | +| `temREDUNDANT` | Occurs if the Account is the same as the Destination | +| `temMALFORMED (Inform & Blob)` | Occurs when; sfInform is same as " "source or destination. Blob was more than 128kib. | +| `temMALFORMED (AmountEntry)` | Occurs when; AmountEntry count exceeds `32.` Expected AmountEntry. Native Currency appears more than once. Issued Currency appears more than once. | +| `temMALFORMED (MintURIToken)` | Occurs when; sfMintURIToken contains invalid field. URI was not provided. URI was too long/short. Invalid UTF8 inside MintURIToken. | +| `temMALFORMED (URITokenIDs)` | Occurs when; URITokenIDs too short/long. Duplicate URITokenID. | +| `temBAD_AMOUNT` | Occurs when an Amount in the AmountEntry is invalid. | +| `terNO_ACCOUNT` | Occurs when the source account does not exist. | +| `tecNO_TARGET` | Occurs when the `sfInform` field is present but the account does not exist. | +| `tecNO_PERMISSION` | Occurs when `disallowIncomingRemit` is enabled on the `Destination` | +| `tecNO_PERMISSION` | Occurs when the `Destination` has `DepositAuthorization` enabled. | +| `tecDST_TAG_NEEDED` | Occurs if the destination account requires a destination tag, but the transaction does not include one. | +| `tecDUPLICATE` | Occurs when the `MintURIToken` URI from that issuer already exists. | +| `tecDIR_FULL` | Occurs when the source or destination accouts directory is full. | +| `tecNO_ENTRY` | Occurs when the URIToken does not exist. | +| `tecNO_PERMISSION` | Occurs when the URIToken is not owned by the source account. | +| `tecUNFUNDED_PAYMENT` | Occurs when the source account does not have the required funds to execute the transaction. (XAH or Issued Currencies) | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/sethook.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/sethook.mdx new file mode 100644 index 0000000..11555f1 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/sethook.mdx @@ -0,0 +1,365 @@ +--- +title: SetHook +description: >- + The SetHook transaction allows users to install, update, delete, or perform + other operations on hooks in Xahau. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/SetHook.cpp)] + +_(Added by the \[Hooks amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "SetHook", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Flags": 0, + "Hooks": [ + { + "Hook": { + "HookHash": "610F33B8EBF7EC795F822A454FB852156AEFE50BE0CB8326338A81CD74801864", + "CreateCode": "697066733A2F2F4445414442454546697066733A2F2F44454144424545467878", + "HookGrants": [], + "HookNamespace": "0000000000000000000000000000000000000000000000000000000000000000", + "HookParameters": [], + "HookOn": "0000000000000000000000000000000000000000000000000000000000000000", + "HookApiVersion": 0, + "Flags": 0 + } + } + ] +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------- | --------- | ------------------- | -------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that will own the hook. | +| `Hooks` | Array | Array | The array of hooks to be set. | + +### Special Transaction Cost + +The SetHook transaction has a standard transaction cost, which is the minimum transaction cost required for all transactions. + +### Error Cases + +Besides errors that can occur for all transactions, SetHook transactions can result in the following transaction result codes: + +| Error Code | Description | +| --------------- | ---------------------------------------------------------------------------- | +| `tecDUPLICATE` | Occurs if a hook with the same hash already exists. | +| `tecDIR_FULL` | Occurs if the owner's directory is full and cannot accommodate the new hook. | +| `terNO_ACCOUNT` | Occurs if the sending account does not exist. | +| `terNO_HOOK` | Occurs if no hook exists with the specified hash. | +| `temDISABLED` | Occurs if the Hooks Amendment is not enabled. | +| `temMALFORMED` | Occurs if the transaction is malformed. | + +### SetHook Operations + +There are six possible operations: No Operation, Create, Update, Delete, Install and Namespace Delete + +Each operation is specified by the inclusion or omission of certain HookSet Object fields. This might seem confusing at first but by working through a few examples the reader should find it intuitive; Essentially HookSet operations are a type of **diff** between a specific Hook's _defaults_, _existing_ and newly specified fields. + +Achieving each type of operation is explained in a subsection below. + +### No Operation + +**Occurs when**: + +* The HookSet Object is empty + +**Behaviour**: + +* No change of any kind is made. + +**Example**: + +JSON + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: {} + } + ] +} +``` + +### Create Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook does not exist _or_`FLAG_OVERRIDE` is specified. +* `CreateCode` field is specified and is not blank and contains the valid web assembly bytecode for a valid Hook. +* No instance of the same web assembly bytecode already exists on the XRPL. (If it does and all other requirements are met then interpret as an Install Operation — see below.) + +**Behaviour**: + +* A reference counted `HookDefinition` object is created on the XRPL containing the fields in the HookSet Object, with all specified fields (Namespace, Parameters, HookOn) becoming defaults (but not Grants.) +* A `Hooks` array is created on the executing account, if it doesn't already exist. (This is the structure that contains the Corresponding Hooks.) +* A `Hook` object is created at the Corresponding Hook position if one does not already exist. +* The `Hook` object points at the `HookDefinition`. +* The `Hook` object contains no fields except `HookHash` which points at the created `HookDefinition`. +* If `hsfNSDELETE` flag is specified then any HookState entires in the destination namespace are deleted if they currently exist. + +**Example**: + +JSON + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + CreateCode: fs.readFileSync('accept.wasm').toString('hex').toUpperCase(), + HookOn: '0000000000000000', + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + HookApiVersion: 0 + } + } + ] +} +``` + +### Install Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook does not exist _or_`FLAG_OVERRIDE` is specified. +* `HookHash` field is specified and is not blank and contains the hash of a Hook that already exists as a `HookDefinition` on the ledger _or_ `CreateCode` field is specified and is not blank and contains the valid web assembly bytecode for a valid hook that already exists on the ledger as a `HookDefinition`. + +**Behaviour**: + +* The reference count of the `HookDefinition` object is incremented. +* A `Hooks` array is created on the executing account, if it doesn't already exist. (This is the structure that contains the Corresponding Hooks.) +* A `Hook` object is created at the Corresponding Hook position if one does not already exist. +* The `Hook` object points at the `HookDefinition`. +* The `Hook` object contains all the fields in the HookSet Object, except and unless: +* A field or key-pair within a field is identical to the Hook Defaults set on the `HookDefinition`, in which case it is omitted due to defaults. +* If `hsfNSDELETE` flag is specified then any HookState entires in the destination namespace are deleted if they currently exist. + +**Example**: + +JSON + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + HookHash: "A5663784D04ED1B4408C6B97193464D27C9C3334AAF8BBB4FA5EB8E557FC4A2C", + HookOn: '0000000000000000', + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + } + } + ] +} +``` + +### Update Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook exists. +* `HookHash` is absent. +* `CreateCode` is absent. +* One or more of `HookNamespace`, `HookParameters` or `HookGrants` is present. + +**General Behaviour**: + +* The Corresponding Hook is updated in such a way that the desired changes are reflected in the Corresponding Hook. + +**Specific Behaviour**: + +If `HookNamespace` is specified and differs from the Corresponding Hook's Namespace: + +* the Corresponding Hook's `HookNamespace` is updated, and +* if the `hsfNSDELETE` flag is specified all HookState entires in the old namespace are deleted. + +If `HookParameters` is specified, then for each entry: + +* If `HookParameterName` exists but `HookParameterValue` is absent and the Corresponding Hook's Parameters (either specifically or via defaults) contains this `HookParameterName` then the parameter is marked as deleted on the Corresponding Hook. +* If `HookParameterName` exists and `HookParameterValue` exists then the Corresponding Hook's Parameters are modified to include the new or updated parameter. + +If `HookGrants` is specified then: + +* The Corresponding Hook's `HookGrants` array is replaced with the array. + +**Example**: + +JSON + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + HookNamespace: addr.codec.sha256('new_accept').toString('hex').toUpperCase(), + } + } + ] +} +``` + +### Delete Operation + +**Occurs when**: + +_All_ of the following conditions are met: + +* The Corresponding Hook exists. +* `hsfOVERRIDE` is specified. +* optionally `hsfNSDELETE` is also specified. +* `HookHash` is absent. +* `CreateCode` is present but empty. + +**Behaviour**: + +* The reference count of the `HookDefinition` object is decremented. +* If the reference count is now zero the `HookDefintion` is removed from the ledger. +* The `Hook` object in the Corresponding Hook position is deleted, leaving an empty position. +* If `hsfNSDELETE` is specified the namespace and all HookState entries are also deleted. + +**Example**: + +JSON + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + CreateCode: "", + Flags: 1, + } + } + ] +} +``` + +### Namespace Reset + +**Occurs when**: + +_All_ of the following conditions are met: + +* `flags` is present and `hsfNSDELETE` is set. `hsfOVERRIDE` can optionally also be specified if the Hook at this position is to be deleted. +* `HookNamespace` is specified. +* `CreateCode` is absent. +* `HookHash` is absent. +* `HookGrants`, `HookParameters`, `HookOn` and `HookApiVersion` are absent. + +**Behaviour**: + +* If the Corresponding Hook exists, it remains, nothing happens to it. +* A subset of HookState objects and the HookState directory for the specified namespace are removed from the ledger, up to the defined limit (512). Further transactions are needed to continue the deletion process until all relevant records are removed. See [`tesPARTIAL`](https://docs.xahau.network/technical/protocol-reference/transactions/transaction-results/tes-codes). + +**Example**: + +JSON + +```json +{ + Account: "r4GDFMLGJUKMjNhhycgt2d5LXCdXzCYPoc", + TransactionType: "SetHook", + Fee: "2000000", + Hooks: + [ + { + Hook: { + HookNamespace: addr.codec.sha256('accept').toString('hex').toUpperCase(), + Flags: 3, + } + } + ] +} +``` + +### Hook Fields + +The following fields are used in the hook object: + +| Field | JSON Type | Internal Type | Description | +| ---------------- | --------- | ------------- | ------------------------------------------------- | +| `HookHash` | String | Hash256 | The hash of the hook. | +| `CreateCode` | String | Blob | The WebAssembly code for the hook. | +| `HookGrants` | Array | Array | The grants associated with the hook. | +| `HookNamespace` | String | Hash256 | The namespace of the hook. | +| `HookParameters` | Array | Array | The parameters of the hook. | +| `HookOn` | String | Hash256 | The transaction/s on which the hook is triggered. | +| `HookCanEmit` | String | Hash256 | The transaction/s which the hook can emit. | +| `HookApiVersion` | Number | UInt16 | The API version of the hook. | +| `Flags` | Number | UInt32 | Additional flags for the hook. | + +### Flags + +The `Flags` field in the hook object specifies additional flags for the hook. The following flags are supported: + +| Flag Name | Description | +| ------------- | ------------------------------------------------------------------------ | +| `hsfOVERRIDE` | Allows the hook to be deleted even if it is referenced by other objects. | +| `hsfNSDELETE` | Deletes an entire namespace of hooks. | +| `hsfCOLLECT` | Collects the hook's associated objects. | + +### Hook Grants + +The `HookGrants` field is an array of objects that specify the grants associated with the hook. Each grant object has the following fields: + +| Field | JSON Type | Internal Type | Description | +| ----------- | --------- | ------------- | -------------------------------------------------- | +| `HookHash` | String | Hash256 | The hook to apply the grant to. | +| `Authorize` | String | AccountID | The address of the account that is granted access. | +| `Flags` | Number | Uint32 | Flags | + +### Hook Parameters + +The `HookParameters` field is an array of objects that specify the parameters of the hook. Each parameter object has the following fields: + +| Field | JSON Type | Internal Type | Description | +| -------------------- | --------- | ------------- | --------------------------- | +| `HookParameterName` | String | Blob | The name of the parameter. | +| `HookParameterValue` | String | Blob | The value of the parameter. | + +### Hook Executions + +When Hooks execute they leave behind information about the status of that execution. This appears in the Originating Transaction metadata as an `sfHookExecutions` block. This block contains the following fields: + +| Field | JSON Type | Internal Type | Description | +| ---------------------- | --------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `HookAccount` | String | AccountID | The account the Hook ran on. | +| `HookEmitCount` | Number | UInt16 | The total number of Emitted Transactions produced by the Hook. | +| `HookExecutionIndex` | Number | UInt16 | The SHA512H of the Hook at the time it was executed. | +| `HookHash` | String | Hash256 | The value of the parameter. | +| `HookInstructionCount` | String | UInt64 | The total number of webassembly instructions that were executed when the Hook ran. | +| `HookResult` | Number | UInt8 |

Hooks can end in three ways: accept, rollback and error.
This is not the same as sfHookReturnCode!

| +| `HookReturnCode` | String | UInt64 | The integer returned as the third parameter of `accept` or `rollback`. | +| `HookReturnString` | String | Blob | The string returned in the first two parameters of `accept` or `rollback`, if any. | +| `HookStateChangeCount` | Number | UInt16 | The number of Hook State changes the Hook made during execution. | + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/setregularkey.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/setregularkey.mdx new file mode 100644 index 0000000..8987397 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/setregularkey.mdx @@ -0,0 +1,33 @@ +--- +title: SetRegularKey +description: >- + A SetRegularKey transaction assigns, changes, or removes the regular key pair + associated with an account. +--- +[\[Source\]](https://github.com/ripple/rippled/blob/4239880acb5e559446d2067f00dabb31cf102a23/src/ripple/app/transactors/SetRegularKey.cpp) + +You can protect your account by assigning a regular key pair to it and using it instead of the master key pair to sign transactions whenever possible. If your regular key pair is compromised, but your master key pair is not, you can use a `SetRegularKey` transaction to regain control of your account. + +### Example SetRegularKey JSON + +```json +{ + "Flags": 0, + "TransactionType": "SetRegularKey", + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Fee": "12", + "RegularKey": "rAR8rR8sUkBoCZFawhkWzY4Y5YoyuznwD" +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------ | --------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `RegularKey` | String | AccountID | _(Optional)_ A base-58-encoded \[Address]\[] that indicates the regular key pair to be assigned to the account. If omitted, removes any existing regular key pair from the account. Must not match the master key pair for the address. | + +### See Also + +For more information about regular and master key pairs, see Cryptographic Keys. + +For a tutorial on assigning a regular key pair to an account, see Working with a Regular Key Pair. + +For even greater security, you can use multi-signing, but multi-signing requires additional XAH for the \[transaction cost]\[] and reserve. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/setremarks.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/setremarks.mdx new file mode 100644 index 0000000..cc521fd --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/setremarks.mdx @@ -0,0 +1,95 @@ +--- +title: SetRemarks +description: >- + The SetRemarks transaction enables accounts to attach, update, or remove + arbitrary remarks (key-value pairs) on supported ledger objects. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/SetRemarks.cpp)] + +_(Added by the \[_Remarks _amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "SetRemarks", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Flags": 0, + "ObjectID": "AABBCCDDEEFF00112233445566778899AABBCCDDEEFF00112233445566778899", + "Remarks": [ + { + "Remark": { + "RemarkName": "CAFE", + "RemarkValue": "DEADBEEF", + "Flags": 0 + } + } + ] +} + +``` + +| Field | JSON Type | Internal Type | Description | +| ---------- | --------- | ------------- | ---------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account submitting the transaction (must be the owner/issuer of the object) | +| `ObjectID` | String | Hash256 | The ledger object ID to which the remarks are attached (see Supported Objects) | +| `Remarks` | Array | Array | Array of remark objects to set, update, or delete (see Remarks Format) | + +### SetRemarks Flags + +| Flag Name | Hex Value | Decimal Value | Description | +| ------------- | ------------ | ------------- | ------------------------------------------------------- | +| `tfImmutable` | `0x00000001` | 1 | Marks the remark as immutable (cannot change or delete) | + +### Remarks Format + +Each entry in the `Remarks` array is an object with a single `Remark` field, which itself is an object with the following fields: + +| Field | JSON Type | Internal Type | Required | Description | +| ------------- | --------- | ------------- | -------- | ------------------------------------------------------------------------ | +| `RemarkName` | String | Blob | Yes | The name/key of the remark (1–256 bytes, must be unique per object) | +| `RemarkValue` | String | Blob | No | The value of the remark (1–256 bytes). Omit to delete the remark. | +| `Flags` | Number | UInt32 | No | Set to `1` (`tfImmutable`) to make the remark immutable. Default is `0`. | + +### Supported Objects and Permissions + +Remarks can be attached to the following ledger object types. **Only the specified party (owner or issuer) may create, update, or delete remarks on each object:** + +| Ledger Object Type | Who Can Set Remarks? | Notes | +| --------------------------- | -------------------- | ---------------------------------------------------------------------------------------- | +| **AccountRoot** | Owner | The account itself (the address in the object) | +| **Offer** | Owner | The account that created the offer | +| **Escrow** | Owner | The account that created the escrow | +| **Ticket** | Owner | The account that created the ticket | +| **PayChannel** | Owner | The account that created the payment channel | +| **Check** | Owner | The account that created the check | +| **DepositPreauth** | Owner | The account that created the deposit preauthorization | +| **URI Token** | Issuer | The account that issued the URI token (field `sfIssuer`) | +| **Trustline (RippleState)** | Issuer | Only the issuer side of the trustline (the account that issued the IOU) can set remarks. | + +### Limits + +* **Maximum 32 remarks** per object. +* Each `RemarkName` and `RemarkValue` must be 1–256 bytes. +* Each `RemarkName` must be unique per object. +* Once a remark is marked as immutable (`Flags: 1`), it cannot be changed or deleted. + +### Special Transaction Cost + +The base transaction cost is increased by **1 drop per byte** of all `RemarkName` and `RemarkValue` fields in the transaction. + +### Error Cases + +| Error Code | Description | +| --------------------- | -------------------------------------------------------------------------------------------- | +| `temDISABLED` | The Remarks amendment is not enabled. | +| `temINVALID_FLAG` | Invalid flags set on the transaction. | +| `temMALFORMED` | The transaction is malformed (e.g., too many remarks, duplicate names, invalid field sizes). | +| `terNO_ACCOUNT` | The sending account does not exist. | +| `tecNO_TARGET` | The target object does not exist. | +| `tecNO_PERMISSION` | The sender is not the owner/issuer of the object. | +| `tecIMMUTABLE` | Attempted to modify or delete an immutable remark. | +| `tecTOO_MANY_REMARKS` | The number of remarks on the object would exceed the limit of 32. | + + + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/signerlistset.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/signerlistset.mdx new file mode 100644 index 0000000..1919a10 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/signerlistset.mdx @@ -0,0 +1,55 @@ +--- +title: SignerListSet +description: >- + The SignerListSet transaction creates, replaces, or removes a list of signers + that can be used to multi-sign a transaction. This transaction type was + introduced by the [MultiSign amendment][]. +--- +[\[Source\]](https://github.com/Xahau/xahaud/blob/master/src/ripple/app/tx/impl/SetSignerList.cpp) + +### Example + +```json +{ + "Flags": 0, + "TransactionType": "SignerListSet", + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Fee": "12", + "SignerQuorum": 3, + "SignerEntries": [ + { + "SignerEntry": { + "Account": "rsA2LpzuawewSBQXkiju3YQTMzW13pAAdW", + "SignerWeight": 2 + } + }, + { + "SignerEntry": { + "Account": "rUpy3eEg8rqjqfUoLeBnZkscbKbFsKXC3v", + "SignerWeight": 1 + } + }, + { + "SignerEntry": { + "Account": "raKEEVSGnKSD9Zyvxu4z6Pqpm4ABH8FS6n", + "SignerWeight": 1 + } + } + ] +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| --------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `SignerQuorum` | Number | UInt32 | A target number for the signer weights. A multi-signature from this list is valid only if the sum weights of the signatures provided is greater than or equal to this value. To delete a signer list, use the value `0`. | +| `SignerEntries` | Array | Array | _(Omitted when deleting)_ Array of `SignerEntry` objects, indicating the addresses and weights of signers in this list. This signer list must have at least 1 member and no more than 32 members. No address may appear more than once in the list, nor may the `Account` submitting the transaction appear in the list. _(Updated by the \[ExpandedSignerList amendment]\[].)_ | + +A successful SignerListSet transaction replaces the account's `SignerList` object in the ledger, or adds one if it did not exist before. An account may not have more than one signer list. To delete a signer list, you must set `SignerQuorum` to `0` _and_ omit the `SignerEntries` field. Otherwise, the transaction fails with the error `temMALFORMED`. A transaction to delete a signer list is considered successful even if there was no signer list to delete. + +You cannot create a signer list such that the `SignerQuorum` could never be met. The `SignerQuorum` must be greater than 0 but less than or equal to the sum of the `SignerWeight` values in the list. Otherwise, the transaction fails with the error `temMALFORMED`. + +You can create, update, or remove a signer list using the master key, regular key, or the current signer list, if those methods of signing transactions are available. + +You cannot remove the last method of signing transactions from an account. If an account's master key is disabled (the account has the `lsfDisableMaster` flag enabled) and the account does not have a Regular Key configured, then you cannot delete the signer list from the account. Instead, the transaction fails with the error `tecNO_ALTERNATIVE_KEY`. + +Creating or replacing a signer list enables the `lsfOneOwnerCount` flag on the SignerList object. Lists that were created before the \[MultiSignReserve amendment]\[] became enabled do not have this flag and have a higher owner reserve. You can decrease the owner reserve for these lists by replacing the list with the same list. For more information, see SignerList Flags. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/ticketcreate.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/ticketcreate.mdx new file mode 100644 index 0000000..f1d8c02 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/ticketcreate.mdx @@ -0,0 +1,39 @@ +--- +title: TicketCreate +description: >- + A TicketCreate transaction sets aside one or more [sequence numbers][Sequence + Number] as Tickets. +--- +[\[Source\]](https://github.com/ripple/rippled/blob/develop/src/ripple/app/tx/impl/CreateTicket.cpp) + +_(Added by the \[TicketBatch amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "TicketCreate", + "Account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "Fee": "10", + "Sequence": 381, + "TicketCount": 10 +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------- | --------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `TicketCount` | Number | UInt32 | How many Tickets to create. This must be a positive number and cannot cause the account to own more than 250 Tickets after executing this transaction. | + +If the transaction cannot create _all_ of the requested Tickets (either due to the 250-Ticket limit or the owner reserve), it fails and creates no Tickets. To look up how many Tickets an account currently owns, use the \[account_info method]\[] and check the `account_data.TicketCount` field. + +**Tip:** This transaction increases the sending account's \[sequence number]\[Sequence Number] by 1 _plus_ the number of tickets created (`TicketCount`). This is the only transaction that increases an account's sequence number by more than 1. + +### Error Cases + +Besides errors that can occur for all transactions, TicketCreate transactions can result in the following transaction result codes: + +| Error Code | Description | +| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `temINVALID_COUNT` | The `TicketCount` field is invalid. It must be an integer from 1 to 250. | +| `tecDIR_FULL` | This transaction would cause the account to own more than the limit of 250 Tickets at a time, or more than the maximum number of ledger objects in general. | +| `tecINSUFFICIENT_RESERVE` | The sending account does not have enough XAH to meet the owner reserve of all the requested Tickets. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/trustset.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/trustset.mdx new file mode 100644 index 0000000..e6c48c0 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/trustset.mdx @@ -0,0 +1,50 @@ +--- +title: TrustSet +description: Create or modify a trust line linking two accounts. +--- +[\[Source\]](https://github.com/Xahau/xahaud/blob/master/src/ripple/app/tx/impl/SetTrust.cpp) + +### Example + +```json +{ + "TransactionType": "TrustSet", + "Account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "Fee": "12", + "Flags": 262144, + "LastLedgerSequence": 8007750, + "LimitAmount": { + "currency": "USD", + "issuer": "rsP3mgGb2tcYUrxiLFiHJiQXhsziegtwBc", + "value": "100" + }, + "Sequence": 12 +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------------------ | --------- | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `LimitAmount` | Object | Amount | Object defining the trust line to create or modify, in the format of a \[Currency Amount]\[]. | +| `LimitAmount`.`currency` | String | (Amount.currency) | The currency to this trust line applies to, as a three-letter [ISO 4217 Currency Code](https://www.xe.com/iso4217.php) or a 160-bit hex value according to currency format. "XAH" is invalid. | +| `LimitAmount`.`value` | String | (Amount.value) | Quoted decimal representation of the limit to set on this trust line. | +| `LimitAmount`.`issuer` | String | (Amount.issuer) | The address of the account to extend trust to. | +| `QualityIn` | Number | UInt32 | _(Optional)_ Value incoming balances on this trust line at the ratio of this number per 1,000,000,000 units. A value of `0` is shorthand for treating balances at face value. | +| `QualityOut` | Number | UInt32 | _(Optional)_ Value outgoing balances on this trust line at the ratio of this number per 1,000,000,000 units. A value of `0` is shorthand for treating balances at face value. | + +If the account specified in `LimitAmount.issuer` is blocking incoming trust lines, the transaction fails with the result code `tecNO_PERMISSION`. _(Requires the \[DisallowIncoming amendment]\[] :not_enabled:)_ + +### TrustSet Flags + +Transactions of the TrustSet type support additional values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| ----------------- | ------------ | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `tfSetfAuth` | `0x00010000` | 65536 | Authorize the other party to hold currency issued by this account. (No effect unless using the `asfRequireAuth` AccountSet flag.) Cannot be unset. | +| `tfSetNoRipple` | `0x00020000` | 131072 | Enable the No Ripple flag, which blocks rippling between two trust lines of the same currency if this flag is enabled on both. | +| `tfClearNoRipple` | `0x00040000` | 262144 | Disable the No Ripple flag, allowing rippling on this trust line. | +| `tfSetFreeze` | `0x00100000` | 1048576 | Freeze the trust line. | +| `tfClearFreeze` | `0x00200000` | 2097152 | Unfreeze the trust line. | + +If a transaction tries to enable No Ripple but cannot, it fails with the result code `tecNO_PERMISSION`. Before the \[fix1578 amendment]\[] became enabled, such a transaction would result in `tesSUCCESS` (making any other changes it could) instead. + +The Auth flag of a trust line does not determine whether the trust line counts towards its owner's XAH reserve requirement. However, an enabled Auth flag prevents the trust line from being in its default state. An authorized trust line can never be deleted. An issuer can pre-authorize a trust line with the `tfSetfAuth` flag only, even if the limit and balance of the trust line are 0. diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenburn.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenburn.mdx new file mode 100644 index 0000000..32708db --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenburn.mdx @@ -0,0 +1,39 @@ +--- +title: URITokenBurn +description: >- + The URITokenBurn transaction is used to burn a URIToken in Xahau. Burning a + URIToken permanently removes it from circulation. +--- +[\[Source\]](https://github.com/ripple/rippled/blob/develop/src/ripple/app/tx/impl/URIToken.cpp) + +_(Added by the \[URIToken amendment]\[].)_ + +The URITokenBurn transaction is used to burn a URIToken in Xahau. Burning a URIToken permanently removes it from circulation. + +### Example + +```json +{ + "TransactionType": "URITokenBurn", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "URITokenID": "C1AE6DDDEEC05CF2978C0BAD6FE27362498DGS691DC749DCDD3B95992978C0BA", +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------ | --------- | ------------------- | --------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that owns the URIToken to be burned. | +| `URITokenID` | String | Hash256 | The ID of the URIToken to burn. | + +### Special Transaction Cost + +The URITokenBurn transaction does not have any special transaction cost requirements. + +### Error Cases + +Besides errors that can occur for all transactions, URITokenBurn transactions can result in the following transaction result codes: + +| Error Code | Description | +| ------------------ | ----------------------------------------------------------------- | +| `tecNO_PERMISSION` | Occurs if the account does not have permission to burn the token. | + diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenbuy.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenbuy.mdx new file mode 100644 index 0000000..46f700f --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenbuy.mdx @@ -0,0 +1,48 @@ +--- +title: URITokenBuy +description: >- + The URITokenBuy transaction allows a user to buy a URIToken from the issuer. + This transaction is used to transfer ownership of a URIToken from the issuer + to the buyer. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[URIToken amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "URITokenBuy", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "URITokenID": "C1AE6DDDEEC05CF2978C0BAD6FE27362498DGS691DC749DCDD3B95992978C0BA", + "Amount": { + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "currency": "USD", + "value": "100", + }, +} +``` + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | --------------------------------------------------- | +| `Account` | String | AccountID | The address of the buyer's account. | +| `URITokenID` | String | Hash256 | The unique identifier of the URIToken to be bought. | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | The amount of currency to pay for the URIToken. | + +### Special Transaction Cost + +The URITokenBuy transaction has a standard transaction cost, which is the minimum fee required for any transaction in Xahau. + +### Error Cases + +Besides errors that can occur for all transactions, URITokenBuy transactions can result in the following transaction result codes: + +| Error Code | Description | +| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | +| `tecCANT_ACCEPT_OWN_NFTOKEN_OFFER` | Occurs if the owner of the token is the one claiming the offer. | +| `tecDST_TAG_NEEDED` | Occurs if the destination account requires a destination tag, but the transaction does not include one. | +| `tecNO_PERMISSION` | Occurs if the seller does not have the token listed for sale or the token `Destination` is not the account buying the token. | +| `temBAD_CURRENCY` | Occurs when the buying currency does not match the offer currency. | +| `tecINSUFFICIENT_PAYMENT` | Occurs when the buy amount is less than the offer amount. | +| `tecINSUFFICIENT_FUNDS` | Occurs when the buyer doesn't have sufficient funds including the `Fee` to purchase the token. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokencancelselloffer.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokencancelselloffer.mdx new file mode 100644 index 0000000..3721f51 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokencancelselloffer.mdx @@ -0,0 +1,36 @@ +--- +title: URITokenCancelSellOffer +description: >- + An URITokenCancelSellOffer transaction cancels a sell offer for a URIToken in + Xahau. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[URIToken amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "URITokenCancelSellOffer", + "Account": "r9cZA1mLK5R5Am25ArfXFmqgNwjZgnfk59", + "URITokenID": "C1AE6DDDEEC05CF2978C0BAD6FE27362498DGS691DC749DCDD3B95992978C0BA", +} +``` + + + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------ | --------- | ------------------- | -------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that owns the sell offer to cancel. | +| `URITokenID` | String | Hash256 | The ID of the URIToken to cancel the sell offer. | + +### Error Cases + +Besides errors that can occur for all transactions, URITokenCancelSellOffer transactions can result in the following transaction result codes: + +| Error Code | Description | +| ------------------ | ----------------------------------------------------------------------- | +| `tecNO_PERMISSION` | Occurs when the account executing the tx is not the owner of the token. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokencreateselloffer.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokencreateselloffer.mdx new file mode 100644 index 0000000..b35519c --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokencreateselloffer.mdx @@ -0,0 +1,47 @@ +--- +title: URITokenCreateSellOffer +description: >- + An URITokenCreateSellOffer transaction allows a user to create a sell offer + for a URIToken on Xahau's decentralized exchange. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[URIToken amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "URITokenCreateSellOffer", + "Account": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + "URITokenID": "C1AE6DDDEEC05CF2978C0BAD6FE27362498DGS691DC749DCDD3B95992978C0BA", + "Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + "Amount": { + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "currency": "USD", + "value": "100", + }, +} +``` + +### Fields + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | --------------------------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account creating the sell offer. | +| `URITokenID` | String | Hash256 | The ID of the URIToken being sold. | +| `Destination` | String | AccountID | _(Optional)_ The address of the account to receive the sell offer. | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | The amount of currency the account wants to receive in exchange for the URIToken. | + +### Error Cases + +Besides errors that can occur for all transactions, URITokenCreateSellOffer transactions can result in the following transaction result codes: + +| Error Code | Description | +| ------------------------ | -------------------------------------------------------------------------------- | +| `tecNO_TARGET` | Occurs if the target account does not exist. | +| `tecNO_PERMISSION` | Occurs if the account does not have permission to create a sell offer. | +| `tecINSUF_RESERVE_LINE` | Occurs if the account does not have a sufficient reserve to create a sell offer. | +| `tecINSUF_RESERVE_OFFER` | Occurs if the account does not have a sufficient reserve to create a sell offer. | +| `tecUNFUNDED_OFFER` | Occurs if the account does not have a sufficient balance to create a sell offer. | +| `tecOFFER_INVALID` | Occurs if the sell offer is invalid. | diff --git a/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenmint.mdx b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenmint.mdx new file mode 100644 index 0000000..7510819 --- /dev/null +++ b/src/content/docs/docs/protocol-reference/transactions/transaction-types/uritokenmint.mdx @@ -0,0 +1,63 @@ +--- +title: URITokenMint +description: >- + An URIToken Mint transaction mints a new URIToken and assigns ownership to the + specified account. The URIToken represents a unique digital asset that can be + used in various applications. +--- +\[[Source](https://github.com/Xahau/xahaud/blob/dev/src/ripple/app/tx/impl/URIToken.cpp)] + +_(Added by the \[URIToken amendment]\[].)_ + +### Example + +```json +{ + "TransactionType": "URITokenMint", + "Account": "rWYkbWkCeg8dP6rXALnjgZSjjLyih5NXm", + "Flags": 1, + "URI": "697066733A2F2F4445414442454546", + "Digest": "697066733A2F2F4445414442454546697066733A2F2F44454144424545467878", + "Destination": "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe", + "Amount": { + "issuer": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "currency": "USD", + "value": "100", + }, +} +``` + + + +| Field | JSON Type | \[Internal Type]\[] | Description | +| ------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ---------------------------------------------------------------------------------------------- | +| `Account` | String | AccountID | The address of the account that will own the minted URIToken. | +| `URI` | String | String | The URI associated with the minted URIToken. (256 byte max) | +| `Digest` | String | Hash256 | _(Optional)_ The digest of the URIToken. | +| `Destination` | String | AccountID | _(Optional)_ The address of the account that can buy the minted URIToken. | +| `Amount` | [Currency Amount](https://docs.xahau.network/technical/protocol-reference/data-types/currency-formats#specifying-currency-amounts) | Amount | _(Optional)_ The amount of currency the account wants to receive in exchange for the URIToken. | + +### URITokenMint Flags + +Transactions of the URITokenMint type support additional values in the `Flags` field, as follows: + +| Flag Name | Hex Value | Decimal Value | Description | +| ------------ | ------------ | ------------- | --------------------------------------------------------------------------------------------------------------------------------------- | +| `tfBurnable` | `0x00000001` | 1 | Allow the issuer (or an entity authorized by the issuer) to destroy the minted `URIToken`. (The `URIToken`'s owner can _always_ do so.) | + +### Error Cases + +### Special Transaction Cost + +The URIToken Mint transaction has a standard transaction cost, which is the minimum transaction cost required for all transactions. + +### Error Cases + +Besides errors that can occur for all transactions, URIToken Mint transactions can result in the following transaction result codes: + +| Error Code | Description | +| ----------------- | -------------------------------------------------------------------------------- | +| `tecDUPLICATE` | Occurs if a URIToken with the same URI from the same issuer already exists. | +| `tecDIR_FULL` | Occurs if the owner's directory is full and cannot accommodate the new URIToken. | +| `temINVALID_FLAG` | Occurs when the user specified an incorrect `Flag`. | +| `terNO_ACCOUNT` | Occurs if the sending account does not exist. | diff --git a/src/content/docs/docs/resources/media-kit.mdx b/src/content/docs/docs/resources/media-kit.mdx new file mode 100644 index 0000000..321c14b --- /dev/null +++ b/src/content/docs/docs/resources/media-kit.mdx @@ -0,0 +1,5 @@ +--- +title: Media Kit +--- + +Logos and branding guidelines are available on https://github.com/Xahau/Graphics \ No newline at end of file diff --git a/src/content/docs/docs/resources/whitepaper.mdx b/src/content/docs/docs/resources/whitepaper.mdx new file mode 100644 index 0000000..46f5c65 --- /dev/null +++ b/src/content/docs/docs/resources/whitepaper.mdx @@ -0,0 +1,194 @@ +--- +title: Whitepaper +--- +import { Aside } from '@astrojs/starlight/components'; + + + + + + +## 1. Summary + +1. The Xahau Ledger (Xahau) is the smart contract sidechain for the XRPL ecosystem. It is a fork of the XRP Ledger’s (XRPL’s) open-source rippled codebase that embodies all the useful and innovative features of the XRPL, including its environmental sustainability, but tweaks and upgrades the codebase to support smart contracts. +2. Xahau’s core features are: + * **XRPL Core:** Xahau retains the key features that have made the XRPL one of the most enduring and popular networks, including the **XRP Ledger Consensus Protocol** (Previously: Ripple Protocol Consensus Algorithm), the **DEX**, and the logic of protecting the ledger against spam and bloat by charging and burning fees in the native token, but it substitutes the recent **XLS-20 NFTs** for the cleaner, simpler **URITokens**. + * **Hooks for Smart Contracts:** The big new feature of Xahau is Hooks, the smart contract implementation for rippled. Hooks are small pieces of code installed on an account that impose rules on the transactions the account sends or receives before those transactions can be finalized. + * **Native Token & Better Tokenomics:** Xahau will be secured by its native token, XAH (currency code: XAH), and powered by better tokenomics designed to reward validators and support smart contracts. + * **Genesis Hook Governance Game:** Xahau’s Genesis account is powered by a Hook that regulates, amongst other things, the emission of new XAH and this Hook is governed by a two-tiered governance game with up to 20 independently owned validators as participants. +3. In concert, these features create a new network within the XRPL ecosystem that implements the Hooks amendment to deliver fast, cheap, secure smart contracts for the XRPL ecosystem supported by a properly incentivised community of validators and developers. +4. The development of the Xahau Ledger has been driven by the Xahau Launch Alliance, five experienced and committed entities within the XRPL community that have carried the cost and risk of establishing the new network without an ICO. +5. Xahau will launch fully functional and decentralised with over 10 independently owned validators run by a representative mixture of the XRPL ecosystem, including developers, exchanges, and long-term community members. + +## 2. Xahau – Built from the XRPL’s DNA + +1. Xahaud - the software that runs Xahau - is a fork of rippled, the open-source codebase of the XRPL. It retains the key features that have made the XRPL one of the most popular and enduring networks since it was launched in 2012. + +### XRP Ledger Consensus Protocol + +2. Xahau uses the XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm) – sometimes called Proof of Association (PoA). It is designed to overcome the limitations of traditional consensus mechanisms like Proof of Work (PoW) or Proof of Stake (PoS), particularly the high energy consumption associated with PoW. +3. The XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm) works as follows + * **Validator Proposal:** Each validator proposes a new set of transactions, called a "candidate set," which they believe should be included in the +next ledger. This candidate set includes both new transactions and any transactions that were not previously included in a validated ledger. + * **Agreement Phase:** Validators communicate with each other to exchange and evaluate candidate sets. They independently verify the validity and order of transactions proposed by other validators. Through a series of iterative rounds, validators attempt to converge on a single candidate set that the majority agrees upon. + * **Finalization:** Once a supermajority of validators (at least 80%) agrees on a specific candidate set, that set is considered "finalized." Finalized candidate sets become the basis for the next ledger. + * **Ledger Closing:** The ledger is closed, and a new ledger is created based on the transactions in the finalized candidate set. This process occurs roughly every 3-5 seconds in the XRPL, allowing for fast transaction settlement times. +4. Under the XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm), each validator specifies a UNL (Unique Node List) being a list of other validators it trusts. The canonical ledger is found through the overlap between the UNLs of all the validators. +5. To facilitate social consensus on the appropriate UNL, several entities, including the XRPL Foundation, publish recommended Validator Lists (or VLs) of the validators they deem suitably trustworthy. Following a generally accepted dUNL helps ensure you stay on the main ledger and do not unintentionally end up following an irrelevant fork. Xahau will follow a similar, social-consensus approach to defining a dUNL, with organisations like the XRPL Foundation publishing its recommended VL. +6. The XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm) Protocol provides several advantages, including high scalability, low energy consumption, and resistance to censorship and network forks. By utilizing a set of trusted validators and this unique consensus algorithm, Xahau achieves fast and secure transaction processing while maintaining decentralization and reliability. + +### The DEX + +7. Xahau retains a version of the XRPL’s limit order book decentralized exchange (DEX) that allows users to trade and exchange assets directly on the ledger. The DEX leverages Xahau's decentralized and trustless architecture to enable peer-to-peer asset trading without the need for intermediaries. +8. In summary, the decentralized exchange works as follows: + * **Order Creation:** Users can create buy or sell orders on the DEX by specifying the asset they want to trade, the desired quantity, and the price they are willing to accept or pay. + * **Order Matching:** The DEX’s order book maintains a record of all open buy and sell orders. When a new order is placed, the DEX automatically matches it against existing orders based on price and quantity. + * **Cross-Currency Trading:** The DEX supports cross-currency trading, enabling users to trade between different assets. To facilitate this, the DEX uses the ledger’s native currency as a bridge currency, allowing users to convert one asset to the native currency and then to another asset. + * **Pathfinding Function:** The pathfinding function is a key component of the DEX. It helps users find the most efficient trading path when converting one asset to another. For example, if a user wants to trade Asset A for Asset D, but there is no direct market available, the pathfinding function will search for the best sequence of trades (e.g., A to B, B to C, and C to D) to achieve the desired conversion with minimal slippage and fees. + * **Automatic Order Execution:** Once a trade is matched, the DEX automatically executes the transaction. The ledger's consensus mechanism ensures that the transaction is validated and added to the ledger, providing a high level of security and immutability. + * **Trustless and Decentralized:** The DEX operates in a trustless and decentralized manner. It does not rely on a centralized exchange or require users to deposit their funds into a third-party wallet. Instead, users maintain control over their assets throughout the trading process, reducing counterparty risk. + * **Low Fees and Fast Settlement:** Trading on the DEX incurs minimal fees compared to traditional centralized exchanges. Xahau's consensus protocol allows for fast settlement times, enabling near-instantaneous transaction processing. +9. With these features, the DEX provides users with a convenient and secure platform for peer-to-peer token trading. By leveraging the trustless and decentralized nature of Xahau, the DEX offers efficient cross-token trading and seamless order matching while maintaining user control and privacy. + +### Burned Transaction Fees + +10. To protect itself against spam and bloat, the XRPL charges transaction fees and account reserves in its native currency and burns all transaction fees, rather than redistribute them to validators. Xahau follows this “fees charged and burned” model to likewise protect itself. +11. While this is a proven mechanism for protecting the ledger, it has implications for Xahau’s Tokenomics, as discussed later. The fees burned by Xahau’s smart contracts, while still small, will be much higher and more variable than standard transaction fees on the XRPL. + +### URIToken NFTs instead of XLS-20 NFTs + +12. Unlike the XLS-20 NFT standard introduced to the XRPL, which relies on compressing NFTs into on-ledger “pages”, Xahau will use URIToken objects. +13. URITokens (short for Uniform Resource Identifier Token) are an innovative way to represent and manage NFTs, their metadata and ownership information within Xahau. Each token is a first-class ledger object with a unique address that does not change when the current owner does. +14. URIToken NFTs have many benefits over the XLS-20 NFT standard, including: + * **Lightweight and Efficient:** URITokens are first-class on-ledger objects that can be created, destroyed, transferred, bought and sold, and which interoperate easily with Hooks. Trading is limited to a single sell offer per token, that can be accepted either by the specified destination account or, if no destination is specified, then the general public. There is no brokered mode. + * **Interoperability and Immutability:** URITokens come with a built-in extensible metadata JSON standard and an optional Digest field (a hash making the content of the NFT immutable). This provides flexibility for developers and creators to choose their preferred storage solutions, such as IPFS or traditional web servers. It also promotes interoperability with existing NFT standards and platforms, facilitating the integration with the broader NFT ecosystem. + * **Improved User Experience:** URITokens can be easily located by their keylet (on ledger address) that does not depend on the current owner of the token. The NFT metadata and ownership information can be easily accessed and updated through standard web protocols. Users can simply click on the URI associated with an NFT to view its details, including images, descriptions, and provenance. This approach simplifies the user experience and reduces the complexity of interacting with NFTs on Xahau. +15. Thus, URITokens provide a lightweight, flexible, and cost-efficient solution for NFTs on Xahau. + +## 3. Hooks – Smart Contracts for the XRPL Ecosystem + +1. Hooks is a smart contract solution developed specifically for the XRPL ecosystem. Hooks are small, efficient pieces of code defined on a Xahau account that execute logic on transactions sent to or received by the account before those transactions are finalised in the ledger. Hooks are thus a way for developers to create and deploy smart contracts on Xahau, opening a wide range of possibilities for decentralized applications (dApps) and automated transactions. +2. Xahau implements the Hooks amendment as a sidechain so the XRPL ecosystem can benefit from Hooks now rather than later. It also allows the XRPL community to better evaluate whether and how to implement Hooks on the XRPL mainnet in the future. + +### Benefits of Hooks + +3. Some key benefits of Hooks over other smart contract solutions include: + * **Simplicity and Efficiency:** Hooks are lightweight and efficient compared to conventional smart contract solutions. The underlying architecture of Xahau, which focuses on transaction settlement and fast consensus, ensures quick execution of smart contracts without compromising performance. + * **Native Integration:** Hooks are a layer-one smart contract solution and thus live natively inside the ledger, allowing developers to create contracts that interact directly with on-ledger objects, balances and transactions. In contrast to layer-two smart contract solutions, this tight integration simplifies the development process and ensures seamless interoperability with Xahau's ecosystem. + * **Low Fees and Scalability:** Hooks leverage Xahau's low transaction fees and high scalability. Like most chains, Xahau can handle a high volume of transactions per second, making it suitable for applications that require fast and cost-effective smart contract execution. + * **Security and Reliability:** Hooks inherit the robust security and reliability of the XRPL. The XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm), which powers Xahau, ensures a decentralized network with consensus among trusted validators. This strong security foundation provides confidence for developers and users alike. + * **Ecosystem Compatibility:** Hooks are designed to be compatible with existing XRPL tools and services, making it easier for developers to integrate smart contracts into their applications. This compatibility enables seamless interaction with other features of the XRPL, such as decentralized exchanges and payment channels. + * **Account Decentralisation:** Using Hooks it is possible for a Xahau account to be fully autonomous and to emit and receive transactions according to the logic of its Hook, instead of relying on external private key holders to manually authorise transactions. + +### Sample Use-Cases + +4. By introducing smart contract capabilities to the XRPL ecosystem, Hooks offer a powerful and efficient solution for developers seeking to build decentralized applications and automate transactions. Examples of the kinds of functions Hooks can achieve include: + * **Whitelists:** A Hook enabled account can protect accounts against fraud or sanctioned transactions by being coded to only accept or send transactions to whitelisted accounts. + * **Blacklists:** A hook enabled account can be coded to refuse to receive or send transactions to any prohibited (blacklisted) account. + * **Sophisticated Escrow:** A Hook enabled account can hold any asset received from nominated account and only forward or return those assets if told to do so by a valid transaction that meets predetermined criteria. + * **Automated Registry:** A Hook enabled account can act as an automated registry and mint and redeem URI NFTs as evidence of registration or registration rights. + * **Self-Sovereign Treasury:** Issued currencies can mimic decentralised, counterparty-free assets by being deposited into a self-owned Account with a Hook that emits the currency according to a disclosed and predetermined emission schedule. +5. The combination of simplicity, low fees, scalability, security, and ecosystem compatibility means Xahau offers early access to an attractive smart contract solution for the XRPL ecosystem. Xahau’s experience with Hooks will help the community determine whether and how to implement Hooks on the XRPL in the future. + +## 4. XAH – Native Token & Tokenomics + +1. Xahau is secured by its native token, XAH. Its salient details are as follows: + * **Native Token:** XAH + * **Ticker:** XAH + * **Smallest Unit:** 1 drop or 0.000001 XAH + * **Function:** XAH is the currency of the network. It is a utility token to purchase network services. Like the XRPL, transactions on Xahau incur a fee or reserve that is charged in XAH to protect the Ledger against spam and bloat. + * **Initial Liquidity:** 600 million distributed to launch participants. + * **Max Supply:** Uncapped. + * **Emission Mechanisms:** The supply of XAH is determined via the amendments enabled in Xahau’s consensus protocol: + * **Monthly Balance Adjustment:** To put back into circulation some of the XAH burned from transaction fees, each active user can claim an increase in their account balance of ~0.34% of their average monthly balance (equal to 4% pa. compounding). This emission is controlled by the Protocol Governance Game which uses a combination of the Hooks, BalanceRewards and the XahauGenesis amendments. + * **Monthly Seat Rewards:** To put back into circulation some of the XAH burned from the transaction fees, and to incentivise active and appropriate governance, an amount matching the total claimed Monthly Balance Adjustments is also rewarded to Governance Game validators. + +### Initial Distribution + +2. The Launch parties have invested significant time and resources to launch Xahau. An initial distribution is provided at the protocol level by the XahauGenesis amendment. +3. The protocol will pay a modest 600 million Xahau XAH as follows: 12 million to each of the eight Governance Game validator Seats on launch. + * 16 million additional to GateHub for DEX stablecoin liquidity bootstrapping. + * 160 additional million to XRPL Labs (Xaman) for Intellectual Property - Xaman has carried the main technical and financial burden of developing Hooks and xahaud. This additional distribution is for that effort. + * 328 million to the XRPL Foundation (now INFTF), to help ensure the health of the XRPL Protocol (now Xahau) ecosystem moving forward. + +### Monthly Balance Adjustment + +4. One challenge Xahau must manage is the additional expense of smart contracts compared to normal XRPL transactions. +5. On the XRPL, transaction fees cost as little as one drop or 0.000001 XRP. Against a total supply of 100 billion XRP, this is a trivial-but-sufficient cost. Hooks transactions, on the other hand, can cost orders of magnitude more to set and to trigger. Further, while every XRPL transaction is standardised, Hooks can vary enormously in their complexity and cost. To properly protect itself against spam and bloat from its Hooks, the Ledger must charge appropriately (and dynamically) for the size and logic complexity of every Hook transaction. +6. The consequence is that, as a smart contract chain that burns fees, XAH could easily be burned to near-zero, and certainly much more rapidly than equivalent XRP would be burned on the XRPL, potentially leading to perverse incentives to horde Xahau rather than use it to deploy and run Hooks. +7. To guard against these risks, Xahau needs a protocol-level mechanism that puts burned tokens back into circulation, but one that does not simply incentivise high fees. This is the purpose of the monthly balance adjustment. +8. The Monthly Balance Adjustment works as follows: + * Each month, each Xahau account can choose to claim (against the protocol) an adjustment based on their average XAH balance (computed since the last adjustment). The adjusted amount is the equivalent of 4% p.a. compounded (roughly 0.34% per month). + * Users can claim their balance adjustment by sending a RewardClaim transaction to the Genesis account at any time provided 30 days has passed since the last claim. Doing so demonstrates they are an active user. + * Upon receipt of the claim transaction, the protocol, via the BalanceRewards and XahauGenesis amendments, increases the user’s account balance by the balance adjustment. + * Unclaimed balance adjustments are foregone as a penalty for inactivity. + * 4% is the initial rate at launch, but it can be changed via the Governance Game if it proves too small or too large in the future. +9. This mechanism allows active users to claim a monthly adjustment that puts further XAH into circulating supply, mitigating the risk of the token being burned down to zero through smart contract execution fees. + +### Monthly Governance Validator Rewards + +10. The Xahau Genesis Account is enabled with a Hook that controls, among other things, the emission of XAH. This Hook needs a governance arrangement so that it can be monitored, amended, and/or replaced in the face of changing network and real-world conditions. +11. It is well known that XRPL mainnet validators do not receive any kind of reward for the services they provide for underpinning the mainnet Ledger. However, infrastructure costs money to run, and real-world experience shows that this lack of incentive leads to a lack of actively managed validators. +12. The Xahau Genesis Hook needs to know, or be told, which accounts it must trust when deciding whether to update itself. So, those accounts must be known in advance, rather than emerging from the overlapping UNLs. +13. The technical solution to this problem is an incentivised Genesis Hook Governance Game that rewards certain Validators for overseeing the Hook. It works as follows: + * There are 20 “Seats” on the Genesis Hook Governance Game. + * Each Seat is controlled either by a single Xahau Account (Level 1) or a self-managing committee of 3-20 Accounts (Level 2). + * For each occupied Seat, the protocol mints and distributes 1/20th of the total Monthly Balance Adjustments claimed that month. + * If a Seat is held by a committee of Accounts, the rewards for that Seat are split in a manner of that committee’s choosing. + * If no users claim a Balance Adjustment that month no rewards are paid to any validators. + * Each Flag Ledger (256 ledgers) an on-ledger record called a UNLReport is generated. This report contains a list of validators’ public keys that 80% of other validators believe participated adequately in consensus since the previous Flag Ledger. The Genesis Hook will only distribute validator rewards to Seats that correspond to the public keys of validators on the UNLReport. +14. Thus, the Genesis Hook Governance Game includes a reward mechanism designed to ensure that trusted accounts are rewarded for running trustworthy validators, that those rewards are linked to user activity, and that those rewards put new XAH into distribution, mitigating the risk of a token liquidity crunch from high smart contract execution fees. + +## 5. Xahau Governance Game +1. XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm) chains rely on a robust overlap in validator UNLs to define the canonical ledger. If a validator does not trust enough of the same machines that everyone else trusts, they risk unknowingly listening to an irrelevant fork of the ledger. Determining the best UNL is a matter of social (off-chain) consensus. +2. To assist that social consensus, various entities publish dUNLs – lists of validators everyone should follow. Xahau will follow the same approach, with the XRPL Foundation and others expected to publish such lists. So, like the XRPL, Xahau will be a public permissionless chain for which anyone can run a validator. And like the XRPL, any update of the protocol will be dependent on more than 80% of UNL validators supporting the changes, in the same manner as the XRPL. +3. While the dUNL helps define the validators responsible for the canonical Ledger, Xahau has a second governance challenge, not present in the XRPL mainnet: the governance of its Genesis Hook. The XRPL mainnet minted all of its XRP on creation. Xahau cannot follow this approach. Its native token needs to be minted in response to the happening of predefined events (i.e. Burn2Mint, Account Adjustments, Validator Rewards.) It uses a Hook on its Genesis Account to achieve this. +4. This means Xahau needs a governance mechanism for its Genesis Hook in case the Hook needs to be adjusted or replaced. This is known as the Governance Game: + * **Purpose:** The Governance Game exists to ensure that the UNL validators remain active and allows those active members to maintain the Hook on the Genesis account that controls the distribution of XAH. + * **Seats:** There are 20 Seats at a table. A Seat is a Xahau Account whose vote counts in the Governance Game. + * **L1 Table:** The Governance Game requires at least the top-level table. This is called the Level 1 table (L1 Table). This table by definition exists only on the Genesis account according to the Governance Game Hook installed there. A seat at the L1 table may be filled by an Account or may be empty. These seats are called L1s. + * **L2 Table:** An L1 seat may itself be filled by an Account which has another, different, Governance Hook installed on it. The seats at this table are called L2s, and the table is an L2 Table. The structure is a self-managing committee of 3-20 Accounts that collectively control the L1 seat and its voting rights. Thus up to 400 Accounts may be involved in the two layer Governance game, depending on the mix of L1 and L2 Seats. + * **Filling Seats:** L1 Seats are filled or vacated by 80% vote of all existing filled L1 Seats. For L2 Seats, the committee of Accounts that collectively holds that L1 Seat invites or disinvites new members (up to a maximum or 20 and down a minimum of 3) by majority vote, or according to whatever other logic or rules they deem fit. No other Seats have any control over the members of an L2 Table. + * **Voting:** Each L1 Seat has 1 vote in the Governance Game. For L2 Seats, the single vote of its L2 table is determined by whatever logic that L2 table decides. The default is more than 50% vote of the L2 Seat members at that L2 table. + * **Hook Changes:** All changes to the Hook are voted on via the Governance Game. A Hook change is only successful if supported by the defined % vote of all Seats. The regular vote is 80%, but for the increase of the rate of balance adjustment it is 100%. + * **Rewards:** To incentivise L1 Seats to run reliable validators, L1 Seats earn monthly Rewards provided they actively participate in consensus. + * **Foundation of dUNL**: The validators run by those participating in the Genesis Hook Governance Game should form the foundation of any dUNL, as any Seat that performs unreliably risks being voted out by the other Seats. +5. The different types of Seats allow for a greater diversity of participating Accounts without undermining security. Level 1 Seats are suitable to Accounts controlled by significant entities the community can trust, while Layer 2 Seats allow a broader pool of participants, but since their collective participation counts as 1 vote, their numbers do not overwhelm the trust placed in Level 1 Seats. +6. Thus, the Governance Game allows up to 400 Accounts to participate and rewards those Accounts for doing so provided they also participate in consensus by running a reliable validator. + +## 6. The Xahau Launch Alliance + +1. Xahau has been developed by an alliance of 5 independent entities with a track record of building on and supporting the XRPL ecosystem. Those entities are as follows: + * XRPL Labs (Xaman), the software developer behind the XUMM wallet, Hooks, and Xahaud that has carried most of the expertise and cost of developing Xahau. + * GateHub Limited, a multinational technology company, crypto exchange, and crypto service provider, including Stablecoins issued on the XRPL. + * Titanium OU, an IT consulting and infrastructure firm specialising in providing secure hosting and a major provider of the infrastructure for the XRPL (as Alloy Networks). + * Evernode Labs Ltd, the developer of the Evernode smart contract project and responsible for deploying it to Xahau. + * Digital Governing OU, an incorporated entity associated with a globally active firm for accounting, audit, and legal services. + +## 7. Launch Fully Functional & Decentralised + +1. Xahau will launch fully functional and decentralised without raising funds. No Centralised Control +2. Xahau will launch with 8 of its 20 Governance Game Seats filled: + * 5 will be Layer 1 Seats, each filled by a member of the Xahau Launch Alliance. + * 3 will be Layer 2 Tables, one of which will be filled by a committee of Exchanges and the other a diverse committee of XRP community projects, developers, and long-term supporters. + * 1 will be FYEO, a company offering code audit and review services on blockchain development, including software such as Hooks. + +### No Funds Being Raised + +3. There is no ICO, and no funds are being raised from the launch. +4. The Xahau Alliance members have each independently funded their own development efforts. There’s no communal funding, nor any pooling of money or resources for the further development of Xahau. Nor is there any roadmap, or “Xahau Foundation”, or other centralised treasury. Any further development is wholly at the discretion of independent actors within the ecosystem. + +### No Promises + +5. The Governance Game members are independent entities. There is no agreement, arrangement, or understanding between them about how to cast their vote, deploy their resources, or use their assets, including any XAH. It is only the logic of the Game – be a trustworthy Validator in the eyes of the other members or be voted out of the Game – that drives Validator behaviour. This is an inherent feature of the XRP Ledger Consensus Protocol (Previously: Ripple Protocol Consensus Algorithm) (PoA) mechanism Xahau uses. + +### No Further Features Needed + +6. While software, by its nature, needs to be maintained, there are no essential functionalities missing from Xahaud or in need of further development for the software to be useful as a smart contract sidechain of the XRPL. \ No newline at end of file diff --git a/src/content/docs/docs/support/help-us.mdx b/src/content/docs/docs/support/help-us.mdx new file mode 100644 index 0000000..b6360f4 --- /dev/null +++ b/src/content/docs/docs/support/help-us.mdx @@ -0,0 +1,16 @@ +--- +title: Help Us +--- +This page exists for us to track changes requested by users who don't necessarily want to create a PR to update the documentation but have suggestions. + +## Not Documented + +* accounts on xahau start at a sequence that matches the timestamp of the previous ledger +* Pseudo tx docs missing: UNLReport, EmitFailure, Etc +* URIToken Size Limit +* AccountDelete is still listed as a transaction but is disabled on Xahau + +## Suggestions + +* Move/Copy HookExecutions, HookEmissions to metadata +* Add second security audit on hooks to `Compliance` diff --git a/src/content/docs/docs/what-is-different.mdx b/src/content/docs/docs/what-is-different.mdx new file mode 100644 index 0000000..cc1db2f --- /dev/null +++ b/src/content/docs/docs/what-is-different.mdx @@ -0,0 +1,89 @@ +--- +title: 'XRPL/Xahau: What is Different?' +description: A list of notable differences between the XRP Ledger and Xahau. +--- +import { Aside, LinkCard } from '@astrojs/starlight/components'; + + + + +#### IOU Token Escrow & PayChannels + +Xahau introduces IOU Token Escrow and PayChannels as unique features, enhancing transaction flexibility and security. They facilitate the temporary holding of IOU tokens under predefined conditions (escrow) and the establishment of payment channels for efficient, off-ledger transactions. + + + +#### URITokens NOT NFTokens + +Instead of using NFTokens like XRPL, Xahau employs URITokens. URITokens are a form of non-fungible digital assets with unique identifiers and metadata, offering a novel approach to asset representation on the blockchain. + + + +#### Different Repo + +Xahau and XRPL operate from different repositories, signifying that they are separate protocols with their own development trajectories and documentation. This distinction implies that Xahau may offer unique features and optimizations not found in XRPL. + +[https://github.com/Xahau/xahaud](https://github.com/Xahau/xahaud) + +#### Different Build Process (WASM & LLVM) + +Xahau's build process incorporates WebAssembly (WASM) and the Low-Level Virtual Machine (LLVM), which is not described in the XRPL build process. Xahau is utilizing these technologies for enhanced smart contract capabilities and to improve the performance and cross-platform compatibility of its codebase. + + + +#### Different Amendment Time (5 days) + +The amendment process in Xahau has a specified time frame of 5 days, differing from XRPL's timeline. Amendments are protocol changes, and the 5-day period refers to the duration validators have to reach a consensus and implement these changes. + + + +#### Different Starting Sequence + +Xahau employs a different starting sequence for accounts than XRPL. The initial sequence on the account is the ripple epoch time when the account was create/imported into Xahau. + +#### Import / Burn 2 Mint + +Importing from XRPL to Xahau grants users 2 XAH tokens, indicating an incentive mechanism to encourage asset migration or bridging from XRPL to Xahau, potentially to enhance network adoption and liquidity. + + + +#### Balance Rewards (Rewards for using XAH) + +Xahau offers balance rewards for utilizing XAH, a feature absent in XRPL. This is a reward system for holding or using Xahau's native token, XAH, to promote network engagement and stability. + + + +#### Hooks + +Hooks in Xahau, which are not present in XRPL, are programmable scripts or smart contract-like functions that can be attached to accounts. They add a layer of programmability and automation to the network's operations. + + + +#### Governance Structure + +Xahau's governance structure differs from XRPL's. Xahau has its own approach to decision-making, proposal systems, or validator roles, which could influence the network's evolution. + + + +#### Node Requirements + +Running a Xahau node has different requirements compared to an XRPL node. These differences could be related to the technical specifications needed to support Xahau's unique features and network demands. + + + +#### Native Token + +Xahau's native token is XAH, distinct from XRPL's XRP. As the primary currency within the Xahau network, XAH likely serves as the main medium of exchange and a store of value, central to the network's economic framework. + + + +#### Versioning (Uses Dates) + +Xahau employs a date-based versioning system, unlike XRPL's versioning approach. This method may provide a more intuitive means of tracking the network's updates and historical development. + + diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro new file mode 100644 index 0000000..6b3bcf7 --- /dev/null +++ b/src/layouts/BaseLayout.astro @@ -0,0 +1,22 @@ +--- +import Header from '../components/Header.jsx'; +import Footer from '../components/Footer.astro'; +import CookieConsent from '../components/CookieConsent.astro'; +const canonicalURL = new URL(Astro.url.pathname, Astro.site); +--- + + + + + {Astro.props.frontmatter?.title ? `Xahau: ${Astro.props.frontmatter?.title}` : 'Xahau'} + + + + + +
+ +