Adding form to do fraud reports (#65)

* Adding form to do fraud reports

* Removed SSR
This commit is contained in:
Thomas Silkjær
2025-10-08 16:35:13 +02:00
committed by GitHub
parent 896959c613
commit 8f7545b541
4 changed files with 614 additions and 0 deletions

226
package-lock.json generated
View File

@@ -9,12 +9,14 @@
"version": "0.0.1",
"dependencies": {
"@astrojs/mdx": "^4.3.0",
"@astrojs/node": "^9.4.4",
"@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",
"altcha": "^2.2.4",
"astro": "^5.10.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@@ -27,6 +29,12 @@
"@biomejs/biome": "^2.0.6"
}
},
"node_modules/@altcha/crypto": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/@altcha/crypto/-/crypto-0.0.1.tgz",
"integrity": "sha512-qZMdnoD3lAyvfSUMNtC2adRi666Pxdcw9zqfMU5qBOaJWqpN9K+eqQGWqeiKDMqL0SF+EytNG4kR/Pr/99GJ6g==",
"license": "MIT"
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
@@ -109,6 +117,26 @@
"astro": "^5.0.0"
}
},
"node_modules/@astrojs/node": {
"version": "9.4.4",
"resolved": "https://registry.npmjs.org/@astrojs/node/-/node-9.4.4.tgz",
"integrity": "sha512-zQelZmeejnpw3Y5cj2gCyAZ6HT7tjgsWLZH8k40s3bTaT6lqJXlPtKJeIsuEcod21vZLODqBEQeu0CWrWm01EQ==",
"license": "MIT",
"dependencies": {
"@astrojs/internal-helpers": "0.7.3",
"send": "^1.2.0",
"server-destroy": "^1.0.1"
},
"peerDependencies": {
"astro": "^5.7.0"
}
},
"node_modules/@astrojs/node/node_modules/@astrojs/internal-helpers": {
"version": "0.7.3",
"resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.3.tgz",
"integrity": "sha512-6Pl0bQEIChuW5wqN7jdKrzWfCscW2rG/Cz+fzt4PhSQX2ivBpnhXgFUCs0M3DCYvjYHnPVG2W36X5rmFjZ62sw==",
"license": "MIT"
},
"node_modules/@astrojs/prism": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz",
@@ -2701,6 +2729,31 @@
}
}
},
"node_modules/altcha": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/altcha/-/altcha-2.2.4.tgz",
"integrity": "sha512-UrU2izh1pISqzd7TCAJiJB2N+r7roqA348Qxt1gJlW5k9pJpbDDmMcDaxfuet9h/WFE6Snrritu/WusmERarrg==",
"license": "MIT",
"dependencies": {
"@altcha/crypto": "^0.0.1"
},
"optionalDependencies": {
"@rollup/rollup-linux-x64-gnu": "4.18.0"
}
},
"node_modules/altcha/node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.18.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz",
"integrity": "sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==",
"cpu": [
"x64"
],
"license": "MIT",
"optional": true,
"os": [
"linux"
]
},
"node_modules/ansi-align": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz",
@@ -3417,6 +3470,15 @@
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
"integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/dequal": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
@@ -3504,6 +3566,12 @@
"node": ">=4"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/electron-to-chromium": {
"version": "1.5.177",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.177.tgz",
@@ -3514,6 +3582,15 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/enhanced-resolve": {
"version": "5.18.2",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.2.tgz",
@@ -3619,6 +3696,12 @@
"node": ">=6"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
@@ -3714,6 +3797,15 @@
"@types/estree": "^1.0.0"
}
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/eventemitter3": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
@@ -3802,6 +3894,15 @@
"unicode-trie": "^2.0.0"
}
},
"node_modules/fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@@ -4250,6 +4351,31 @@
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
"integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"license": "MIT",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/http-errors/node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/i18next": {
"version": "23.16.8",
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz",
@@ -4281,6 +4407,12 @@
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/inline-style-parser": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz",
@@ -5772,6 +5904,27 @@
}
]
},
"node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz",
"integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
@@ -5923,6 +6076,18 @@
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
"integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/oniguruma-parser": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz",
@@ -6182,6 +6347,15 @@
"resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz",
"integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/react": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
@@ -6642,6 +6816,40 @@
"semver": "bin/semver.js"
}
},
"node_modules/send": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz",
"integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==",
"license": "MIT",
"dependencies": {
"debug": "^4.3.5",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"mime-types": "^3.0.1",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/server-destroy": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
"integrity": "sha512-rb+9B5YBIEzYcD6x2VKidaa+cqYBJQKnU4oe4E3ANwRRN56yk/ua1YCJT1n21NTS8w6CcOclAKNP3PhdCXKYtQ==",
"license": "ISC"
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/sharp": {
"version": "0.33.5",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
@@ -6801,6 +7009,15 @@
"astro": ">=5.5.0"
}
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/stream-replace-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz",
@@ -6959,6 +7176,15 @@
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",

View File

@@ -11,12 +11,14 @@
},
"dependencies": {
"@astrojs/mdx": "^4.3.0",
"@astrojs/node": "^9.4.4",
"@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",
"altcha": "^2.2.4",
"astro": "^5.10.1",
"react": "^19.1.0",
"react-dom": "^19.1.0",

View File

@@ -16,6 +16,7 @@ import logo from '../assets/xahau-logo.svg'
<a href="/ecosystem">Ecosystem</a>
<a href="/roadmap">Roadmap</a>
<a href="/docs/compliance/responsible-disclosure">Break Xahau</a>
<a href="/fraud-report">Report Fraud</a>
<a href="/docs/resources/media-kit">Media kit</a>
<a href="/privacy-policy">Privacy Policy</a>
</div>

View File

@@ -0,0 +1,385 @@
---
import '../styles/main.css'
import PageLayout from '../layouts/PageLayout.astro'
import PageSection from '../components/PageSection.astro'
const frontmatter = {
title: 'Report Fraud',
description: 'Have you been scammed or hacked? Here is what to do!'
}
---
<PageLayout frontmatter={frontmatter} wide="true">
<PageSection align="center">
<p>Xahau is a public blockchain, with no governing party that can freeze or retrieve funds, close accounts, or otherwise keep people from their assets.</p>
<div class="p-4 bg-green-50 border border-green-200 rounded-lg my-4">
<strong>We can't reverse or cancel transactions, no-one can.</strong>
</div>
<p>We can flag accounts used for illicit activity, which will:</p>
<ul class="list-disc list-outside">
<li>Be included in our API that exchanges and other entities are using for AML compliance to monitor deposits, and possibly withhold illicit funds.</li>
<li>Movement of funds will be auto-traced and we will receive notifications whenever they move, no matter how old the case is.</li>
<li>In case of a scam, warn other users through wallet software and exchanges using our API, not to send funds to a flagged account.</li>
</ul>
<h3 class="mt-4">1. Submit the address to Xahau Forensics</h3>
<p>We maintain the largest fraudulent address registry on Xahau and is used by several entities to combat illicit activity.</p>
<h3 class="mt-4">2. Report your case to law enforcement</h3>
<p>Report it to the local police and if your country has an online report form for cybercrime or financial crime, report it there as well.</p>
<h3 class="mt-4">3. Follow up on your police report</h3>
<p>We work with law enforcement. Let them know that we have the information the odds are that we are also in contact with other victims and can help law enforcement combine cases across jurisdictions and provide actionable intelligence.</p>
<h2 class="mt-4">What can you expect?</h2>
<ul class="list-disc list-outside">
<li>We can't reverse or cancel transactions, no-one can.</li>
<li>We do our best to have funds seized when they leave Xahau, by working with exchanges and other off ramps both through our fraudulent address registry API and by manually making contact.</li>
<li>When you report an account to us, you can expect us to treat your report with as much attention than any other report.</li>
<li>We get many reports every single day. If an account is added to our fraudulent address registry, we are taking the best care of it along with all other cases.</li>
<li>If money is seized we will contact you (if you have left us a way to contact you).</li>
<li>To reclaim funds you <strong>have</strong> to work with law enforcement for paperwork</li>
</ul>
<div class="p-4 bg-green-50 border border-green-200 rounded-lg my-4">
<strong>We monitor hundreds of cases at the same time and can't hold hands on a case-by-case basis. We will only contact you if we have good news!</strong>
</div>
</PageSection>
<main class="page-content flex-1 container mx-auto max-w-4xl p-6">
<div class="bg-white rounded-lg shadow-lg p-8">
<!-- Success message (hidden by default, shown via JS) -->
<div id="success-message" class="mb-6 p-6 bg-green-50 border-2 border-green-500 text-green-800 rounded-lg hidden shadow-md">
<div class="flex items-center mb-2">
<svg class="w-6 h-6 mr-2 text-green-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
<p class="font-bold text-lg">Success!</p>
</div>
<p class="mb-2">Thank you for your report. It has been submitted successfully.</p>
<p class="text-sm mt-3 font-semibold">Report ID: <code id="report-id" class="bg-green-200 px-3 py-1 rounded text-green-900"></code></p>
</div>
<!-- Error message (hidden by default, shown via JS) -->
<div id="error-message" class="mb-6 p-6 bg-red-50 border-2 border-red-500 text-red-800 rounded-lg hidden shadow-md">
<div class="flex items-center mb-2">
<svg class="w-6 h-6 mr-2 text-red-500" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
</svg>
<p class="font-bold text-lg">Error</p>
</div>
<p id="error-text" class="whitespace-pre-wrap"></p>
</div>
<!-- Form container -->
<div id="form-container">
<form id="fraud-report-form" class="space-y-6">
<div>
<label for="address" class="block text-sm font-semibold text-gray-700 mb-2">
Xahau Address <span class="text-red-500">*</span>
</label>
<input
type="text"
id="address"
name="address"
required
placeholder="rXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-xahau-green focus:border-transparent transition-all"
/>
<p class="text-sm text-gray-500 mt-1">Enter the Xahau address associated with the fraudulent activity</p>
</div>
<div>
<label for="description" class="block text-sm font-semibold text-gray-700 mb-2">
Description <span class="text-red-500">*</span>
</label>
<textarea
id="description"
name="description"
required
rows="6"
placeholder="Describe the fraudulent activity"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-xahau-green focus:border-transparent transition-all"
></textarea>
<p class="text-sm text-gray-500 mt-1">Provide as much detail as possible to help us investigate</p>
</div>
<div>
<label for="url" class="block text-sm font-semibold text-gray-700 mb-2">
URL <span class="text-gray-400 text-xs">(Optional)</span>
</label>
<input
type="url"
id="url"
name="url"
placeholder="Optional URL related to the fraud"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-xahau-green focus:border-transparent transition-all"
/>
<p class="text-sm text-gray-500 mt-1">Provide a URL if relevant (e.g., scam website, social media post)</p>
</div>
<div>
<label for="category_suggested" class="block text-sm font-semibold text-gray-700 mb-2">
Suggested Category <span class="text-gray-400 text-xs">(Optional)</span>
</label>
<select
id="category_suggested"
name="category_suggested"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-xahau-green focus:border-transparent transition-all bg-white"
>
<option value="">Select a category...</option>
<option value="giveaway">Giveaway</option>
<option value="theft">Theft</option>
<option value="other">Other</option>
</select>
<p class="text-sm text-gray-500 mt-1">Help us categorize the type of fraud</p>
</div>
<div>
<label for="reporter_contact" class="block text-sm font-semibold text-gray-700 mb-2">
Contact Information <span class="text-gray-400 text-xs">(Optional)</span>
</label>
<input
type="text"
id="reporter_contact"
name="reporter_contact"
placeholder="Optional contact information, for example e-mail, X handle or Telegram username"
class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-xahau-green focus:border-transparent transition-all"
/>
<p class="text-sm text-gray-500 mt-1">Provide contact info if you're willing to help with follow-up questions</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg border border-gray-200">
<altcha-widget
name="altcha"
challengeurl="https://api.analytics.xahau.network/captcha/challenge"
hidefooter="false"
hidelogo="false"
></altcha-widget>
</div>
<div class="flex items-center justify-between pt-4">
<p class="text-sm text-gray-600">
<span class="text-red-500">*</span> Required fields
</p>
<button
type="submit"
class="px-8 py-3 bg-xahau-green-dark text-white font-semibold rounded-lg hover:bg-xahau-green transition-all transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-xahau-green focus:ring-offset-2"
>
Submit Report
</button>
</div>
</form>
<!-- Submit another report button (hidden by default) -->
<div id="another-report-btn" class="mt-6 hidden">
<button
onclick="location.reload()"
class="inline-block px-6 py-3 bg-xahau-green-dark text-white font-semibold rounded-lg hover:bg-xahau-green transition-all no-underline"
>
Submit Another Report
</button>
</div>
</div>
</div>
<div class="mt-8 bg-blue-50 border border-blue-200 rounded-lg p-6 pt-0">
<h3 class="text-lg font-semibold text-blue-900 mb-3">Privacy & Security</h3>
<ul class="space-y-2 text-sm text-blue-800">
<li class="flex items-start">
<svg class="w-5 h-5 mr-2 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
<span>This form uses ALTCHA, a privacy-compliant CAPTCHA that doesn't track you</span>
</li>
<li class="flex items-start">
<svg class="w-5 h-5 mr-2 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
<span>Your report is submitted securely to the Xahau Forensics network</span>
</li>
<li class="flex items-start">
<svg class="w-5 h-5 mr-2 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
<span>Reports are reviewed and used to improve network security</span>
</li>
<li class="flex items-start">
<svg class="w-5 h-5 mr-2 mt-0.5 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
</svg>
<span>No personal information is required to submit a report</span>
</li>
</ul>
</div>
<div class="mt-6 text-center text-sm text-gray-600">
<p>
Xahau Forensics is run by <a href="https://inftf.org" class="text-xahau-green-dark underline hover:text-black">INFTF</a>.
</p>
</div>
</main>
<script is:inline type="module">
// Import ALTCHA widget
import 'https://cdn.jsdelivr.net/npm/altcha/dist/altcha.min.js';
// Wait for the widget to be ready
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('fraud-report-form');
const altchaWidget = document.querySelector('altcha-widget');
const successMessage = document.getElementById('success-message');
const errorMessage = document.getElementById('error-message');
const errorText = document.getElementById('error-text');
const reportIdEl = document.getElementById('report-id');
const formContainer = document.getElementById('form-container');
const anotherReportBtn = document.getElementById('another-report-btn');
if (!form || !altchaWidget) {
return;
}
// Listen for state changes on the ALTCHA widget
let isVerified = false;
altchaWidget.addEventListener('statechange', (event) => {
isVerified = event.detail.state === 'verified';
});
// Handle form submission
form.addEventListener('submit', async (e) => {
e.preventDefault();
// Hide previous messages
errorMessage.classList.add('hidden');
successMessage.classList.add('hidden');
// Check verification state
if (!isVerified) {
errorText.textContent = 'Please complete the CAPTCHA verification before submitting.';
errorMessage.classList.remove('hidden');
// Scroll to top of the white card container
const card = document.querySelector('.bg-white.rounded-lg.shadow-lg');
if (card) {
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
return;
}
// Get ALTCHA payload - try multiple methods
let altchaSolution = null;
// Try getting from FormData first (if widget name attribute works)
const formData = new FormData(form);
altchaSolution = formData.get('altcha');
// If not found, try getting directly from widget
if (!altchaSolution) {
// The widget stores the solution in a hidden input or as a property
const hiddenInput = form.querySelector('input[name="altcha"]');
if (hiddenInput) {
altchaSolution = hiddenInput.value;
}
}
// Try getting from data attribute
if (!altchaSolution) {
altchaSolution = altchaWidget.dataset.payload;
}
if (!altchaSolution) {
errorText.textContent = 'CAPTCHA verification failed. Please complete the challenge and try again.';
errorMessage.classList.remove('hidden');
// Scroll to top of the white card container
const card = document.querySelector('.bg-white.rounded-lg.shadow-lg');
if (card) {
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
return;
}
const requestBody = {
address: formData.get('address'),
description: formData.get('description'),
altcha_solution: altchaSolution
};
// Add optional fields
if (formData.get('url')) requestBody.url = formData.get('url');
if (formData.get('category_suggested')) requestBody.category_suggested = formData.get('category_suggested');
if (formData.get('reporter_contact')) requestBody.reporter_contact = formData.get('reporter_contact');
// Disable submit button and show loading state
const submitBtn = form.querySelector('button[type="submit"]');
const originalText = submitBtn.textContent;
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="flex items-center justify-center"><svg class="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>Submitting...</span>';
try {
const response = await fetch('https://api.analytics.xahau.network/ufr', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(requestBody)
});
const result = await response.json();
if (response.ok) {
// Show success message
reportIdEl.textContent = result.reportId || 'unknown';
successMessage.classList.remove('hidden');
errorMessage.classList.add('hidden');
formContainer.style.display = 'none';
anotherReportBtn.classList.remove('hidden');
// Scroll to top of the white card container
const card = document.querySelector('.bg-white.rounded-lg.shadow-lg');
if (card) {
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
} else {
// Show error message
const errorMsg = Array.isArray(result.message)
? result.message.join(', ')
: (result.message || 'Failed to submit report. Please try again.');
errorText.textContent = errorMsg;
errorMessage.classList.remove('hidden');
successMessage.classList.add('hidden');
submitBtn.disabled = false;
submitBtn.innerHTML = originalText;
// Scroll to top of the white card container
const card = document.querySelector('.bg-white.rounded-lg.shadow-lg');
if (card) {
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
} catch (error) {
errorText.textContent = 'Network error: Unable to connect to the server. Please check your connection and try again.';
errorMessage.classList.remove('hidden');
successMessage.classList.add('hidden');
submitBtn.disabled = false;
submitBtn.innerHTML = originalText;
// Scroll to top of the white card container
const card = document.querySelector('.bg-white.rounded-lg.shadow-lg');
if (card) {
card.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
});
});
</script>
<style>
altcha-widget {
--altcha-primary-color: #007b3d;
--altcha-background-color: #ffffff;
--altcha-border-color: #e1e5e9;
--altcha-text-color: #333333;
--altcha-border-radius: 8px;
--altcha-font-family: 'Onest', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}
</style>
</PageLayout>