Initial commit

This commit is contained in:
Thomas Silkjær
2025-07-03 09:24:20 +02:00
commit 3f36194a10
296 changed files with 26997 additions and 0 deletions

24
.gitignore vendored Normal file
View File

@@ -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/

4
.vscode/extensions.json vendored Normal file
View File

@@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

36
README.md Normal file
View File

@@ -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 |

300
astro.config.mjs Normal file
View File

@@ -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/'
});

7465
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

25
package.json Normal file
View File

@@ -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"
}
}

12
public/favicon.svg Normal file
View File

@@ -0,0 +1,12 @@
<svg width="180" height="180" viewBox="0 0 180 180" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_834_164)">
<rect width="180" height="180" rx="40" fill="#0E0143"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M97.9191 125.747L106.355 138H137.482L127.298 123.21L97.9191 125.747ZM87.9795 111.309L87.8937 111.184L72.1277 138H42.078L72.9362 89.3546L41 43H72.1277L90.0497 69.1419L105.411 43H135.461L105.007 90.8369L116.936 108.161L88.0408 111.205L87.9795 111.309Z" fill="white"/>
<path d="M167.632 104.614C169.337 105.392 169.535 107.671 167.988 108.715L143.979 124.925C142.432 125.969 140.301 124.996 140.143 123.173L137.688 94.8819C137.53 93.059 139.464 91.7535 141.169 92.5319L167.632 104.614Z" fill="#F7F7F7"/>
</g>
<defs>
<clipPath id="clip0_834_164">
<rect width="180" height="180" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 856 B

View File

@@ -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: "<a href=\"/privacy-policy\">Privacy Policy</a>"
},
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 <span class=\"pm__badge\">Always Enabled</span>",
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 <a class=\"cc__link\" href=\"/privacy-policy\">Privacy Policy</a>."
}
]
}
}
}
}
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/assets/gems/1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

BIN
src/assets/gems/10.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB

BIN
src/assets/gems/11.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

BIN
src/assets/gems/12.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
src/assets/gems/13.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

BIN
src/assets/gems/14.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
src/assets/gems/15.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 KiB

BIN
src/assets/gems/16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

BIN
src/assets/gems/17.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

BIN
src/assets/gems/2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

BIN
src/assets/gems/3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 KiB

BIN
src/assets/gems/4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

BIN
src/assets/gems/5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 KiB

BIN
src/assets/gems/6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 641 KiB

BIN
src/assets/gems/7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

BIN
src/assets/gems/8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 177 KiB

BIN
src/assets/gems/9.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 KiB

158
src/assets/worldmap.svg Normal file
View File

@@ -0,0 +1,158 @@
<svg viewBox="0 0 1613 918" fill="none" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid meet">
<g opacity="0.03">
<path d="M724.129 648.029C724.129 655.056 718.179 660.759 710.854 660.759H682.879C675.554 660.759 669.604 655.056 669.604 648.029V642.229C669.604 635.249 675.554 629.549 682.879 629.549H710.854C718.179 629.549 724.129 635.252 724.129 642.229V648.029Z" fill="url(#paint0_linear_1_14)"/>
<path d="M602.449 598.782H600.089C592.764 598.782 586.814 604.485 586.814 611.462V628.961C586.814 635.941 590.206 641.641 596.059 641.641H597.534C603.878 641.641 602.452 647.344 602.452 654.32V662.48C602.452 669.558 608.352 675.16 615.727 675.16H636.031C643.356 675.16 649.306 669.558 649.306 662.48V641.641V611.462C649.306 604.482 643.356 598.782 636.031 598.782H602.449Z" fill="url(#paint1_linear_1_14)"/>
<path d="M767.49 492.079C761.248 492.079 755.839 496.256 754.511 502.057L747.089 534.742C745.811 540.59 740.352 544.72 734.11 544.72H650.876C643.551 544.72 637.554 550.423 637.554 557.4V567.034C637.554 574.014 643.551 579.667 650.876 579.667H653.579C660.954 579.667 666.901 585.37 666.901 592.397V598.688C666.901 605.668 672.851 611.368 680.176 611.368H783.223C789.465 611.368 794.874 607.238 796.202 601.39L817.736 507.467C818.62 503.73 817.588 499.798 815.131 496.851C812.573 493.853 808.788 492.082 804.757 492.082H767.49V492.079Z" fill="url(#paint2_linear_1_14)"/>
<path d="M849.446 464.602C848.266 470.551 842.81 474.825 836.369 474.825H778.603C774.62 474.825 770.885 473.155 768.377 470.255C765.819 467.355 764.787 463.52 765.527 459.787L773.884 418.058C775.114 412.109 780.57 407.784 786.96 407.784H844.726C848.71 407.784 852.444 409.454 855.002 412.405C857.51 415.255 858.542 419.089 857.806 422.826L849.446 464.602Z" fill="url(#paint3_linear_1_14)"/>
<path d="M689.713 756.746C692.664 754.582 696.547 754.29 699.744 755.96C702.988 757.63 705.005 760.876 705.005 764.513V760.876C705.005 766.136 709.331 770.461 714.592 770.461H754.121C759.382 770.461 763.708 766.136 763.708 760.876C763.708 755.567 767.984 751.241 773.295 751.241H777.376C780.18 751.241 782.832 752.471 784.654 754.485L836.958 814.005C838.48 815.725 839.317 817.987 839.317 820.346V874.705C839.317 877.309 838.285 879.816 836.416 881.587L805.984 911.077C804.212 912.747 801.805 913.732 799.298 913.732H760.115C756.723 913.732 753.576 911.961 751.906 909.064L742.762 893.631C741.091 890.731 737.895 888.963 734.503 888.963H631.063C625.752 888.963 621.476 884.638 621.476 879.379V811.454C621.476 808.359 622.901 805.506 625.409 803.687L689.713 756.746Z" fill="url(#paint4_linear_1_14)"/>
<path d="M358.941 866.548C355.893 876.082 347.045 882.619 336.967 882.619H330.378C323.053 882.619 316.169 879.13 311.795 873.232C307.469 867.335 306.238 859.666 308.403 852.689L319.022 818.874C322.071 809.239 330.969 802.753 341.048 802.753H347.586C354.961 802.753 361.842 806.194 366.169 812.092C370.495 818.041 371.773 825.659 369.561 832.636L358.941 866.548Z" fill="url(#paint5_linear_1_14)"/>
<path d="M1029.88 34.8906C1029.88 15.7719 1045.31 0.339844 1064.44 0.339844H1513.25C1528.79 0.339844 1542.45 10.7611 1546.58 25.8L1595.95 206.767C1599 217.874 1596.24 229.818 1588.67 238.518L1475.2 368.962C1468.61 376.53 1459.12 380.855 1449.14 380.855H1431.54C1418.02 380.855 1405.78 388.719 1400.13 401.005C1394.48 413.292 1396.54 427.743 1405.39 437.966L1430.76 467.358C1437.3 475.027 1446.88 479.399 1456.91 479.399H1576.43C1595.55 479.399 1610.99 494.882 1610.99 513.95V645.475C1610.99 652.358 1608.93 659.139 1605.09 664.839L1444.57 902.427C1438.13 911.961 1427.41 917.664 1415.91 917.664H1366.6C1356.91 917.664 1347.67 913.534 1341.13 906.456C1334.59 899.281 1331.35 889.744 1332.13 880.112L1361.29 542.21C1362.32 530.562 1357.41 519.206 1348.16 511.984L1199.79 395.991C1192.86 390.682 1188.28 382.868 1186.91 374.218L1166.55 245.495C1163.9 228.685 1149.44 216.349 1132.43 216.349H1064.44C1045.32 216.349 1029.88 200.866 1029.88 181.798V34.8906H1029.88Z" fill="url(#paint6_linear_1_14)"/>
<path d="M138.542 203.719C138.542 207.355 135.59 210.256 132.003 210.256H74.7284C71.1383 210.256 68.2373 207.355 68.2373 203.719V97.1633C68.2373 93.5742 71.1383 90.6741 74.7284 90.6741H132.003C135.594 90.6741 138.542 93.5742 138.542 97.1633V203.719Z" fill="url(#paint7_linear_1_14)"/>
<path d="M46.2624 203.719C46.2624 207.355 43.311 210.255 39.7241 210.255H20.5496C16.9123 210.255 14.0112 207.355 14.0112 203.719V168.92C14.0112 165.331 16.9123 162.43 20.5496 162.43H39.7241C43.3142 162.43 46.2624 165.331 46.2624 168.92V203.719Z" fill="url(#paint8_linear_1_14)"/>
<path d="M508.25 0.339838C499.302 0.339838 491.19 5.54887 487.405 13.6109L446.747 100.803C442.961 108.912 434.8 114.074 425.851 114.074H400.629C392.467 114.074 384.947 109.749 380.765 102.769L346.349 44.233C342.218 37.2058 334.648 32.8806 326.486 32.8806H280.33C271.627 32.8806 263.714 37.7468 259.781 45.4629L190.855 181.706C185.446 192.42 189.184 205.594 199.558 211.835L225.566 227.512C235.991 233.803 249.558 230.856 256.443 220.828L272.225 197.824C277.681 189.813 287.564 186.126 296.906 188.485L280.437 184.308C292.68 187.403 300.103 199.841 297.104 212.077L290.909 237.439C288.401 247.663 279.16 254.938 268.541 254.938H107.178C103.046 254.938 98.9687 256.02 95.4289 258.181L11.3084 307.818C4.32638 311.996 0 319.513 0 327.673V383.604C0 396.284 10.3235 406.608 23.0572 406.608H52.0141C64.6975 406.608 75.0241 409.804 75.0241 418.108C75.0241 433.54 85.3477 441.158 98.0814 441.158H95.8694C108.553 441.158 118.879 434.031 118.879 418.108C118.879 408.671 129.203 406.608 141.937 406.608H162.732C175.465 406.608 185.789 416.928 185.789 429.611V435.707C185.789 448.387 175.465 458.711 162.732 458.711H23.0572C10.3235 458.711 0 469.031 0 481.761V644.887C0 657.667 10.3235 667.988 23.0572 667.988H94.4913C107.175 667.988 117.501 678.309 117.501 690.991V864.293C117.501 877.073 127.825 887.343 140.559 887.343H251.323C261.254 887.343 270.104 880.904 273.201 871.468L361.5 599.77C363.664 593.183 362.73 586.106 359.089 580.305L309.926 502.94C303.485 492.912 305.795 479.594 315.335 472.369L313.563 473.646C317.594 470.598 322.559 468.927 327.575 468.927H385.34C393.993 468.927 401.859 473.743 405.843 481.412L453.238 573.517C456.925 580.595 464.055 585.313 472.019 585.904C480.033 586.543 487.802 582.856 492.471 576.37L564.496 475.81C568.823 469.764 575.805 466.175 583.18 466.175H638.586C646.402 466.175 653.73 462.243 657.956 455.609L709.577 375.199C715.083 366.599 724.522 352.737 731.158 344.974C739.32 335.537 752.003 333.473 752.003 340.255C752.003 352.935 762.327 363.259 775.061 363.259H775.898C786.715 363.259 796.104 355.69 798.414 345.172L813.309 276.658C814.832 269.776 819.356 263.979 825.7 260.88L924.813 212.467C932.73 208.632 937.742 200.574 937.742 191.823V23.3873C937.742 10.6573 927.418 0.33667 914.732 0.33667H508.25V0.339838Z" fill="url(#paint9_linear_1_14)"/>
</g>
<path opacity="0.3" d="M1295.5 401V312.5C1295.5 302.007 1304.01 293.5 1314.5 293.5H1366.5C1376.99 293.5 1385.5 284.993 1385.5 274.5V184C1385.5 173.507 1394.01 165 1404.5 165H1479.5" stroke="black" stroke-width="3" stroke-dasharray="4 4"/>
<path opacity="0.3" d="M1407 692.5V658.5C1407 648.007 1415.51 639.5 1426 639.5C1440.04 639.5 1451.85 639.5 1469 639.5M1469 639.5V581.5C1469 571.007 1477.51 562.5 1488 562.5H1563M1469 639.5L1407 577.5M1469 639.5L1486.5 657" stroke="black" stroke-width="3" stroke-dasharray="4 4"/>
<g filter="url(#filter0_d_1_14)">
<circle cx="1563.5" cy="561.5" r="6.5" fill="#5DE48C"/>
<circle cx="1563.5" cy="561.5" r="5.5" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter1_d_1_14)">
<circle cx="1406.5" cy="576.5" r="6.5" fill="#5DE48C"/>
<circle cx="1406.5" cy="576.5" r="5.5" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter2_d_1_14)">
<circle cx="1491.5" cy="660.5" r="6.5" fill="#5DE48C"/>
<circle cx="1491.5" cy="660.5" r="5.5" stroke="white" stroke-width="2"/>
</g>
<g filter="url(#filter3_d_1_14)">
<circle cx="1407.5" cy="693.5" r="6.5" fill="#5DE48C"/>
<circle cx="1407.5" cy="693.5" r="5.5" stroke="white" stroke-width="2"/>
</g>
<circle cx="1468.5" cy="638.5" r="6.5" fill="#0F2328" stroke="black" stroke-width="2"/>
<g filter="url(#filter4_d_1_14)">
<circle cx="1296.5" cy="338.5" r="6.5" fill="#5DE48C"/>
<circle cx="1296.5" cy="338.5" r="5.5" stroke="white" stroke-width="2"/>
</g>
<circle cx="1486.5" cy="164.5" r="6.5" fill="#0F2328" stroke="black" stroke-width="2"/>
<circle cx="1295.5" cy="408.5" r="6.5" fill="#0F2328" stroke="black" stroke-width="2"/>
<path opacity="0.3" d="M607.5 67L607.5 655.5L607.5 726.5C607.5 736.993 616.006 745.5 626.5 745.5L655.5 745.5C665.993 745.5 674.5 754.006 674.5 764.5L674.5 808" stroke="black" stroke-width="3" stroke-dasharray="4 4"/>
<g filter="url(#filter5_d_1_14)">
<circle cx="607.5" cy="94.5" r="6.5" transform="rotate(90 607.5 94.5)" fill="#5DE48C"/>
<circle cx="607.5" cy="94.5" r="5.5" transform="rotate(90 607.5 94.5)" stroke="white" stroke-width="2"/>
</g>
<circle cx="674.5" cy="807.5" r="6.5" transform="rotate(90 674.5 807.5)" fill="#0F2328" stroke="black" stroke-width="2"/>
<circle cx="607.5" cy="66.5" r="6.5" transform="rotate(90 607.5 66.5)" fill="#0F2328" stroke="black" stroke-width="2"/>
<path opacity="0.3" d="M200.5 613V441.5C200.5 431.559 208.559 423.5 218.5 423.5V423.5C228.441 423.5 236.5 415.441 236.5 405.5V396C236.5 385.507 245.007 377 255.5 377H304.5" stroke="black" stroke-width="3" stroke-dasharray="4 4"/>
<circle cx="312.5" cy="376.5" r="6.5" fill="#0F2328" stroke="black" stroke-width="2"/>
<g filter="url(#filter6_d_1_14)">
<circle cx="201.5" cy="483.5" r="6.5" fill="#5DE48C"/>
<circle cx="201.5" cy="483.5" r="5.5" stroke="white" stroke-width="2"/>
</g>
<circle cx="200.5" cy="620.5" r="6.5" fill="#0F2328" stroke="black" stroke-width="2"/>
<defs>
<filter id="filter0_d_1_14" x="1557" y="555" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<filter id="filter1_d_1_14" x="1400" y="570" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<filter id="filter2_d_1_14" x="1485" y="654" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<filter id="filter3_d_1_14" x="1401" y="687" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<filter id="filter4_d_1_14" x="1290" y="332" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<filter id="filter5_d_1_14" x="601" y="88" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<filter id="filter6_d_1_14" x="195" y="477" width="13" height="15" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/>
</filter>
<linearGradient id="paint0_linear_1_14" x1="696.867" y1="629.549" x2="696.867" y2="660.759" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint1_linear_1_14" x1="618.06" y1="598.782" x2="618.06" y2="675.16" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint2_linear_1_14" x1="727.801" y1="492.079" x2="727.801" y2="611.368" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint3_linear_1_14" x1="811.666" y1="407.784" x2="811.666" y2="474.825" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint4_linear_1_14" x1="730.396" y1="751.241" x2="730.396" y2="913.732" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint5_linear_1_14" x1="338.992" y1="802.753" x2="338.992" y2="882.619" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint6_linear_1_14" x1="1320.43" y1="0.339844" x2="1320.43" y2="917.664" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint7_linear_1_14" x1="103.39" y1="90.6741" x2="103.39" y2="210.256" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint8_linear_1_14" x1="30.1368" y1="162.43" x2="30.1368" y2="210.255" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
<linearGradient id="paint9_linear_1_14" x1="468.871" y1="0.33667" x2="468.871" y2="887.343" gradientUnits="userSpaceOnUse">
<stop stop-color="#1959FF"/>
<stop offset="1"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

View File

@@ -0,0 +1,4 @@
<svg viewBox="0 0 222 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M196.582 22.9795C196.582 26.6118 195.814 29.7198 194.279 32.3037C192.744 34.8502 190.648 36.7791 187.989 38.0898C185.368 39.3631 182.448 40 179.228 40C176.008 40 173.124 39.3631 170.578 38.0898C168.07 36.7791 166.085 34.8502 164.625 32.3037C163.202 29.7573 162.491 26.6492 162.491 22.9795V22.5312L173.442 21.5986V22.9795C173.442 25.1139 173.93 26.762 174.903 27.9229C175.914 29.0835 177.431 29.664 179.452 29.6641C181.474 29.6641 182.991 29.0838 184.002 27.9229C185.05 26.7245 185.574 25.0765 185.574 22.9795V20.5645L196.582 19.627V22.9795ZM20.4434 10.9014L26.8457 0.00390625H39.3701L26.6777 19.9453L31.6494 27.168L19.6064 28.4375L19.5811 28.4795L19.5449 28.4277L12.9736 39.6064H0.449219L13.3105 19.3281L0 0.00390625H12.9736L20.4434 10.9014ZM40.2129 39.6064H27.2393L23.7236 34.499L35.9688 33.4414L40.2129 39.6064ZM52.8643 39.6064H41.2949L43.7871 32.7656L55.458 31.7578L52.8643 39.6064ZM82.7988 39.6064H71.1738L68.2148 30.6553L79.2041 29.7061L82.7988 39.6064ZM95.71 39.6064H84.7021V29.2314L95.71 28.2803V39.6064ZM95.71 20.374L109.133 18.9795V0.00390625H120.142V39.6064H109.133V27.1367L95.7178 28.2773V20.416L84.7021 21.5762V0.00390625H95.71V20.374ZM133.624 39.6035H122.055L127.171 25.5625L138.591 24.5762L133.624 39.6035ZM163.56 39.6035H151.934L146.733 23.873L146.777 23.8701L143.93 15.3359L143.912 15.3369L142.779 11.9092L141.563 15.585L130.378 16.7637L136.488 0H149.182L163.56 39.6035ZM76.5645 22.4336L65.8691 23.5615L62.0186 11.9121L57.8896 24.4023L46.3936 25.6143L55.7285 0.00390625H68.4219L76.5645 22.4336ZM173.442 12.249L162.491 13.3936V0.00390625H173.442V12.249ZM196.582 9.8291L185.574 10.9805V0.00390625H196.582V9.8291Z" fill="black" />
<path d="M220.158 11.4972C220.966 11.8662 221.06 12.946 220.327 13.441L208.951 21.1231C208.218 21.618 207.208 21.1569 207.133 20.293L205.97 6.88506C205.895 6.02116 206.811 5.40245 207.619 5.77138L220.158 11.4972Z" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -0,0 +1,10 @@
---
import 'vanilla-cookieconsent/dist/cookieconsent.css';
---
<script>
import { run } from 'vanilla-cookieconsent';
import { config } from '../CookieConsentConfig';
run(config);
document.body.classList.add('cc--darkmode');
</script>

View File

@@ -0,0 +1,12 @@
---
---
<script is:inline>
document.documentElement.dataset.theme = 'light';
</script>
<style is:global>
.social-icons::after {
display: none;
}
</style>

View File

@@ -0,0 +1,107 @@
---
import { ChevronDownIcon, Bars3Icon, XMarkIcon } from '@heroicons/react/20/solid'
---
<starlight-menu-button class="print:hidden">
<button
aria-expanded="false"
aria-label={Astro.locals.t('menuButton.accessibleLabel')}
aria-controls="starlight__sidebar"
class="sl-flex md:sl-hidden"
>
<Bars3Icon name="open" className="open-menu" />
<XMarkIcon name="close" className="close-menu" />
</button>
</starlight-menu-button>
<script>
class StarlightMenuButton extends HTMLElement {
btn = this.querySelector('button')!;
constructor() {
super();
// Toggle `aria-expanded` state when a user clicks the button.
this.btn.addEventListener('click', () => this.toggleExpanded());
// Close the menu when a user presses the escape key.
const parentNav = this.closest('nav');
if (parentNav) {
parentNav.addEventListener('keyup', (e) => this.closeOnEscape(e));
}
}
setExpanded(expanded: boolean) {
this.setAttribute('aria-expanded', String(expanded));
document.body.toggleAttribute('data-mobile-menu-expanded', expanded);
}
toggleExpanded() {
this.setExpanded(this.getAttribute('aria-expanded') !== 'true');
}
closeOnEscape(e: KeyboardEvent) {
if (e.code === 'Escape') {
this.setExpanded(false);
this.btn.focus();
}
}
}
customElements.define('starlight-menu-button', StarlightMenuButton);
</script>
<style>
@layer starlight.core {
button {
position: fixed;
bottom: var(--sl-nav-pad-y);
inset-inline-end: var(--sl-nav-pad-x);
z-index: var(--sl-z-index-navbar);
border: 0;
border-radius: 50%;
width: var(--sl-menu-button-size);
height: var(--sl-menu-button-size);
padding: 0.5rem;
background-color: var(--sl-color-white);
color: var(--sl-color-black);
box-shadow: var(--sl-shadow-md);
cursor: pointer;
}
[aria-expanded='true'] button {
background-color: var(--sl-color-gray-2);
box-shadow: none;
}
[aria-expanded='true'] button .open-menu {
display: none;
}
:not([aria-expanded='true']) button .close-menu {
display: none;
}
:global button {
background-color: var(--sl-color-black);
color: var(--sl-color-white);
}
:global [aria-expanded='true'] button {
background-color: var(--sl-color-gray-5);
}
}
</style>
<style is:global>
@layer starlight.core {
[data-mobile-menu-expanded] {
overflow: hidden;
}
@media (min-width: 50rem) {
[data-mobile-menu-expanded] {
overflow: auto;
}
}
}
</style>

View File

@@ -0,0 +1,55 @@
---
import TableOfContents from '@astrojs/starlight/components/TableOfContents.astro';
---
{
Astro.locals.starlightRoute.toc && (
<>
<div class="right-sidebar-panel sl-hidden lg:sl-block">
<div class="sl-container">
<TableOfContents />
</div>
</div>
</>
)
}
<style>
@layer starlight.core {
.right-sidebar-panel {
padding: 1rem var(--sl-sidebar-pad-x);
}
.sl-container {
width: calc(var(--sl-sidebar-width) - 2 * var(--sl-sidebar-pad-x));
}
.right-sidebar-panel :global(h2) {
color: var(--sl-color-white);
font-size: var(--sl-text-h5);
font-weight: 600;
line-height: var(--sl-line-height-headings);
margin-bottom: 0.5rem;
}
.right-sidebar-panel :global(:where(a)) {
display: block;
font-size: var(--sl-text-xs);
text-decoration: none;
color: var(--sl-color-gray-3);
overflow-wrap: anywhere;
}
.right-sidebar-panel :global(:where(a):hover) {
color: var(--sl-color-white);
}
@media (min-width: 72rem) {
.sl-container {
max-width: calc(
(
(
100vw - var(--sl-sidebar-width) - 2 * var(--sl-content-pad-x) - 2 *
var(--sl-sidebar-pad-x)
) * 0.25 /* MAGIC NUMBER 🥲 */
)
);
}
}
}
</style>

View File

@@ -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;
---
<SidebarPersister>
<SidebarSublist sublist={sidebar} />
</SidebarPersister>

View File

@@ -0,0 +1,48 @@
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<div class="col-span-3"><slot /></div>
{
Astro.locals.starlightRoute.toc && (
<aside class="right-sidebar-container col-span-1 print:hidden">
<div class="right-sidebar">
<slot name="right-sidebar" />
</div>
</aside>
)
}
</div>
<style>
@layer starlight.core {
@media (min-width: 72rem) {
.right-sidebar-container {
order: 2;
position: relative;
width: calc(
var(--sl-sidebar-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2
);
}
.right-sidebar {
position: fixed;
border-inline-start: 1px solid var(--sl-color-hairline);
width: 100%;
height: 100vh;
overflow-y: auto;
scrollbar-width: none;
}
.main-pane {
width: 100%;
}
:global([data-has-sidebar][data-has-toc]) .main-pane {
--sl-content-margin-inline: auto 0;
order: 1;
width: calc(
var(--sl-content-width) + (100% - var(--sl-content-width) - var(--sl-sidebar-width)) / 2
);
}
}
}
</style>

View File

@@ -0,0 +1,7 @@
---
const { class: className, ...rest } = Astro.props
import { Image } from 'astro:assets';
---
<a href={Astro.props.href} target="_blank" class:list={["flex hover:border-xahau-green hover:bg-gray-50 !text-black !no-underline items-center justify-center p-4 text-center bg-white font-bold border-black border-2",className]}>
{Astro.props.imageSrc ? <Image src={Astro.props.imageSrc} alt={Astro.props.title} class="w-auto h-auto max-h-2/5" /> : Astro.props.title}
</a>

View File

@@ -0,0 +1,38 @@
---
import logo from '../assets/xahau-logo.svg'
import { Image } from 'astro:assets';
---
<footer class="bg-white text-base font-regular text-black **:text-black **:no-underline">
<div class="flex-none container mx-auto py-12 max-w-7xl p-6 grid grid-cols-1 md:grid-cols-10 gap-4">
<div class="col-span-1 md:col-span-3 flex flex-col gap-3">
<a href="/"><Image src={logo} class="w-1/2" alt="Xahau" /><a>
<p>This website is open source and open for contributions <a href="https://github.com/Xahau/xahau-web" target="_blank">on GitHub</a></p>
</div>
<div class="col-span-1 md:col-span-2 md:col-start-5 flex flex-col gap-3">
<p><strong>Xahau</strong></p>
<a href="/about">About</a>
<a href="/features">Features</a>
<a href="/ecosystem">Ecosystem</a>
<a href="/roadmap">Roadmap</a>
<a href="/docs/compliance/responsible-disclosure">Break Xahau</a>
<a href="/docs/resources/media-kit">Media kit</a>
<a href="/privacy-policy">Privacy Policy</a>
</div>
<div class="col-span-1 md:col-span-2 flex flex-col gap-3">
<p><strong>Documentation</strong></p>
<a href="/docs">Get started</a>
<a href="/docs/protocol-reference/transactions">Protocol Reference</a>
<a href="/docs/hooks">Hooks</a>
<a href="/docs/data-apis">Data APIs</a>
<a href="/docs/infrastructure/node-requirements">Infrastructure</a>
<a href="/docs/resources/whitepaper">Whitepaper</a>
</div>
<div class="col-span-1 md:col-span-2 flex flex-col gap-3">
<p><strong>Connect</strong></p>
<a href="https://x.com/XahauNetwork" target="_blank">X</a>
<a href="https://github.com/Xahau" target="_blank">GitHub</a>
<a href="https://discord.com/invite/UzU58haAn4" target="_blank">Community Discord</a>
</div>
</div>
</footer>

163
src/components/Header.jsx Normal file
View File

@@ -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 (
<header className="header bg-xahau-background z-20">
<nav aria-label="Global" className="mx-auto flex max-w-7xl items-center justify-between p-6">
<div className="flex lg:flex-1">
<a href="/" className="-m-1.5 p-1.5">
<span className="sr-only">Xahau</span>
<img src={logo.src} width="222" height="40" />
</a>
</div>
<div className="flex lg:hidden">
<button type="button" onClick={() => setMobileMenuOpen(true)} className="border-none bg-transparent -m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700">
<span className="sr-only">Open main menu</span>
<Bars3Icon aria-hidden="true" className="size-6" />
</button>
</div>
<PopoverGroup className="hidden lg:flex lg:gap-x-12">
<a href="/about" className={`selected:no-underline no-underline text-base text-black ${props.url.pathname.slice(1).split('/')[0] == 'about' ? 'font-bold' : 'font-regular'}`}>About</a>
<a href="/features" className={`selected:no-underline no-underline text-base text-black ${props.url.pathname.slice(1).split('/')[0] == 'features' ? 'font-bold' : 'font-regular'}`}>Features</a>
<a href="/ecosystem" className={`selected:no-underline no-underline text-base text-black ${props.url.pathname.slice(1).split('/')[0] == 'ecosystem' ? 'font-bold' : 'font-regular'}`}>Ecosystem</a>
<a href="/roadmap" className={`selected:no-underline no-underline text-base text-black ${props.url.pathname.slice(1).split('/')[0] == 'roadmap' ? 'font-bold' : 'font-regular'}`}>Roadmap</a>
<Popover className="relative">
<PopoverButton className={`selected:no-underline no-underline p-0 border-none text-base text-black flex items-center gap-x-1 bg-transparent ${props.url.pathname.slice(1).split('/')[0] == 'docs' ? 'font-bold' : 'font-regular'}`}>
Documentation
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-black" />
</PopoverButton>
<PopoverPanel transition className="absolute left-1/2 z-10 mt-3 w-screen max-w-max -translate-x-1/2 overflow-hidden bg-xahau-gray shadow-lg ring-1 ring-gray-900/5 transition data-closed:translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in">
<div className="p-4">
{docs.map((item) => (
<div key={item.name} className="group relative flex items-center gap-x-6 p-2 text-sm/6">
<a href={item.href} className="no-underline block font-regular text-white">{item.name}</a>
</div>
))}
</div>
</PopoverPanel>
</Popover>
<Popover className="relative">
<PopoverButton className="flex p-0 border-none items-center gap-x-1 text-base font-regular text-black bg-transparent">
Connect
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none text-black" />
</PopoverButton>
<PopoverPanel transition className="absolute left-1/2 z-10 mt-3 w-screen max-w-max -translate-x-1/2 overflow-hidden bg-xahau-gray shadow-lg ring-1 ring-gray-900/5 transition data-closed:translate-y-1 data-closed:opacity-0 data-enter:duration-200 data-enter:ease-out data-leave:duration-150 data-leave:ease-in">
<div className="p-4">
{socials.map((item) => (
<div key={item.name} className="group relative flex items-center gap-x-6 p-2 text-sm/6">
<a href={item.href} target="_blank" className="no-underline block font-regular text-white">{item.name}</a>
</div>
))}
</div>
</PopoverPanel>
</Popover>
<a href="https://explorer.xahau.network/" target="_blank" className="selected:no-underline no-underline text-base text-black font-regular">Explorer</a>
</PopoverGroup>
</nav>
<Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden">
<div className="fixed inset-0 z-50" />
<DialogPanel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white p-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
<div className="flex items-center justify-between">
<a href="#" className="-m-1.5 p-1.5">
<span className="sr-only">Your Company</span>
<svg width="222" height="40" viewBox="0 0 222 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M196.582 22.9795C196.582 26.6118 195.814 29.7198 194.279 32.3037C192.744 34.8502 190.648 36.7791 187.989 38.0898C185.368 39.3631 182.448 40 179.228 40C176.008 40 173.124 39.3631 170.578 38.0898C168.07 36.7791 166.085 34.8502 164.625 32.3037C163.202 29.7573 162.491 26.6492 162.491 22.9795V22.5312L173.442 21.5986V22.9795C173.442 25.1139 173.93 26.762 174.903 27.9229C175.914 29.0835 177.431 29.664 179.452 29.6641C181.474 29.6641 182.991 29.0838 184.002 27.9229C185.05 26.7245 185.574 25.0765 185.574 22.9795V20.5645L196.582 19.627V22.9795ZM20.4434 10.9014L26.8457 0.00390625H39.3701L26.6777 19.9453L31.6494 27.168L19.6064 28.4375L19.5811 28.4795L19.5449 28.4277L12.9736 39.6064H0.449219L13.3105 19.3281L0 0.00390625H12.9736L20.4434 10.9014ZM40.2129 39.6064H27.2393L23.7236 34.499L35.9688 33.4414L40.2129 39.6064ZM52.8643 39.6064H41.2949L43.7871 32.7656L55.458 31.7578L52.8643 39.6064ZM82.7988 39.6064H71.1738L68.2148 30.6553L79.2041 29.7061L82.7988 39.6064ZM95.71 39.6064H84.7021V29.2314L95.71 28.2803V39.6064ZM95.71 20.374L109.133 18.9795V0.00390625H120.142V39.6064H109.133V27.1367L95.7178 28.2773V20.416L84.7021 21.5762V0.00390625H95.71V20.374ZM133.624 39.6035H122.055L127.171 25.5625L138.591 24.5762L133.624 39.6035ZM163.56 39.6035H151.934L146.733 23.873L146.777 23.8701L143.93 15.3359L143.912 15.3369L142.779 11.9092L141.563 15.585L130.378 16.7637L136.488 0H149.182L163.56 39.6035ZM76.5645 22.4336L65.8691 23.5615L62.0186 11.9121L57.8896 24.4023L46.3936 25.6143L55.7285 0.00390625H68.4219L76.5645 22.4336ZM173.442 12.249L162.491 13.3936V0.00390625H173.442V12.249ZM196.582 9.8291L185.574 10.9805V0.00390625H196.582V9.8291Z" fill="black" />
<path d="M220.158 11.4972C220.966 11.8662 221.06 12.946 220.327 13.441L208.951 21.1231C208.218 21.618 207.208 21.1569 207.133 20.293L205.97 6.88506C205.895 6.02116 206.811 5.40245 207.619 5.77138L220.158 11.4972Z" fill="black" />
</svg>
</a>
<button
type="button"
onClick={() => setMobileMenuOpen(false)}
className="border-none bg-transparent -m-2.5 rounded-md p-2.5 text-gray-700"
>
<span className="sr-only">Close menu</span>
<XMarkIcon aria-hidden="true" className="size-6" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-gray-500/10">
<div className="space-y-2 py-6">
<a href="/about" className={`selected:no-underline no-underline -mx-3 block rounded-lg px-3 py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black ${props.url.pathname.slice(1).split('/')[0] == 'about' ? 'font-bold' : 'font-regular'}`}>About</a>
<a href="/features" className={`selected:no-underline no-underline -mx-3 block rounded-lg px-3 py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black ${props.url.pathname.slice(1).split('/')[0] == 'features' ? 'font-bold' : 'font-regular'}`}>Features</a>
<a href="/resources/whitepaper" className={`selected:no-underline no-underline -mx-3 block rounded-lg px-3 py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black ${props.url.pathname.slice(1).split('/')[0] == 'whitepaper' ? 'font-bold' : 'font-regular'}`}>Whitepaper</a>
<a href="/ecosystem" className={`selected:no-underline no-underline -mx-3 block rounded-lg px-3 py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black ${props.url.pathname.slice(1).split('/')[0] == 'ecosystem' ? 'font-bold' : 'font-regular'}`}>Ecosystem</a>
<a href="/roadmap" className={`selected:no-underline no-underline -mx-3 block rounded-lg px-3 py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black ${props.url.pathname.slice(1).split('/')[0] == 'roadmap' ? 'font-bold' : 'font-regular'}`}>Roadmap</a>
<Disclosure as="div" className="-mx-3">
<DisclosureButton className={`selected:no-underline no-underline border-none block rounded-lg py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black bg-transparent group flex w-full items-center justify-between pr-3.5 pl-3 hover:bg-gray-50 ${props.url.pathname.slice(1).split('/')[0] == 'docs' ? 'font-bold' : 'font-regular'}`}>
Documentation
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-2">
{[...docs].map((item) => (
<DisclosureButton
key={item.name}
as="a"
href={item.href}
className="no-underline block rounded-lg py-2 pr-3 pl-6 text-sm/7 font-regular text-black hover:bg-gray-50"
>
{item.name}
</DisclosureButton>
))}
</DisclosurePanel>
</Disclosure>
<Disclosure as="div" className="-mx-3">
<DisclosureButton className="border-none bg-transparent group flex w-full items-center justify-between rounded-lg py-2 pr-3.5 pl-3 text-base/7 font-regular text-black hover:bg-gray-50">
Connect
<ChevronDownIcon aria-hidden="true" className="size-5 flex-none group-data-open:rotate-180" />
</DisclosureButton>
<DisclosurePanel className="mt-2 space-y-2">
{[...socials].map((item) => (
<DisclosureButton
key={item.name}
as="a"
href={item.href}
target="_blank"
className="no-underline block rounded-lg py-2 pr-3 pl-6 text-sm/7 font-regular text-black hover:bg-gray-50"
>
{item.name}
</DisclosureButton>
))}
</DisclosurePanel>
</Disclosure>
<a href="https://explorer.xahau.network/" target="_blank" className="selected:no-underline no-underline -mx-3 block rounded-lg px-3 py-2 text-base/7 text-base/7 hover:bg-gray-50 text-black font-regular">Explorer</a>
</div>
</div>
</div>
</DialogPanel>
</Dialog>
</header>
)
}

View File

@@ -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";
}
---
<div class:list={["flex",className]}>
<div class="flex-none container mx-auto py-12 text-left max-w-7xl p-6">
{Astro.props.align ? (
<div class="grid grid-cols-1 md:grid-cols-5" >
{Astro.props.align === "right" && Astro.props.gem && (
<div class="relative overflow-visible invisible md:visible">
<Image loading={Astro.props.loading} src={gem} alt="Gem" class={`overflow-visible ${gemSize} absolute inset-0 m-auto -left-60 object-cover`} />
</div>
)}
<div class={
Astro.props.align === "right"
? "col-span-1 md:col-span-3 md:col-start-3"
: Astro.props.align === "left"
? "col-span-1 md:col-span-3 md:col-start-1"
: "col-span-1 md:col-span-3 md:col-start-2"
}>
<slot />
</div>
{Astro.props.align === "left" && Astro.props.gem && (
<div class="relative overflow-visible invisible md:visible">
<Image loading={Astro.props.loading} src={gem} alt="Gem" class={`overflow-visible ${gemSize} absolute inset-0 m-auto -right-150 object-cover`} />
</div>
)}
</div>
) : (
<slot />
)}
</div>
</div>

7
src/content.config.ts Normal file
View File

@@ -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() }),
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -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 Centres Responsible Disclosure Guidelines and an [example by Floor Terra](https://responsibledisclosure.nl/).

View File

@@ -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.&#x20;
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.&#x20;
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.
<Aside type="note">
The full security audit can be found [**here**](https://xrpl-labs.com/static/misc/Security%20Assessment%20of%20the%20XRP%20Labs%20Hooks%20Amendment%20v1.0.pdf).&#x20;
</Aside>
To a brighter, more innovative future with Xahau!

View File

@@ -0,0 +1,5 @@
---
title: "Data APIs"
---
The primary Data API is located at https://data.xahau.network/

View File

@@ -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.

View File

@@ -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": "<rAddr...>",
"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": "<rAddr...>",
"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": "&#x3C;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:
<table><thead><tr><th width="240">Field</th><th width="95.33333333333331">Type</th><th>Explanation</th></tr></thead><tbody><tr><td><code>sfRewardAccumulator</code></td><td>UINT64</td><td>The area under of the balance-time graph for your account since last ClaimReward transaction.</td></tr><tr><td><code>sfRewardLgrFirst</code></td><td>UINT32</td><td>The ledger number of the last ClaimReward transaction.</td></tr><tr><td><code>sfRewardLgrLast</code></td><td>UINT32</td><td>The ledger sequence number of the last transaction in or out of your account.</td></tr><tr><td><code>sfRewardTime</code></td><td>UINT32</td><td>The ledger time the last reward was claimed.</td></tr></tbody></table>

View File

@@ -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';
<Aside type="caution">
Since the ZeroB2M amendment has been voted in at Xahau, Burn 2 Mint (B2M) is no longer available to mint new assets. B2M is still available, but just for **key synchonisation** or to activate an account based (for which the information & procedures below are still relevant)
[https://xahscan.com/amendment/7CA0426E7F411D39BB014E57CD9E08F61DE1750F0D41FCD428D9FB80BB7596B0](https://xahscan.com/amendment/7CA0426E7F411D39BB014E57CD9E08F61DE1750F0D41FCD428D9FB80BB7596B0)
</Aside>
## Burn2Mint Technical Manual (Xahau Testnet)
<Aside type="caution">
**This process is deliberately non-trivial and not designed for end users.** Mistakes result in a burn not being able to turn into a mint.
This is a warning that will appear on the production version of this document. You may disregard it because you are burning free testnet XRP in this instance.
</Aside>
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 its 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**
<Tabs>
<TabItem label="xPOP Collector & Server (easier)">
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)
</TabItem>
<TabItem label='or: dedicated "Burning Node"'>
**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
```
</TabItem>
</Tabs>
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.
<Aside type="caution">
Tickets _**are not accepted**_ in **any** Burn Transactions and would lead to a Burn Transaction being invalid for minting. To protect against spam, transactions must be validated with a real, natural sequence number.
</Aside>
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 chains 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 Nodes `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": "<same as it was in the Burn Transaction>",
"TransactionType": "Import",
"Blob": "<hex encoded (upper case) XPOP>",
"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": "<HEX ENCODED IMPORT TXN>"
}
```
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 <hex here>`
### 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 Transactions 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.

View File

@@ -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.
<table><thead><tr><th width="172">Language</th><th width="172">Library Name</th><th>Get Started</th><th>Protocol</th><th>Source Code</th></tr></thead><tbody><tr><td><strong>Python</strong></td><td><code>xahau-py</code></td><td><a href="https://github.com/Xahau/xahau-py">Get Started</a></td><td>XAH / XRP</td><td><a href="https://github.com/Xahau/xahau-py">Repo</a></td></tr><tr><td><strong>JavaScript</strong> / <strong>TypeScript</strong></td><td><code>xahau.js</code></td><td><a href="https://github.com/Xahau/xahau.js">Get Started</a></td><td>XAH / XRP</td><td><a href="https://github.com/Xahau/xahau.js">Repo</a></td></tr><tr><td><strong>JavaScript</strong> / <strong>TypeScript</strong></td><td><a href="https://www.npmjs.com/package/xrpl-accountlib"><code>xrpl-accountlib</code></a></td><td><a href="https://www.npmjs.com/package/xrpl-accountlib">Get started</a><br /><a href="https://github.com/WietseWind/xrpl-accountlib/blob/master/samples/prefill-sign-and-submit.mjs">Sample</a></td><td>XAH / XRP</td><td><a href="https://github.com/WietseWind/xrpl-accountlib">Repo</a></td></tr></tbody></table>
**Tip:** To add a client library not listed here, please suggest changes to this page!

View File

@@ -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/) |

View File

@@ -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

View File

@@ -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/)

View File

@@ -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: <member's account>,
TransactionType: Invoke,
NetworkID: 21337,
Destination: <table's account>,
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.&#x20;
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.&#x20;
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.

View File

@@ -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 servers 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. |

View File

@@ -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 clients 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.

View File

@@ -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.&#x20;
### 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 accounts 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. |

View File

@@ -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:
<table><thead><tr><th>Field</th><th width="220">Type</th><th>Description</th></tr></thead><tbody><tr><td>command</td><td>String</td><td>The name of the API method</td></tr><tr><td>id</td><td>(Multiple)</td><td><em>(Optional)</em> Unique identifier for the request. </td></tr><tr><td>api_version</td><td>Number</td><td><em>(Optional)</em> Specifies the API version.</td></tr></tbody></table>
### 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
<table><thead><tr><th>Field</th><th width="220">Type</th><th>Description</th></tr></thead><tbody><tr><td>method</td><td>String</td><td>The name of the API method</td></tr><tr><td>params</td><td>Array</td><td><em>(Optional)</em> A one-item array containing a JSON object with the parameters of the method.</td></tr></tbody></table>
### Comandline
```
xahaud account_info rhBDFMmr3jSjgsWMqBAYaATLy3PuXy395y validated strict
```
### Commandline Request Structure
<table><thead><tr><th>Field</th><th width="220">Description</th></tr></thead><tbody><tr><td>xahaud</td><td>Start calling the service xahaud</td></tr><tr><td>method</td><td>The name of the API method</td></tr><tr><td>params</td><td>(Optional)</td></tr></tbody></table>

View File

@@ -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. |

View File

@@ -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.

View File

@@ -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.
<LinkCard title="ClaimReward" href="/docs/protocol-reference/transactions/transaction-types/claimreward" />
#### 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.
<LinkCard title="GenesisMint - (Emitted Txn)" href="/docs/protocol-reference/transactions/transaction-types/genesismint-emitted-txn" />

View File

@@ -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.
<LinkCard title="CheckCreate" href="/docs/protocol-reference/transactions/transaction-types/checkcreate" />
#### 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.
<LinkCard title="CheckCancel" href="/docs/protocol-reference/transactions/transaction-types/checkcancel" />
#### 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.
<LinkCard title="CheckCash" href="/docs/protocol-reference/transactions/transaction-types/checkcash" />

View File

@@ -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.
<LinkCard title="EscrowCreate" href="/docs/protocol-reference/transactions/transaction-types/escrowcreate" />
#### 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.
<LinkCard title="EscrowFinish" href="/docs/protocol-reference/transactions/transaction-types/escrowfinish" />
#### 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.
<LinkCard title="EscrowCancel" href="/docs/protocol-reference/transactions/transaction-types/escrowcancel" />

View File

@@ -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.
<LinkCard title="SetHook" href="/docs/protocol-reference/transactions/transaction-types/sethook" />
**Invoke**
This transaction type is used to call or invoke the functionality of a hook.
<LinkCard title="Invoke" href="/docs/protocol-reference/transactions/transaction-types/invoke" />

View File

@@ -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.
<LinkCard title="OfferCreate" href="/docs/protocol-reference/transactions/transaction-types/offercreate" />
#### 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.
<LinkCard title="OfferCancel" href="/docs/protocol-reference/transactions/transaction-types/offercancel" />

View File

@@ -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.
<LinkCard title="DepositPreauth" href="/docs/protocol-reference/transactions/transaction-types/depositpreauth" />
**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.
<LinkCard title="TrustSet" href="/docs/protocol-reference/transactions/transaction-types/trustset" />
**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.
<LinkCard title="Payment" href="/docs/protocol-reference/transactions/transaction-types/payment" />
**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.
<LinkCard title="PaymentChannelCreate" href="/docs/protocol-reference/transactions/transaction-types/paymentchannelcreate" />
**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.
<LinkCard title="PaymentChannelFund" href="/docs/protocol-reference/transactions/transaction-types/paymentchannelfund" />
**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.
<LinkCard title="PaymentChannelClaim" href="/docs/protocol-reference/transactions/transaction-types/paymentchannelclaim" />

View File

@@ -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.
<LinkCard title="URITokenMint" href="/docs/protocol-reference/transactions/transaction-types/uritokenmint" />
#### 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.
<LinkCard title="URITokenBurn" href="/docs/protocol-reference/transactions/transaction-types/uritokenburn" />
#### 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.
<LinkCard title="URITokenBuy" href="/docs/protocol-reference/transactions/transaction-types/uritokenbuy" />
<LinkCard title="URITokenCreateSellOffer" href="/docs/protocol-reference/transactions/transaction-types/uritokencreateselloffer" />
<LinkCard title="URITokenCancelSellOffer" href="/docs/protocol-reference/transactions/transaction-types/uritokencancelselloffer" />

View File

@@ -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)

View File

@@ -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. <mark style="color:blue;">**The libraries below implement this and will handle this for you.**</mark>
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`. <mark style="color:blue;">**The libraries below implement this and will handle this for you.**</mark>
## 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)
```

View File

@@ -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":"<hex blob>"}
```
For HTTP POST RPC submit it as follows:
```json
{"method":"fee", "params": [{"tx_blob":"<hex 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.

View File

@@ -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.
<Aside type="caution">
All merges into the dev branch must be squashed
</Aside>
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.
<Aside type="caution">
All merges into the release branch must be done with \`git merge --ff-only candidate\`
</Aside>
### 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.

View File

@@ -0,0 +1,47 @@
---
title: Chaining
description: Chain multiple hooks together to do more useful tasks
---
import { Aside } from '@astrojs/starlight/components';
<Aside type="tip" title="Hook Design Philosophy">
_Each Hook should do one thing, and do it really well._
</Aside>
### 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.
<figure>
![Example: Execution flow for a transaction passing through two Hook Chains](../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_0OucxySTRinbe13SITJT_5561b32-sethook-Page-3.png)
<figcaption>*Example: Execution flow for a transaction passing through two Hook Chains*</figcaption>
</figure>
### 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.

View File

@@ -0,0 +1,27 @@
---
title: Collect Call
---
import { Card, Aside } from '@astrojs/starlight/components';
<Card title="Hook Design Philosophy">
_Every party affected by a transaction should have the opportunity to have their hooks executed._
</Card>
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 |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <p><strong>Again As Weak</strong><br />- Happens when a Strongly Executed Hook calls <a href="../technical/hooks-functions/hook-context/hook_again.md">hook_again</a></p> | Free (already paid by the Strong Execution). |
| <p><strong>Callback</strong><br />- Happens when an emitted transaction either makes it into a ledger or is flagged as being impossible to ever make it into a ledger.</p> | Free (already paid during Emission). |
| <p><strong>Weak Transactional Stakeholder</strong><br />- Happens if a transaction in some way mildly affects your account.</p> | 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. |
<Aside type="caution">
This is an advanced feature most Hook Developers will probably not use.
</Aside>

View File

@@ -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 <stdint.h>
#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;
}
```
<Aside type="tip">
For educational purposes the above example deliberately does not include `hookapi.h` (which developers would typically use.)
</Aside>
### 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.
<Aside type="tip">
Webassembly is a platform-independent general computation `bytecode` language. It has a one-to-one mapping with a human readable equivalent. These are used interchangeably.
</Aside>
### 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.
<Aside type="caution">
Don't forget to use the [Hook Cleaner Utility](https://github.com/XRPLF/hook-cleaner-c) or your Hooks will be rejected.
</Aside>

View File

@@ -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.
<Aside type="tip">
At time of writing there is no interactive Hook Debugger. You must use the trace functions.
</Aside>
### 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.
<Aside type="tip" title="Use testnet">
The [Xahau Testnet](https://xahau-test.net/) is the perfect place to test your Hooks.
</Aside>
### 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 |
<Aside type="tip">
`Xahaud` produces a lot of output. It is therefore generally advisible to grep logs for the account/s you are interested in.
For example use: `tail -f log | grep HookTrace | grep <account>`
</Aside>

View File

@@ -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 | <p>If the Originating Transaction was itself an emitted transaction then one more than the <code>sfEmitGeneration</code> of that transaction.<br /><br />If the Originating Transaction was not an emitted transaction then <code>1</code>.<br /><br />This should be populated using <a href="../technical/hooks-functions/emitted-transaction/etxn_generation.md">etxn_generation</a>.</p> | This field keeps track of a chain of emitted transactions that in turn cause other transactions to be emitted. |
| sfEmitBurden | <p>If the Originating Transaction was itself an emitted transaction then the <code>burden</code> of the Originating Transaction multiplied by the maximum number of transactions the Hook has declared it will emit using <a href="../technical/hooks-functions/emitted-transaction/etxn_reserve.md">etxn_reserve</a>.<br /><br />If the Originating Transaction was not an emitted transaction then <code>1</code>.<br /><br />This should be populated using <a href="../technical/hooks-functions/emitted-transaction/etxn_burden.md">etxn_burden</a>.</p> | 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. |
<Aside type="tip" title="Check the examples">
The [Example Hooks](https://github.com/XRPL-Labs/xrpld-hooks/tree/hooks-ssvm/hook-api-examples), in particular Peggy, Carbon and Doubler, demonstrate how to emit both simple and more complicated transactions.
</Aside>

View File

@@ -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 | <p>Hooks can end in three ways: <code>accept</code>, <code>rollback</code> and <code>error</code>.<br />This is <em>not</em> the same as sfHookReturnCode!</p> |
| 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. |

View File

@@ -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.)
<Aside type="tip">
Use the XFL-tool <a href="https://richardah.github.io/xfl-tools/" target="_blank" rel="noopener">here</a> to compose and decompose XFLs in your browser!
</Aside>
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 |
<Aside type="caution">
You should never do any direct math or comparison on the _enclosing number_. This will almost always result in incorrect computations.
The _sole exception_ is checking for canonical zero.
</Aside>
### 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);
```
<Aside type="tip">
If a float API returns a negative value and you do not check for negatives, then passing that negative value into another float API will also produce a negative value. In this way, errors are propagated much like `NaN` (not a number) is propagated in other languages.
If you ever end up with a negative enclosing number, an error occurred somewhere in your floating point calculations.
</Aside>

View File

@@ -0,0 +1,91 @@
---
title: Grants
description: Hook Grants
---
import { Aside } from '@astrojs/starlight/components';
<Aside type="caution">
Most Hook Developers will rarely need to use HookGrants, and should exercise extreme caution when granting state mutation permission to foreign Hooks and accounts.
While a HookGrant cannot be used to directly steal funds, intentional external modification of a Hook's State may lead a Hook to behave in an unintended way, which in some cases could lead to a theft.
If you think you need to use a Grant, please re-check your design first to ensure you actually need to use one before continuing.
</Aside>
### 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.
<Aside type="caution">
Unlike [Parameters](parameters.md), the `HookGrants` array is always set exactly as specified in the [SetHook Transaction]
(sethook-transaction.md).
</Aside>
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`.
<Aside type="tip">
Grants only apply to external Hooks and never limit the operation of Hooks with respect to the Hook State on the account they are installed on.
</Aside>
### 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).

View File

@@ -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":"<hex blob>"}
```
For HTTP POST RPC submit it as follows:
```json
{"method":"fee", "params": [{"tx_blob":"<hex 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`.

View File

@@ -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
<LinkCard title="HookOn Calculator" href="https://richardah.github.io/xrpl-hookon-calculator/" />

View File

@@ -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)

View File

@@ -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.
<Aside type="note">
Please note: you're reading the **technical documentation** of Hooks. This documentation is highly technical & assumes prior knowledge of programming and the Xahau Ledger. If you are looking for examples on what Hooks are, will bring to the Xahau Ledger and what they could do, please [check this page](example-usage).
</Aside>
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.
<figure>
![Hooks high level concept](../../../assets/spaces_m6f29os4wP16vCS4lHNh_uploads_sEBiInWuRskTqxB29Xgd_7359187-Hooks_High_Level2x_1.png)
<figcaption>*Hooks high level concept*</figcaption>
</figure>
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)

View File

@@ -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.
<Aside type="tip">
Existing developers migrating from other smart contract platforms may find guards to be annoying at first, but once you get used to them they are no harder to use than a normal for-loop.
</Aside>
### 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).
<Aside type="caution">
Guards must be set using numerical literals. You cannot use a variable or runtime value in a Guard.
</Aside>
### 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.
<Aside type="tip" title="The Guard Rule">
A call to <code>_g</code> (the guard function) must be the first branch instruction after a loop instruction.
</Aside>
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`.
<Aside type="caution">
Failure to use guards correctly will cause an attempted <code>SetHook</code> transaction to be rejected.
</Aside>

View File

@@ -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.

Some files were not shown because too many files have changed in this diff Show More