Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
452bc29
feat: enhance Stork oracle documentation with feed ID derivation and …
smilewithkhushi Jul 21, 2026
4911f82
feat: add MCP Server documentation for AI coding assistants integration
smilewithkhushi Aug 5, 2026
370f061
Merge pull request #14 from smilewithkhushi/revamp
smilewithkhushi Aug 5, 2026
552f463
feat: add newsletter subscription functionality with API integration
smilewithkhushi Aug 5, 2026
be3f329
Merge pull request #15 from smilewithkhushi/revamp
smilewithkhushi Aug 5, 2026
6b912a1
refractor: clean up
smilewithkhushi Aug 20, 2026
0849fa8
Merge pull request #16 from smilewithkhushi/revamp
smilewithkhushi Aug 20, 2026
03365df
refactor: restructure Vela documentation and remove obsolete files
smilewithkhushi Aug 26, 2026
f2ef3b4
feat: add open in AI tools dropdown
smilewithkhushi Jun 17, 2026
de2b571
update: new ui
smilewithkhushi Jun 30, 2026
01ff49a
Refactor code structure for improved readability and maintainability
smilewithkhushi Jul 1, 2026
d06d8bd
feat: integrate Tailwind CSS for styling enhancements
smilewithkhushi Jul 1, 2026
f496d9a
feat: apply Funnel Display headings, Nunito Sans body, sidebar active…
smilewithkhushi Jul 1, 2026
d8eee03
feat: typography, nav styles, sidebar active state, content updates, …
smilewithkhushi Jul 1, 2026
1362fc8
feat: update documentation and styles for improved clarity and consis…
smilewithkhushi Jul 6, 2026
0cd2fa6
add new tutorials & update the layout
smilewithkhushi Jul 8, 2026
9b604f1
feat: update Stork oracle integration and enhance tutorial content wi…
smilewithkhushi Jul 9, 2026
4e7183c
fix: correct typos and improve clarity in documentation and tutorial …
smilewithkhushi Jul 14, 2026
96c70a8
feat: adjust hero backdrop positioning and enhance light-mode glow ef…
smilewithkhushi Jul 15, 2026
0964a22
feat: enhance Stork oracle documentation with feed ID derivation and …
smilewithkhushi Jul 21, 2026
27581fa
feat: add MCP Server documentation for AI coding assistants integration
smilewithkhushi Aug 5, 2026
9d7986a
feat: add newsletter subscription functionality with API integration
smilewithkhushi Aug 5, 2026
c8301ff
refractor: clean up
smilewithkhushi Aug 20, 2026
8bd4305
refactor: restructure Vela documentation and remove obsolete files
smilewithkhushi Aug 26, 2026
e0c264b
Merge pull request #17 from smilewithkhushi/smilewithkhushi-main
smilewithkhushi Aug 26, 2026
55b9dc2
feat: UI revamp — Tailwind CSS, typography, and AI tools integration
smilewithkhushi Jun 17, 2026
d333b64
feat: add tutorials and update Stork oracle integration
smilewithkhushi Jul 8, 2026
5deda4c
feat: hero backdrop, enhanced Stork docs, MCP server, and newsletter
smilewithkhushi Jul 15, 2026
ea087d0
refactor: clean up and restructure Vela documentation
smilewithkhushi Aug 20, 2026
085937c
docs: update Vela and Horizen documentation
smilewithkhushi Sep 1, 2026
36439af
Merge branch 'main' into smilewithkhushi-main
smilewithkhushi Sep 1, 2026
108afcc
Merge pull request #18 from smilewithkhushi/smilewithkhushi-main
smilewithkhushi Sep 1, 2026
f0575e8
[feat] fixes as per review
smilewithkhushi Sep 7, 2026
60ce13e
Merge pull request #19 from smilewithkhushi/smilewithkhushi-main
smilewithkhushi Sep 7, 2026
d4eb2a9
chore: update documentation and fix code examples; remove unused files
smilewithkhushi Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .dev.vars.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
BEEHIIV_API_KEY=your_beehiiv_api_key_here
PUBLICATION_ID=your_publication_id_here
# Always-pass Cloudflare test secret — replace with real value from the Pages dashboard for production.
TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Env files
.env
.dev.vars
.env.local
.env.development.local
.env.test.local
Expand Down Expand Up @@ -43,3 +44,7 @@ package-lock.json
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Deployment platforms
.vercel
.wrangler
56 changes: 52 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,62 @@ npm run start

## Environment Variables

Create a `.env` file at the root with:
There are two sets of variables depending on where they are consumed.

**Build-time** (Docusaurus, read via `process.env` at `npm run build`): Docusaurus does not load `.env` files natively, so set these as shell environment variables before building:

```sh
# Algolia search — optional; search falls back to local index without these
export ALGOLIA_APP_ID=your_app_id
export ALGOLIA_API_KEY=your_api_key
export ALGOLIA_INDEX_NAME=your_index_name

# Turnstile — build-time only (embedded in the page bundle)
# For local dev the value below is Cloudflare's always-pass test site key; no dashboard needed.
export TURNSTILE_SITE_KEY=1x00000000000000000000AA
```

Or inline for a one-off build:

```sh
TURNSTILE_SITE_KEY=your_key npm run build
```

In CI/CD (e.g. Cloudflare Pages), set these in the project's **Settings → Environment Variables** under the **Build** environment.

**Runtime** (Cloudflare Pages Functions, never bundled into the client): stored in `.dev.vars` locally and in the Pages project's **Settings → Environment Variables** for deployed environments.

| Variable | Type | Description |
|---|---|---|
| `BEEHIIV_API_KEY` | Secret | beehiiv API key |
| `PUBLICATION_ID` | Secret | beehiiv publication ID |
| `TURNSTILE_SECRET_KEY` | Secret | Cloudflare Turnstile secret for server-side verification |

> **Production setup:** all three runtime variables must be set in the Pages project's **Production** environment (and **Preview**, if you want `/api/subscribe` to work on preview deployments). Without them every subscription attempt returns an error.

### Testing Cloudflare Pages Functions locally

The newsletter endpoint (`/api/subscribe`) runs as a Cloudflare Pages Function. Docusaurus's dev server does not execute these functions — use Wrangler instead.

1. Copy the example vars file:

```bash
cp .dev.vars.example .dev.vars
```
ALGOLIA_APP_ID=
ALGOLIA_API_KEY=
ALGOLIA_INDEX_NAME=

`.dev.vars.example` ships with Cloudflare's always-pass test keys pre-filled for `TURNSTILE_SECRET_KEY`, so the form works locally without a real Cloudflare account. Fill in real `BEEHIIV_API_KEY` and `PUBLICATION_ID` values if you want actual subscriptions to go through, or leave them blank to test the flow up to the beehiiv call.

`.dev.vars` is gitignored and never committed.

2. Build the site and start Wrangler's local Pages dev server:

```bash
npm run build
npx wrangler pages dev ./build
```

The site and all API endpoints are then available at `http://localhost:8788`.

## Contributing

1. Fork the repo and create a branch
Expand Down
8 changes: 4 additions & 4 deletions docs/horizen-chain/compliance.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Compliance
description: "Compliance patterns on Horizen: contract-level rules, confidential enforcement via VELA, and third-party AML/KYC screening with PureFi."
description: "Compliance patterns on Horizen: contract-level rules, confidential enforcement via Vela, and third-party AML/KYC screening with PureFi."
sidebar_position: 7
---

Expand All @@ -23,11 +23,11 @@ This pattern is appropriate when your compliance logic is fully deterministic, y

## Confidential Enforcement

Some compliance requirements involve private data: verifying a user meets a financial threshold without disclosing the amount, enforcing policy on encrypted inputs, or producing auditable proof that a rule executed correctly without exposing the underlying state. For these cases, the compliance logic can run inside a TEE using VELA.
Some compliance requirements involve private data: verifying a user meets a financial threshold without disclosing the amount, enforcing policy on encrypted inputs, or producing auditable proof that a rule executed correctly without exposing the underlying state. For these cases, the compliance logic can run inside a TEE using Vela.

The compliance logic is your code. VELA provides a hardware-isolated execution environment and a cryptographic attestation proving the rules ran correctly on the specified input. No operator, cloud provider, or external party can access the data during execution. Authorized verifiers like auditors and regulators can confirm compliance through the attestation without seeing the underlying state.
The compliance logic is your code. Vela provides a hardware-isolated execution environment where data is encrypted in memory and computations are cryptographically attested. No operator, cloud provider, or external party can access the data during execution. Authorized auditors and regulators receive encrypted compliance reports from the TEE, which they can decrypt and verify without exposing any other user's data.

→ [What is VELA?](/vela/introduction)
→ [What is Vela?](/vela/introduction)

## Third-Party AML/KYC Screening

Expand Down
16 changes: 14 additions & 2 deletions docs/horizen-chain/integrations/stork-oracle.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ Full REST API reference: [docs.stork.network/api-reference/rest-api](https://doc

Available asset IDs (e.g. `BTCUSD`, `ETHUSD`) are listed in the [Stork Asset ID Registry](https://docs.stork.network/resources/asset-id-registry).

### Deriving Feed IDs

Encoded feed IDs are the keccak256 hash of the asset ID string. You can derive
any feed ID locally rather than looking it up:

```bash
cast keccak "ETHUSD"
# 0x59102b37de83bdda9f38ac8254e596f0d9ac61d2035c07936675e87342817160
```

The same value is returned as `encoded_asset_id` in the REST API response.



### Step 2: Push Data On-Chain
Expand Down Expand Up @@ -113,7 +125,7 @@ interface IStork {
contract PriceConsumer {
IStork public immutable stork;

// ETHUSD feed ID (verify from Stork Asset Registry)
// ETHUSD feed ID — keccak256("ETHUSD"), verify with: cast keccak "ETHUSD"
bytes32 public constant ETH_USD_ID =
0x59102b37de83bdda9f38ac8254e596f0d9ac61d2035c07936675e87342817160;

Expand All @@ -130,7 +142,7 @@ contract PriceConsumer {
}
```

For view functions where you want to implement custom staleness logic, use `getTemporalNumericValueUnsafeV1` instead — it returns the stored value without reverting on staleness, allowing you to implement your own freshness checks.
If your contract needs a **tighter** freshness window than the chain default (e.g. reject prices older than 60 seconds), call `getTemporalNumericValueV1` as normal and add your own `require` check on `timestampNs`. If you need a **looser** or fully custom freshness policy, use `getTemporalNumericValueUnsafeV1` instead — it returns the stored value without reverting on staleness.



Expand Down
2 changes: 1 addition & 1 deletion docs/horizen-chain/privacy-tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Confidentiality primitives available on Horizen: Vela for TEE-base
sidebar_position: 6
---

Horizen gives you two complementary confidentiality primitives that operate at different layers, in addition to supporting any other EVM-compatible privacy implementation integrated by developers at the app level. Vela keeps inputs and computation private during execution using a TEE-based approach. zkVerify uses zero-knowledge proofs to prove that computation ran correctly and posts attestations onchain for dApp interoperability. These tools can be used independently or together — what you adopt depends on what your application needs to keep private and how it needs to demonstrate correctness.
Horizen gives you two complementary confidentiality primitives that operate at different layers, in addition to supporting any other EVM-compatible privacy implementation integrated by developers at the app level. Vela keeps inputs and computation private during execution using a TEE-based approach. zkVerify uses zero-knowledge proofs to prove that computation ran correctly and posts attestations onchain for dApp interoperability. These tools can be used independently or together. What you adopt depends on what your application needs to keep private and how it needs to demonstrate correctness.


## Vela - Confidential Execution
Expand Down
2 changes: 1 addition & 1 deletion docs/migration/01-overview.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Migration overview
description: "Historical reference: Horizen's ZEN token migration from legacy mainchain and EON EVM chain to a Base ERC-20 contract, completed July 23, 2025. Not relevant to current EVM development on Horizen."
description: "ZEN token migration from the legacy Horizen mainchain (ZEND) and EON EVM chain to a Base ERC-20 contract, completed July 23, 2025. ZEND mainchain holders must manually claim ZEN on Base — no deadline. EON holders were migrated automatically to the same address. Official claim page: https://www.horizen.io/zenclaim"
---

# Migration overview
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorials/horizen-chain/price-triggered-escrow.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ Key facts about the Stork data model:

- `quantizedValue` is `int192` scaled to 18 decimals. Example: $3,500 is `3500e18`.
- `timestampNs` is a nanosecond Unix timestamp (`uint64`). It's a 19-digit integer that **exceeds float64 precision**. See [Step 5](#step-5-server-side-price-proxy) for why this matters in JavaScript.
- The ETH/USD asset ID on all networks: `0x59102b37de83bdda9f38ac8254e596f0d9ac61d2035c07936675e87342817160`
- The ETH/USD asset ID on all networks: `0x59102b37de83bdda9f38ac8254e596f0d9ac61d2035c07936675e87342817160` — derived as keccak256("ETHUSD"); verify with `cast keccak "ETHUSD"`



Expand Down Expand Up @@ -700,7 +700,7 @@ cast call $STORK "getTemporalNumericValueV1(bytes32)(uint64,int192)" $ETH_USD_ID
--rpc-url $RPC_URL

# Read a specific escrow
cast call $VAULT "escrows(uint256)((address,address,uint256,int256,uint8,bool))" 0 \
cast call $VAULT "escrows(uint256)(address,address,uint256,int256,uint8,bool)" 0 \
--rpc-url $RPC_URL

# Cancel an escrow (depositor only)
Expand Down
74 changes: 47 additions & 27 deletions docs/tutorials/integrations/connect-stork-oracle.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Stork identifies price feeds using an **asset ID** - a human-readable string lik

```bash
curl -u "<YOUR_API_KEY>:" \
"https://rest.jp.stork-oracles.com/v1/prices/latest?assets=BTCUSD,ETHUSD"
"https://rest.jp.stork-oracle.network/v1/prices/latest?assets=BTCUSD,ETHUSD"
```

The response contains the latest signed price with its encoded asset ID:
Expand All @@ -62,13 +62,13 @@ The response contains the latest signed price with its encoded asset ID:
"price": "67500000000000000000000",
"stork_signed_price": {
"public_key": "0x...",
"encoded_asset_id": "0x4254435553440000000000000000000000000000000000000000000000000000",
"encoded_asset_id": "0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de",
"price": "67500000000000000000000",
"timestamped_signature": {
"signature": {
"r": "0x...",
"s": "0x...",
"v": 28
"v": "28"
},
"timestamp": 1718000000000000000,
"msg_hash": "0x..."
Expand Down Expand Up @@ -109,8 +109,8 @@ The `TemporalNumericValue` struct returned by the getter:

```solidity
struct TemporalNumericValue {
uint256 timestampNs; // Nanosecond timestamp of the price
int128 quantizedValue; // Price scaled to 18 decimal places
uint64 timestampNs; // Nanosecond timestamp of the price
int192 quantizedValue; // Price scaled to 18 decimal places
}
```

Expand All @@ -134,41 +134,51 @@ const ASSET = "BTCUSD";

// ── Minimal ABI ─────────────────────────────────────────────────────────────
const STORK_ABI = [
"function updateTemporalNumericValuesV1((bytes32 id, (uint256 timestampNs, int128 quantizedValue) temporalNumericValue, bytes32 publisherMerkleRoot, bytes32 valueComputeAlgHash, bytes signature)[] calldata updateData) external payable",
"function getTemporalNumericValueV1(bytes32 id) external view returns (uint256 timestampNs, int128 quantizedValue)",
"function getUpdateFeeV1((bytes32 id, (uint256 timestampNs, int128 quantizedValue) temporalNumericValue, bytes32 publisherMerkleRoot, bytes32 valueComputeAlgHash, bytes signature)[] calldata updateData) external view returns (uint256 feeAmount)",
"function updateTemporalNumericValuesV1(((uint64 timestampNs, int192 quantizedValue) temporalNumericValue, bytes32 id, bytes32 publisherMerkleRoot, bytes32 valueComputeAlgHash, bytes32 r, bytes32 s, uint8 v)[] calldata updateData) external payable",
"function getTemporalNumericValueV1(bytes32 id) external view returns ((uint64 timestampNs, int192 quantizedValue) value)",
"function getUpdateFeeV1(((uint64 timestampNs, int192 quantizedValue) temporalNumericValue, bytes32 id, bytes32 publisherMerkleRoot, bytes32 valueComputeAlgHash, bytes32 r, bytes32 s, uint8 v)[] calldata updateData) external view returns (uint256 feeAmount)",
];

// ── Fetch from Stork API ─────────────────────────────────────────────────────
async function fetchStorkPrice(asset: string) {
const res = await fetch(
`https://rest.jp.stork-oracles.com/v1/prices/latest?assets=${asset}`,
`https://rest.jp.stork-oracle.network/v1/prices/latest?assets=${asset}`,
{
headers: {
Authorization: "Basic " + Buffer.from(`${STORK_API_KEY}:`).toString("base64"),
},
}
);
if (!res.ok) throw new Error(`Stork API error: ${res.status}`);
const json = await res.json();

// Do not use res.json(). timestampNs is a 19-digit integer; JSON.parse
// converts it to float64 and silently rounds it. The Stork signature is
// computed over the exact integer, so a rounded value causes the oracle
// to revert with InvalidSignature.
const rawText = await res.text();
const safeText = rawText.replace(/:(\s*)(-?\d{16,})([,}\]])/g, `:$1"$2"$3`);
const json = JSON.parse(safeText);

return json.data[asset].stork_signed_price;
}

// ── Build update payload ─────────────────────────────────────────────────────
function buildUpdateData(signedPrice: any) {
const { r, s, v } = signedPrice.timestamped_signature.signature;
// Pack the ECDSA signature into 65 bytes: r (32) + s (32) + v (1)
const signature = ethers.concat([r, s, ethers.toBeArray(v)]);

return {
id: signedPrice.encoded_asset_id,
temporalNumericValue: {
timestampNs: BigInt(signedPrice.timestamped_signature.timestamp),
quantizedValue: BigInt(signedPrice.price),
},
id: signedPrice.encoded_asset_id,
publisherMerkleRoot: signedPrice.publisher_merkle_root,
valueComputeAlgHash: signedPrice.calculation_alg.checksum,
signature,
valueComputeAlgHash: signedPrice.calculation_alg.checksum.startsWith("0x")
? signedPrice.calculation_alg.checksum
: `0x${signedPrice.calculation_alg.checksum}`,
r,
s,
v: Number(v),
};
}

Expand Down Expand Up @@ -222,8 +232,8 @@ pragma solidity ^0.8.20;
/// @dev Minimal Stork interface - only what we need
interface IStork {
struct TemporalNumericValue {
uint256 timestampNs;
int128 quantizedValue;
uint64 timestampNs;
int192 quantizedValue;
}

function getTemporalNumericValueV1(bytes32 id)
Expand All @@ -237,17 +247,17 @@ contract PriceGatedVault {

// bytes32 asset IDs - use the encoded_asset_id from the Stork API
bytes32 public constant BTC_USD =
0x4254435553440000000000000000000000000000000000000000000000000000;
0x7404e3d104ea7841c3d9e6fd20adfe99b4ad586bc08d8f3bd3afef894cf184de;

// Price staleness tolerance: reject prices older than 60 seconds
uint256 public constant MAX_PRICE_AGE_NS = 60 * 1e9;

// Minimum BTC price (in USD, 18 decimals) to allow deposits
int128 public constant MIN_PRICE = 50_000 * int128(1e18);
int192 public constant MIN_PRICE = 50_000 * int192(1e18);

mapping(address => uint256) public deposits;

event Deposited(address indexed user, uint256 amount, int128 btcPrice);
event Deposited(address indexed user, uint256 amount, int192 btcPrice);

constructor(address _stork) {
stork = IStork(_stork);
Expand All @@ -273,7 +283,7 @@ contract PriceGatedVault {
emit Deposited(msg.sender, msg.value, price.quantizedValue);
}

function getPrice() external view returns (int128 price, uint256 timestampNs) {
function getPrice() external view returns (int192 price, uint64 timestampNs) {
IStork.TemporalNumericValue memory val =
stork.getTemporalNumericValueV1(BTC_USD);
return (val.quantizedValue, val.timestampNs);
Expand All @@ -293,7 +303,7 @@ forge create src/PriceGatedVault.sol:PriceGatedVault \
### Verify the price read

```bash
cast call <YOUR_VAULT_ADDRESS> "getPrice()(int128,uint256)" \
cast call <YOUR_VAULT_ADDRESS> "getPrice()(int192,uint64)" \
--rpc-url https://horizen-testnet.rpc.caldera.xyz/http
```

Expand Down Expand Up @@ -352,17 +362,27 @@ function depositWithPriceUpdate(

## Encoding Asset IDs

If you need to compute the `bytes32` asset ID for a feed programmatically:
Stork encodes asset IDs as the keccak256 hash of the asset ID string.

With Foundry:

```bash
cast keccak "ETHUSD"
# 0x59102b37de83bdda9f38ac8254e596f0d9ac61d2035c07936675e87342817160
```

With ethers:

```typescript
import { ethers } from "ethers";

// Stork encodes asset IDs as right-padded ASCII bytes32
function encodeAssetId(asset: string): string {
return ethers.encodeBytes32String(asset);
return ethers.keccak256(ethers.toUtf8Bytes(asset));
}

// e.g. "BTCUSD" → "0x4254435553440000000000000000000000000000000000000000000000000000"
console.log(encodeAssetId("BTCUSD"));
console.log(encodeAssetId("ETHUSD"));
```

You can also read the `encoded_asset_id` directly from the Stork REST API
response rather than deriving it. Both are equivalent.

Loading