# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
This site has an agentic ask interface you may use to query the documentation dynamically by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.pye.fi/index.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

---

# Introduction

The DeFi platform for Solana stake

## Why Pye

Pye is building Validator DeFi on Solana.&#x20;

Solana staking is one of the most reliable rewards sources in crypto: stable, predictable, and battle-tested over half a decade. Despite that stability, stakers have almost no options for what to do with their rewards beyond waiting for them to accrue. There are billions of dollars locked up in idle stake, with most stakers and validators concerned about optimizations and hacks that lead to marginal basis point improvements. We believe that DeFi built from the valdiator level up can unlock entirely new revenue streams for Validators and increase Staker APYs manifold.

***

## Who Pye Is For

| Participant          | What they get                                                                                   |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| **Stakers**          | New utility around stake and better returns                                                     |
| **Buyers & Traders** | DeFi strategies around stake and the ability to purchase SOL at a lower cost than anywhere else |
| **Validators**       | Predictable stake, new revenue streams, better tools to manage, retain and attract stake        |


# How Pye Works

Pye is developing the idea of a Programmable Stake Account that leverages new Solana mechanisms that change everything about stake, unlocking a suite of new DeFi products

## Yield Splitter

The Yield Splitter separates staking capital from it's principal. When a staker deposits, the stake is locked up for a defined duration and the position is split into two tokens:

* A **Principal Token (PT):** representing the underlying SOL, redeemable 1:1 at maturity
* A **Reward Token (RT):** representing all staking rewards generated by that position until maturity

These two tokens are SPLs that can be held and redeemed at maturity, traded, collateralized in DeFi, or sold independently.

{% hint style="info" %}
**How are PTs and RTs on Pye different from Pendle?**

Unlike price discovery protocols like Pendle, PTs on Pye are 1:1 redeemable for SOL and do not accrue fixed rewards.
{% endhint %}

#### Principal Tokens (PT)

PTs represent the "principal only" side of a staked position.  At maturity, every PT redeems 1:1 for SOL regardless of which validator it originated from.

**Minting PTs**

PTs are minted 1:1 to the number of tokens deposited:

$$N\_{PT} = P \cdot 1$$

Where $$N\_{PT}$$ is the number of principal tokens to mint and `P` is the principal amount in SOL.<br>

**Redeeming PTs**

At maturity, PT token holders can redeem their tokens for the underlying principal pro rata. To calculate the repayment we use:

$$
RedeemPrincipal(p)= \frac{p}{N\_{PT}}​ \cdot P
$$

where:

* $$p$$ is the number of PT the holder redeems,
* $$P$$ is the total principal backing the pool,
* $$N\_{PT}$$​ is the total supply of PTs outstanding.

***

#### Reward Tokens (RT)

RTs represent the rewards-only side of a staked position, the right to receive all staking rewards generated until maturity, including inflation, MEV, and priority fees.

RT pricing is based on SOL accrued to date, projected forward on an epoch-by-epoch basis from deposit to maturity. Inflation is the most stable component and forms the baseline. MEV and priority fees are more volatile and can increase an RT's value significantly depending on network conditions and how much a validator shares back to stakers.

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/tJGduzqmCYVuSYHg4QMZ/image%20(4).png" alt=""><figcaption></figcaption></figure>

**Minting RTs**

To create a functional rewards curve, RTs need to reflect both how much capital is staked and how long it will generate rewards. The protocol achieves this through a continuous, time-weighted minting formula. A single RT is not a fixed unit of SOL. It is a pro-rata claim on the remaining rewards of a specific lockup duration for a validator. Two RTs from different lockups, or even the same lockup at different deposit times, represent different economic exposures. The time-weighted, minting ensures that every RT holder's claim is proportional to the capital and duration they actually committed.

**The Formula**

When you deposit into a time-based lockup, the program calculates your RT allocation based on the fraction of the lockup’s total duration that remains:

$$\text{RTs} = \text{SOL Deposited} \times \frac{\text{Time Remaining}}{\text{Total Lockup Duration}}$$

At issuance (day 1), you receive 1 RT per SOL:  the maximum allocation. As the lockup progresses toward maturity, new depositors receive proportionally fewer RTs, because they are entitled to fewer remaining epochs of rewards. This creates a natural pricing mechanism: **earlier commitment = larger rewards claim**.

We can formalize the initial value (backing) to be:

$$
S\_0=P
$$

where:

* $$s\_0$$ is the initial deposit
* $$P$$ is the principal deposit amount in SOL.

At the end of each epoch $$t$$, the stake account grows by the effective staking reward rate $$r\_t$$​. The value after $$t$$ epochs is:

$$
S\_t=S\_{t−1}⋅(1+r\_t),  ;;;;;;;   t=1,2,…,T
$$

After $$T$$ epochs (maturity), the stake account balance is:

$$
S\_T = S\_0 \cdot \prod\_{t=1}^{T} (1 + r\_t)
$$

where:

* $$S\_0​=P$$ = initial deposit
* $$r\_t$$​ already accounts for validator commission, inflation rate, MEV, etc.

The rewards is the difference between the maturity value and the initial deposit:

$$
R = S\_T - P
$$

Therefore:

* PT holders redeem their tokens for exactly $$P$$ units of SOL, independent of reward.
* RT holders redeem their tokens for the residual rewards $$R$$, distributed pro rata to the number of RT tokens they hold.

**Why Time-Weighting Matters**

Consider a 12-month lockup. A depositor on day 1 is entitled to a full year of staking rewards. A depositor at the 9-month mark is only entitled to the final 3 months. Minting the same number of RTs to both would dilute the early depositor's claim. The time-weighted formula prevents this, each RT always represents an equal share of the lockup's remaining production.

**Example: Same deposit amount, different lockup durations (deposited at issuance)**

| Deposit Timing | Time Remaining | Fraction | PTs Minted | RTs Minted |
| -------------- | -------------- | -------- | ---------- | ---------- |
| At issuance    | 12 months      | 100%     | 10 PT      | 10 RT      |
| 3 months in    | 9 months       | 75%      | 10 PT      | 7.5 RT     |
| 6 months in    | 6 months       | 50%      | 10 PT      | 5 RT       |
| 9 months in    | 3 months       | 25%      | 10 PT      | 2.5 RT     |

**Example: RT value at maturity by lockup duration (assuming \~7% APY)**

| SOL Deposited | Lockup Duration | PTs Minted | RTs Minted | RT Value at Maturity |
| ------------- | --------------- | ---------- | ---------- | -------------------- |
| 1 SOL         | 3 months        | 1 PT       | 1 RT       | 0.018 SOL            |
| 10 SOL        | 6 months        | 10 PT      | 10 RT      | 0.035 SOL            |
| 10 SOL        | 12 months       | 10 PT      | 10 RT      | 0.070 SOL            |
| 100 SOL       | 12 months       | 100 PT     | 100 RT     | 0.070 SOL            |

*Illustrative example assuming \~7% APY. Actual value depends on validator performance and commissions.*

{% hint style="info" %}
When depositing at issuance, the lockup duration doesn't change the RT count, you always get 1 RT per SOL. What changes is what each RT is worth. An RT on a 12-month lockup represents a claim on 12 months of validator production, while an RT on a 3-month lockup represents only 3 months.
{% endhint %}

***

## Orderbook

The orderbook allows for markets to be created around trading stake accounts and rewards. Principal Tokens and Reward Tokens can be traded, matched and settled on Pye's on-chain orderbook. There are two types of orders supported:

* **Limit orders:** orders placed against a specific validator market at a target discount rate. Fills when a matching seller appears.
* **Market orders:** fills immediately at the best available rate in a given market.

#### Fixed Maturities

All markets on the orderbook settle at fixed 3-month maturities aligned to end-of-quarter dates. Shared maturities mean liquidity concentrates rather than fragments across arbitrary timeframes. It also means buyers can set universal orders across every market on the platform simultaneously, a single order that fills against any validator offering a matching discount rate.

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/8HUCScoHw4VrRC0acZ0z/image%20(5).png" alt=""><figcaption></figcaption></figure>

#### Trading on the Orderbook

PTs earn no rewards but can be traded at a discount to par because they are future assets being priced today. The reason PTs trade at a discount is that the buyer is purchasing a locked version of SOL.

For buyers, purchasing a PT at a discount is equivalent to locking in a fixed return on SOL. The position is straightforward: buy below par today, redeem at par at maturity.<br>

<figure><img src="https://3895694265-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fj4UC7QTpb7zf4JXXnPJl%2Fuploads%2F92APLRI3iyWEUab9qgPo%2FSits%20in%20wallet.png?alt=media&amp;token=069d393b-ccd7-42c8-8da9-03be892f6e1d" alt=""><figcaption></figcaption></figure>

For buyers, RTs are a way to gain direct exposure to Solana staking rewards without holding the underlying SOL.


# Stakers

## What Stakers Can Do on Pye

Pye is building DeFi products for Solana Staking granting you more utility over your stake.

The first product launched is [Speedstake](https://pye.fi/products/speedstake),  which lets you sell your future staking rewards today and receive SOL immediately, without unstaking or waiting for a cooldown period. If you have SOL that's already staked with a validator, you can sell your future rewards directly, your SOL stays staked, your validator relationship stays intact, and you get paid now for committing the stake to pre-defined lockup durations.

{% hint style="info" %}
**What is staked SOL?** When you delegate SOL to a validator on Solana, it becomes "staked SOL" the next epoch: earning rewards each epoch but otherwise inaccessible. Pye lets you access the value of those future rewards without waiting or unstaking.
{% endhint %}

***

## How to Sell Your Future Rewards with Speedstake

1. Go to the [app](https://pye.fi/speedstake)
2. Connect your wallet
3. Choose your deposit amount and choose a validator that you staked SOL to
4. Select a maturity date and the amount you want to lock up
5. Review the discount rate and estimated SOL you'll receive
6. Sign the transaction

<figure><img src="https://3895694265-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fj4UC7QTpb7zf4JXXnPJl%2Fuploads%2FsxT1GfV2TDdB32vhomo2%2Fspeedstake.gif?alt=media&amp;token=19593a37-2aff-4fb7-a597-4a7b09313bca" alt="" width="188"><figcaption></figcaption></figure>

Once the transaction executes, you'll receive SOL immediately. You'll also receive a Principal Token (PT) token in your wallet, which is a receipt that represents your principal and can be redeemed 1:1 for SOL at maturity or sold on Pye's orderbook for an earlier exit.

***

## Understanding the Discount Rate

When you sell your future rewards on Pye through Speedstake, you receive SOL at a discount to the full value you would have earned by waiting.

The discount rate is the difference between what you receive today and what you would have earned at maturity.

* A **lower discount rate** means you give up less: you're closer to full value.
* A **higher discount rate** means you give up more in exchange for receiving SOL sooner.

The price is set by what available buyers are willing to take based on the discount and lockup period.

{% hint style="info" %}
Before you sign, Speedstake will show you how much liquidity is available on Pye's orderbook to fill your order at your chosen size and rate. If liquidity is thin, you may receive a warning that your order could sit unfilled.
{% endhint %}

Traders with early access can also set limit orders directly on the Pye orderbook if they want more control over the rate they accept.

***

## Deposits

**Existing stake accounts:** If you're already staked with a whitelisted validator, Pye tokenizes your stake account into two SPL tokens that are redeemable at maturity:

* **Principal Tokens** redeem 1:1 for SOL.
* **Reward Tokens** receive all staking rewards: inflation, MEV, and any priority fees shared by the validator — that accrued from the deposit date to maturity.

Whoever holds those tokens has the right to redeem them. Your SOL stays staked. Speedstake automatically sells your RTs at the time of deposit allowing on the Pye orderbook giving you SOL today.

## FAQ

<details>

<summary>How do I redeem at maturity?</summary>

You can redeem via Speedstake

</details>

<details>

<summary>How will I know the maturity date?</summary>

Tokens are labelled with maturity dates in the metadata. Apps like Speedstake also show how much longer you need to wait to redeem PTs.

</details>

<details>

<summary>Do I need to unstake to use Pye?</summary>

No. Existing stake accounts from whitelisted validators can be used directly. Your SOL stays staked.

</details>

<details>

<summary>What happens to my staked SOL after I transact?</summary>

Pye tokenizes your staked position into two SPL tokens, a PT and an RT. Your SOL stays staked with the validator. Whoever holds those tokens has the right to redeem them at maturity.

</details>

<details>

<summary>What is the PT I received and what do I do with it?</summary>

1 PT = 1 SOL at maturity. You can hold it and redeem it on Pye when the maturity date arrives, or trade it on the Pye orderbook (if you are part of early access)

</details>

<details>

<summary>What do I get back at maturity?</summary>

You will receive SOL when redeeming PTs and RTs at maturity.

</details>

<details>

<summary>Can I exit my position before maturity?</summary>

Yes. PT and RT tokens can be sold on the Pye Exchange at any time before maturity. Speedstake allows you to request an OTC to exit early.

</details>

<details>

<summary>What if there isn't enough liquidity to fill my order on Speedstake?</summary>

Speedstake will alert you before you sign. You can reduce your order size or wait for liquidity to improve.

</details>

<details>

<summary>Do I pay fees?</summary>

The protocol collects nominal fees when engaging with different Pye products such as Speedstake. Minting fees are set to zero for now, this is subject to change in the future.

</details>

<details>

<summary>What if my validator goes offline before maturity?</summary>

Your PT is always safe, Solana does not have slashing. If a validator goes offline, your PT remains redeemable for 1 SOL at maturity. Any RT rewards that accrued before the validator went offline are also safe. RT rewards will stop generating if the validator ceases operations. Do your own research before choosing a validator or buying their rewards.

</details>

<details>

<summary>Which validators are available?</summary>

You can browse whitelisted validators in the Rewards Widget or on the Pye app.&#x20;

</details>

<details>

<summary>Is there a points program?</summary>

Yes, points are running in the background. More details will be disclosed over time.

</details>


# Validators

Attract stake, retain stakers, and generate new revenue streams with Pye.

## How Pye Benefits Validators

Validators on Solana compete on thin margins with little differentiation. Commissions are public, rewards are commoditized, and most stakers have no reason to choose one validator over another.

By using Pye, validators gain tools to attract stake, retain stakers, and generate additional revenue — without changing how they operate.

***

## Getting Listed

Validators must register with Pye before integrating the Rewards Widget or appearing on the platform. Registration gives you access to all Pye features: widget listing, markets on the Pye exchange, widget embed, and the Custom Commission CLI.

Once approved, your validator appears in the Pye exchange and widget. Stakers with active stake accounts can interact with your validator via the Rewards Widget.

[Apply to be listed →](https://pye.fi)

***

## Fixed Deposits and Predictable Revenue

When a staker sells their future rewards on Pye, their SOL remains locked with your validator until the maturity date. This means:

* **Stable & new revenue** — locked positions generate consistent staking rewards for the duration of the maturity period. Whenever your staker uses the Pye Widget to sell their future rewards, a fee goes to you, manageable from the Validator Dashboard.
* **Predictable withdrawal schedules** — stake delegated through Pye follows fixed quarterly maturities, so you know when redemptions will occur
* **Reduced churn** — stakers who have transacted through Pye are committed to the maturity date, reducing unstaking until the maturity date.
* **Trading Fees** — validators who integrate with the widget can earn additional fees without breaking the user experience.

***

## Validator FAQ

<details>

<summary>Do my existing stakers need to do anything?</summary>

No. Stakers with existing positions can use Pye directly — the program detects existing stake accounts when using Pye Trade or the Rewards Widget without requiring deactivation. There's nothing you need to change on your end. Once you're listed, your validator appears in the marketplace automatically.

</details>

<details>

<summary>Does Pye change how my validator operates?</summary>

No. Pye sits on top of your existing operation. You continue to run your validator as normal. Pye handles the orderbook, token minting, and staker experience. The Programmable Stake Accounts (PSA) operate like a wrapper around the native solana stake accounts and stake is confined to specific lockups, delegated back to you. The PSA has mint and withdraw authority.

</details>

<details>

<summary>What happens at maturity?</summary>

Stakers who deposited through Pye can redeem their Principal tokens or Reward tokens on Pye at the end of the quarter. The underlying stake may be withdrawn or rolled over depending on the staker's choice. Withdrawals follow Solana's standard cooldown period.

</details>

<details>

<summary>Is the widget free?</summary>

Yes. The Rewards Widget is free for all whitelisted validators. Revenue flows through orderbook trading fees, not validator charges.

</details>

<details>

<summary>Can I offer different terms to different stakers?</summary>

Yes, via the Pye CLI. You can offer custom commission structures to specific stakers outside of your public on-chain commission.

</details>

<details>

<summary>Am I offering these lockups or are stakers opting in?</summary>

Stakers opt into lockups based on pre-defined periods. When a staker engages with a specific validator via Pye, the underlying stake is locked with that validator until maturity. The responsibility lies with the staker who is partaking in the action.

</details>


# Speedstake

Embed Speedstake on your website in minutes

***

### Integrating Speedstake

For the first time ever, stakers can [sell their future rewards](/stakers#what-stakers-can-do-on-pye) for SOL via Speedstake by Pye. It lets active stakers delegated to your validator lockup stake for different time durations and sell their future rewards directly from your dedicated site offering a new revenue stream and predictable stake. This guide covers the different integration paths available.

### Prerequisites

You'll need four values before you start:

<table><thead><tr><th>Value</th><th width="368">What it is</th></tr></thead><tbody><tr><td><strong>Vote Account</strong></td><td>Your validator's <strong>vote account address</strong></td></tr><tr><td><strong>RPC endpoint</strong></td><td><a href="https://api.mainnet-beta.solana.com  ">https://api.mainnet-beta.solana.com  </a></td></tr><tr><td><strong>Supabase URL</strong></td><td><a href="https://tfrickmnrfyjkvjhmuik.supabase.co">https://tfrickmnrfyjkvjhmuik.supabase.co</a></td></tr><tr><td><strong>Supabase Anon Key</strong></td><td><code>eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRmcmlja21ucmZ5amt2amhtdWlrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDM0NDkyMDksImV4cCI6MjA1OTAyNTIwOX0.1wl2FWa5g0tkUn6yRcg1AyF6ixWN7SyoD89cFGxkQKM</code></td></tr></tbody></table>

#### Finding your vote account address

Your vote account is the on-chain address that receives staking rewards. It's not your identity account or withdraw authority. Using the wrong one will cause Speedstake to show no stake positions.

Where you can find it:

* [**stakewhiz**](https://www.validators.app/ahttps://stakewiz.com/) — search your validator name; the vote account appears on your profile page.
* [**Solana Explorer**](https://explorer.solana.com/validators) — search by validator name or identity key.
* **Solana CLI** — `solana validators | grep <your-name>`

### Configuration

You can configure what mode Speedstake runs in as well as its style theme.&#x20;

Single-validator mode filters stake positions to only those delegated to your vote account. Universal mode shows positions across all supported validators, enable it by omitting the vote account prop.

| Mode                 | What it shows                                              | How to configure   |
| -------------------- | ---------------------------------------------------------- | ------------------ |
| **Single-validator** | Only stake accounts delegated to your validator            | Pass `voteAccount` |
| **Universal**        | All Pye-compatible stake accounts for the connected wallet | Omit `voteAccount` |

The style defaults to `pye-dark`. Pass one of the following `theme` props (React and Next.js) or set the `data-theme` attribute (CDN).

| Value       | Appearance                           |
| ----------- | ------------------------------------ |
| `pye-light` | Light background, purple accent      |
| `pye-dark`  | Dark background, purple accent       |
| `graphite`  | Dark background, neutral grey accent |

### Installation

{% tabs %}
{% tab title="React (Vite)" %}

#### 1. Install packages

bash

```bash
npm install --legacy-peer-deps @pyefi/sdk @pyefi/widget \
  react react-dom \
  @solana/web3.js @solana/spl-token \
  @solana/wallet-adapter-react @solana/wallet-adapter-base @solana/wallet-adapter-wallets \
  @solana/kit@^2 @cks-systems/manifest-sdk \
  @supabase/supabase-js \
  buffer stream-browserify assert
```

Or with pnpm:

bash

```bash
pnpm add @pyefi/sdk @pyefi/widget \
  react react-dom \
  @solana/web3.js @solana/spl-token \
  @solana/wallet-adapter-react @solana/wallet-adapter-base @solana/wallet-adapter-wallets \
  @solana/kit@^2 @cks-systems/manifest-sdk \
  @supabase/supabase-js \
  buffer stream-browserify assert
```

> **Note** — `buffer`, `stream-browserify`, and `assert` are runtime polyfills required by Solana packages in a browser Vite build.

#### 2. Configure Vite

Update `vite.config.ts` to polyfill the Node.js globals that Solana packages depend on:

typescript

```typescript
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [react()],
  define: {
    "process.env": {},
    "process.version": JSON.stringify("v18.0.0"),
    "process.browser": true,
  },
  resolve: {
    alias: {
      stream: "stream-browserify",
      assert: "assert",
    },
  },
});
```

#### 3. Configure TypeScript

If you don't already have a `tsconfig.json`, create one. Make sure it includes `"vite/client"` in `types` — this gives TypeScript the `import.meta.env` definitions that Vite injects at build time:

```json
{
  "compilerOptions": {
    "target": "ES2020",
    "lib": ["ES2020", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "skipLibCheck": true,
    "types": ["vite/client"]
  },
  "include": ["src"]
}
```

If you already have a `tsconfig.json`, add `"types": ["vite/client"]` to `compilerOptions`.

#### 4. Add the Buffer polyfill

> **Warning** — These two lines must be the **very first lines** of your app entry file (e.g. `src/main.tsx`), before any other imports. If they run after Solana packages load, the polyfill won't take effect.

```typescript
import { Buffer } from "buffer";
(window as any).Buffer = Buffer;

// ...rest of your imports
```

#### 5. Set environment variables

Create `.env.local`:

bash

```bash
VITE_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY
VITE_SUPABASE_URL=https://YOUR_PROJECT.supabase.co
VITE_SUPABASE_ANON_KEY=YOUR_ANON_KEY
VITE_VOTE_ACCOUNT=YOUR_VOTE_ACCOUNT
```

#### 6. Render the Speedstake widget

```tsx
import { useState } from "react";
import { PyeWidget } from "@pyefi/widget";

export default function App() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Get paid now</button>

      {open && (
        <div
          style={{
            position: "fixed", inset: 0,
            display: "flex", alignItems: "center", justifyContent: "center",
            background: "rgba(0,0,0,0.5)", backdropFilter: "blur(8px)",
            zIndex: 9999,
          }}
          onClick={(e) => { if (e.target === e.currentTarget) setOpen(false); }}
        >
          <PyeWidget
            rpcUrl={import.meta.env.VITE_RPC_URL}
            supabaseUrl={import.meta.env.VITE_SUPABASE_URL}
            supabaseAnonKey={import.meta.env.VITE_SUPABASE_ANON_KEY}
            voteAccount={import.meta.env.VITE_VOTE_ACCOUNT}
            theme="pye-dark"
            onClose={() => setOpen(false)}
          />
        </div>
      )}
    </>
  );
}
```

{% endtab %}

{% tab title="Next.js (App Router)" %}

#### 1. Install packages

```bash
npm install --legacy-peer-deps @pyefi/sdk @pyefi/widget \
  react react-dom \
  @solana/web3.js @solana/spl-token \
  @solana/wallet-adapter-react @solana/wallet-adapter-base @solana/wallet-adapter-wallets \
  "@solana/kit@^2" @cks-systems/manifest-sdk \
  @supabase/supabase-js \
  next
```

#### 2. Configure Next.js

Update `next.config.ts`:

```ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  transpilePackages: ["@pyefi/sdk", "@pyefi/widget"],
  turbopack: {},
};

export default nextConfig;
```

`transpilePackages` is required because `@pyefi/widget` ships as an ES module. `turbopack: {}` is required for Next.js 16+, which uses Turbopack by default — it automatically handles Node.js built-in exclusions for browser bundles so no additional webpack fallback config is needed.

> **Next.js 15 or earlier:** Replace `turbopack: {}` with a webpack config instead:
>
> ```ts
> webpack: (config) => {
>   config.resolve.fallback = { ...config.resolve.fallback, fs: false, net: false, tls: false };
>   return config;
> },
> ```

#### 3. Set environment variables

Create `.env.local`:

```
NEXT_PUBLIC_RPC_URL=https://mainnet.helius-rpc.com/?api-key=YOUR_KEY
NEXT_PUBLIC_SUPABASE_URL=https://tfrickmnrfyjkvjhmuik.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InRmcmlja21ucmZ5amt2amhtdWlrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDM0NDkyMDksImV4cCI6MjA1OTAyNTIwOX0.1wl2FWa5g0tkUn6yRcg1AyF6ixWN7SyoD89cFGxkQKM
NEXT_PUBLIC_VOTE_ACCOUNT=YOUR_VOTE_ACCOUNT
```

#### 4. Render the widget

The component must be in a Client Component (add `"use client"` at the top):

```tsx
"use client";

import { useState } from "react";
import { PyeWidget } from "@pyefi/widget";

export default function Page() {
  const [open, setOpen] = useState(false);

  return (
    <>
      <button onClick={() => setOpen(true)}>Get paid now</button>

      {open && (
        <div
          style={{
            position: "fixed", inset: 0,
            display: "flex", alignItems: "center", justifyContent: "center",
            background: "rgba(0,0,0,0.5)", backdropFilter: "blur(8px)",
            zIndex: 9999,
          }}
          onClick={(e) => { if (e.target === e.currentTarget) setOpen(false); }}
        >
          <PyeWidget
            rpcUrl={process.env.NEXT_PUBLIC_RPC_URL!}
            supabaseUrl={process.env.NEXT_PUBLIC_SUPABASE_URL!}
            supabaseAnonKey={process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!}
            voteAccount={process.env.NEXT_PUBLIC_VOTE_ACCOUNT!}
            theme="pye-dark"
            onClose={() => setOpen(false)}
          />
        </div>
      )}
    </>
  );
}
```

> **Universal mode** — Omit the `voteAccount` prop and the `NEXT_PUBLIC_VOTE_ACCOUNT` env variable.
> {% endtab %}

{% tab title="HTML/CDN" %}

### HTML / CDN

No build step required. Add a single `<script>` tag to any HTML page.

#### Single-validator

html

```html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>My Validator</title>
</head>
<body>
  <div id="pye-widget"></div>

  <script
    data-pye-widget
    data-vote-account="YOUR_VOTE_ACCOUNT"
    data-theme="pye-dark"
    data-rpc-url="https://mainnet.helius-rpc.com/?api-key=YOUR_KEY"
    data-supabase-url="https://YOUR_PROJECT.supabase.co"
    data-supabase-anon-key="YOUR_ANON_KEY"
    src="REPLACE_WITH_CDN_URL"
  ></script>
</body>
</html>
```

#### Universal

Omit `data-vote-account`:

html

```html
<script
  data-pye-widget
  data-theme="pye-dark"
  data-rpc-url="https://mainnet.helius-rpc.com/?api-key=YOUR_KEY"
  data-supabase-url="https://YOUR_PROJECT.supabase.co"
  data-supabase-anon-key="YOUR_ANON_KEY"
  src="REPLACE_WITH_CDN_URL"
></script>
```

#### How it mounts

The script looks for a `<div id="pye-widget">` element and mounts into it. If none exists, it creates one and appends it to `<body>`. All configuration is read from the `data-*` attributes on the `<script>` tag itself.

***

### React / Next.js props

| Prop              | Type                                      | Required | Default       | Description                            |
| ----------------- | ----------------------------------------- | -------- | ------------- | -------------------------------------- |
| `rpcUrl`          | `string`                                  | yes      | —             | Solana mainnet RPC endpoint            |
| `supabaseUrl`     | `string`                                  | yes      | —             | Supabase project URL                   |
| `supabaseAnonKey` | `string`                                  | yes      | —             | Supabase anonymous key                 |
| `voteAccount`     | `string`                                  | no       | —             | Vote account for single-validator mode |
| `theme`           | `"pye-light" \| "pye-dark" \| "graphite"` | no       | `"pye-light"` | Visual theme                           |
| `onClose`         | `() => void`                              | no       | —             | Called when the user closes the widget |

### CDN data attributes

| Attribute                | Required | Default                               | Description                                        |
| ------------------------ | -------- | ------------------------------------- | -------------------------------------------------- |
| `data-pye-widget`        | yes      | —                                     | Identifies the script tag (no value needed)        |
| `data-supabase-url`      | yes      | —                                     | Supabase project URL                               |
| `data-supabase-anon-key` | yes      | —                                     | Supabase anonymous key                             |
| `data-rpc-url`           | no       | `https://api.mainnet-beta.solana.com` | Solana RPC endpoint                                |
| `data-vote-account`      | no       | —                                     | Vote account for single-validator mode             |
| `data-theme`             | no       | `pye-light`                           | Visual theme (`pye-light`, `pye-dark`, `graphite`) |
| {% endtab %}             |          |                                       |                                                    |
| {% endtabs %}            |          |                                       |                                                    |

### RPC endpoint

{% hint style="info" %}
**Important** — The public endpoint (`https://api.mainnet-beta.solana.com`) works for development but has rate limits that will cause wallet and balance fetches to fail under normal production usage. Use a dedicated provider in production.
{% endhint %}

Recommended providers:

* [**Helius**](https://helius.dev)&#x20;
* [**Triton**](https://triton.one)
* [**QuickNode**](https://quicknode.com)


# Validator Dashboard

Create, manage, and track your stake products from one place.

The [Validator Dashboard](https://dashboard.pye.fi/) is where you create, manage, and track your stake products. Deposit volume, TVL across public and private lockups, projected APYs and team access. All in one place, updated every epoch.

*Note: Node verification required. New organizations can be created freely, but lockup creation is blocked until the Pye team verifies your validator node(s). You'll see a pending verification notice on the Create Lockup page until this is complete.*

#### Overview Metrics

See a snapshot of your Validator operations and staker engagement.

**Validator Stake (Total)** is the full SOL delegated to your node: Pye-issued and non-Pye combined. Updates each epoch from on-chain data.

**SOL Staked via Pye** is the portion of that stake that entered through Pye-issued lockups. Watching this relative to your total tells you how much of your stake base has opted into documented, on-chain terms.

**Profit (All Nodes)** charts your cumulative commission earnings across all lockups, broken down by inflation, MEV, and block rewards.

**PYE Points** tracks the cumulative points accrued across your lockups over time.

#### Lockup Performance Analytics

Clicking on an individual lockup navigates to its public detail page on app.pye.fi, where you can view historical APY plotted against the Solana network average. The chart breaks down by reward source: inflation, MEV, and block rewards. You can see which component is driving variance in a given period. This is the same page stakers see when evaluating whether to delegate to you and go to when you share a link for them to deposit.

#### Organization & Node Management

Your organization is the top-level container for everything on Pye: your nodes, your team, how much is staked to you via Pye products and your lockups.

**Settings** lets you update your organization's display name and logo. These appear on your public lockup pages, so keep them current. Stakers see your org branding when they're evaluating whether to deposit.

**Node IDs** is where you add and manage the validator nodes connected to your organization. Pye supports multiple nodes under a single org, so if you operate more than one validator you don't need separate accounts. Add each node by its vote account address. Once added, you can create lockups independently for each node. Commissions, terms, and TVL are tracked per-node.

**User Management** is where you manage users. There are two types of users that can be invited to join your validator organization: `Admins` and `Members`. `Admins` can add or remove members as well as assign a new admin (thereby revoking their admin status). `Admins` are also able to create lockups for the validator org as well as invite members and edit organization details. Both `Admins` and `members` are able to view the Validator's dashboard and details about created lockups as well and total stake deposited so far. On the User Management tab you can assign more **Admins.** Members have read-only dashboard access. Remove departing team members promptly.

#### Claim Fees

The Claim Fees page lets you collect trading fees earned from DeFi activity on Pye products. For example, when stakers sell Reward tokens on Speedstake, a portion of the fees accrues to the validator they are staked with. Your claimable balance is displayed in SOL with a USD equivalent.&#x20;

Fees accumulate continuously as trades occur on your lockups' PT/RT pairs. There is no deadline to claim; uncollected fees remain available indefinitely.

#### Lockup Table

Shows all lockups associated with your validator, in three tabs.

**Public** lockups can be accessed by any staker. **Private** lockups are restricted to a single depositor address you specify during creation. Useful for one-off institutional arrangements or custom terms not meant for the open marketplace. Only the designated wallet can deposit; all other wallets are blocked.

| Column             | What it shows                                                                                                                                                                                                |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Product**        | Term length                                                                                                                                                                                                  |
| **Status**         | <p><em>Deposits Open:</em> accepting new deposits. <em>Deposits Closed:</em> no new deposits, lockup still running to maturity. </p><p><em>Expired:</em> past maturity date, PT/RT redemption available.</p> |
| **Maturity**       | The date depositors can redeem their Principal Tokens for the underlying SOL.                                                                                                                                |
| **Capacity (SOL)** | The maximum SOL the lockup will accept. Once reached, deposits close automatically. Optional: lockups without a cap stay open until the maturity date.                                                       |
| **TVL**            | Current dollar value of SOL held in the lockup. On expired lockups, non-zero TVL means stakers haven't redeemed yet.                                                                                         |
| **Inflation Com.** | Your commission rate on inflation rewards for this lockup.                                                                                                                                                   |
| **MEV Com.**       | Your commission rate on MEV and priority fee rewards.                                                                                                                                                        |
| **Block Com.**     | Your commission rate on block production rewards.                                                                                                                                                            |
| **Proj. APY**      | Projected annualized return for depositors, calculated from the three commission rates and your recent validator performance.                                                                                |
| **Stakers**        | Number of distinct wallet addresses currently deposited in this lockup.                                                                                                                                      |

**Status transitions**

Lockup status changes are automatic. A lockup opens at the start date you set during creation and closes to new deposits when it either hits its deposit cap or reaches the end of the open window. You cannot manually reopen a closed lockup or extend a maturity date after the lockup has been created.

If a lockup fills before you expected, or you want to continue running the same terms after it closes, create a new lockup. Each lockup gets its own URL. Stakers with a link to the original will see a "deposits closed" or "at capacity" state; point them to the new one directly or update whatever surface you used to share the original link.

**Custom Commissions**

Custom commissions require the Pye CLI, which handles automated reward calculation and distribution at the end of each epoch.

The **Custom Commissions** page in the dashboard shows you three things: whether the CLI is connected and running, the payer wallet currently funding distribution transactions, and per-lockup distribution status.

You only need one CLI instance per organization. Once running, it handles automated distribution across every lockup on every node connected to your org, you don't need a separate instance per node or per lockup.

**Payer wallet** is the wallet that funds the transaction fees for each epoch's reward distribution. This is separate from your user wallet (used for deploying lockups) and your validator identity. If the payer wallet runs low on SOL, distributions will fail, keep it topped up. You can update the payer wallet from this page without restarting the CLI.

Each lockup carries independent commission rates for each reward source, encoded in the on-chain account data at creation. Inflation is the most stable of the three sources, it tracks network parameters and epoch-level validator performance. MEV and block rewards are more variable: MEV in particular depends on your positioning in the Jito tip ecosystem and block frequency. A lockup offering a high MEV share will show higher projected APY in periods where MEV is elevated, and lower in quiet periods. Each lockup has configurable commission rates you can setup for how much rewards go to the Validator vs stakers. Stakers comparing your lockups to others will see this variance, so the commission split you set matters as much as the headline APY number.

If a lockup has a deposit cap, it appears alongside the TVL. Caps let you run volume-limited offers — a promotional commission structure, a tranche-limited private deal — that close automatically when the cap is reached rather than staying open indefinitely.

#### Operating Notes

**Treat your admin list like key rotation.** It is the access control between your organization and the ability to issue new lockups. A member that leaves your team should be removed.

**Private lockups are not secret by default: they are permissioned.** Anyone with the link can see a private lockup's terms. What they can't do is deposit unless their wallet address is the designated depositor. If you need the terms themselves to be confidential, share the link only with the counterparty.

**A lockup's commission structure cannot be changed after creation.** If you need to offer different terms, create a new lockup. Currently the old one runs to its maturity date regardless, so use caps strategically for testing. Contact the Pye Team if you have concerns about removing an existing lockup.


# Create a Lockup

Create public or private staking lockups in the Validator Dashboard.

{% embed url="<https://www.loom.com/share/a65fd37abaab47a3a26211639eae1e0a>" %}

This guide is intended for whitelisted validators who are issuing Lockups. In order to create a lockup, your organization needs to approve specific wallets affiliated with your validator organization as `admins.` Admins have the ability to sign and create Lockups.&#x20;

If you have not yet completed the whitelisting approval process, please refer to the [Validator Onboarding section](broken://pages/SsY3khSSHWj9rSb6OWet) for detailed instructions on how to register your validator, add admins, and gain access to creating Lockups.

After a Lockup is created and issued onchain, it cannot be deleted and will run until maturity, however Validators will be able to toggle visibility of the lockups between public and private.

<details>

<summary>STEP 1:  Lockup Parameters</summary>

* Go to <https://app.pye.fi/>
* Navigate to the `/Create Lockup` tab
* Input the following parameters:
  * **Single Depositor (optional):** Whitelist a single depositor address that will be able to deposit into the Lockup.
  * **Lockup Duration**: Date/time when the lockup ends (eg. 3m, 1yr into the future), also referred to as "maturity".
  * **Deposits Start**: Date/time when stakers can begin depositing SOL or stake.
  * **Deposits End:** Date/time when stakers may no longer deposit.

Notes:

* **Validator Vote Key: No need to enter this, it will auto-populate after whitelisting.**

</details>

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/j5Ns5jQJUfEdd1FwwtEp/Screenshot%202026-01-17%20at%208.23.41%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

<details>

<summary>STEP 2: Commission Structure</summary>

Pye allows validators to set custom commission for each reward source:

* **Inflation Commission**: The % of inflation the validator keeps.
* **MEV Commission:** The % of MEV the validator keeps.
* **Block Rewards Commission:** The % of block rewards the validator keeps.

For more information visit our [technical specification section](broken://pages/aOjs4gC5WzIpifbjuGsn).

</details>

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/0cxqXOnCpqq47kmGyEyz/Screenshot%202025-09-12%20at%202.48.24%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

<details>

<summary>STEP 3: Review Token Details</summary>

* The symbol and metadata URI are autogenerated.
* Please review the symbols for both the PT and RT tokens and make sure the dates are correct.

Note: Stake Accounts get tokenized via the issuance of SPL tokens representing the principal and rewards of the account.

</details>

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/JkomPHlJb5JvPwrs65D6/Screenshot%202026-01-17%20at%208.26.04%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>

<details>

<summary>Step 4: Sign TX in wallet</summary>

* Confirm your transaction in the notification window of your wallet

</details>

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/SUS16dsViDWU3EiCwTpw/Screenshot%202026-01-17%20at%208.30.29%E2%80%AFPM.png" alt="" width="265"><figcaption></figcaption></figure>

<details>

<summary>Step 5: Share Link to new Lockup page</summary>

Congratulations, you have now issued a Lockup.To share the Lockup directly with your stakers for deposit:

* Copy the generated link URL and share.

</details>

<figure><img src="https://content.gitbook.com/content/j4UC7QTpb7zf4JXXnPJl/blobs/8U08tqQ0puhBYhS3w3Ii/Screenshot%202026-01-17%20at%208.10.21%E2%80%AFPM.png" alt=""><figcaption></figcaption></figure>


# Custom Commissions CLI

Offer stakers custom commission structures outside your public on-chain commission.

The following is a step-by-step guide for Solana validators to set up and run the Pye CLI for automated rewards distribution to Programmable Stake Account (PSA) lockups.

**Repository:** [github.com/pyefi/pye-cli-2](https://github.com/pyefi/pye-cli-2)

**Estimated Setup Time Required:** 15-20 minutes

{% embed url="<https://www.loom.com/share/80e907b740dc4d0e9809314a7a153309>" %}

### How it Works

The Pye CLI automates the settlement of excess rewards owed to stakers under custom commission terms. The CLI runs as a long-lived daemon that:

1. Fetches pending reward payments for your organization from the Pye backend
2. Calculates the excess owed to each staker (what they’re entitled to minus what they already received)
3. Batches and submits SOL transfers on-chain (up to 50 per transaction) through payer wallet. If payer wallet runs out of funds it will automatically backfill appropriate payments
4. Sleeps for a configurable interval, then repeats

The CLI never modifies your vote account, withdrawer keys, or node configuration. It only reads reward data from the Pye API and sends SOL transfers from a dedicated payer wallet. It is completely free.

### Prerequisites

* **Pye API key** — sign in to the [Pye Dashboard](https://app.pye.fi/), create an organization and complete verification, then navigate to **Custom Commissions** and generate an API key
* **Dedicated server** — a small EC2 instance (e.g. `t3.micro` with 2 vCPUs, 1 GB RAM) or equivalent is sufficient, however we recommend 2GB+ RAM to ensure no issues during package installation. The CLI is lightweight (\~5 MB memory) and makes minimal RPC calls.
* **Rust toolchain** — edition 2024 compatible (rustc 1.85+)
* **Solana CLI tools** — for keypair generation (`solana-keygen`)
* **Payer wallet** — a Solana filesystem keypair funded with SOL (see [Payer Wallet Setup](about:blank#payer-wallet-setup))
* **Stable internet** — the CLI must reach both the Solana RPC endpoint and the Pye API

> **Important:** Run only one instance of the CLI per organization. Multiple simultaneous instances are not supported and may result in duplicate transfers.

### Quick Reference

For experienced users who want the commands without the explanation:

```bash
# Install deps & Rust
sudo apt-get update && sudo apt-get install -y build-essential pkg-config libssl-dev
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"

# Build
git clone https://github.com/pyefi/pye-cli-2.git
cd pye-cli-2
cargo build --release

# Generate Payer Keypair
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"                                                      
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"                                           
solana-keygen new --outfile /home/ubuntu/keypair.json                                                                         
chmod 600 /home/ubuntu/keypair.json                                                   

# Configure
cat > /home/pye/.env <<EOF
PAYER=/home/ubuntu/keypair.json
PYE_API_KEY=your-api-key-here
RPC_URL=https://api.mainnet-beta.solana.com
RUST_LOG=info
EOF

# Run
./target/release/pye-cli validator-lockup-manager

# Setup systemd 
sudo tee /etc/systemd/system/pye-cli.service > /dev/null <<EOF                                                     
[Unit]                                                                                                             
Description=Pye CLI V2 — Validator Lockup Manager
After=network.target                                                                                               
                                                                                                                     
[Service]                                                                                                          
Type=simple                                                                                                        
User=ubuntu                                                                                                        
Group=ubuntu                                                                                                       
WorkingDirectory=/home/ubuntu/pye-cli-2                                                                            
ExecStart=/home/ubuntu/pye-cli-2/target/release/pye-cli validator-lockup-manager                                   
EnvironmentFile=/home/ubuntu/.env                                                                                  
Restart=on-failure                                                                                                 
RestartSec=30                                                                                                      
                                                                                                                     
[Install]                                                                                                          
WantedBy=multi-user.target                                                                                       
EOF
                                                                                                                     
cp ~/pye-cli-2/.env ~/.env                                                                                         
chmod 600 ~/.env                                                                                        
sudo systemctl daemon-reload                                                                                       
sudo systemctl enable pye-cli                                                                                      
sudo systemctl start pye-cli     
```

See the sections below for detailed instructions, systemd setup, and troubleshooting.

### Installation

#### 1. Install system dependencies (Ubuntu/Debian)

```bash
sudo apt-get update && sudo apt-get install -y build-essential pkg-config libssl-dev
```

> If you are running a different Linux distribution, install the equivalent packages for your platform (`gcc`, `make`, `pkg-config`, and OpenSSL development headers).

#### 2. Install Rust

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
```

#### 3. Clone and build

```bash
git clone https://github.com/pyefi/pye-cli-2.git
cd pye-cli-2
cargo build --release
```

The binary is at `target/release/pye-cli`.

> The first build downloads and compiles all dependencies. On a `t3.micro` this takes approximately 8-10 minutes. You will see one compiler warning about unreachable code — this is expected and does not affect functionality.

To update to a newer version later:

```bash
cd pye-cli-2
git pull origin master
cargo build --release
sudo systemctl restart pye-cli
```

#### 4. Verify installation

```bash
./target/release/pye-cli --version
```

You should see output ending with `pye-cli 2.0.0` (or later). A JSON log line may appear before the version — this is normal and can be ignored.

### Payer Wallet Setup

The payer wallet is the Solana account that **funds all excess reward transfers** to lockup accounts. This is not just a fee payer — the actual SOL for reward distributions is sent from this wallet. Keeping it funded is critical to the CLI’s operation.

#### Create a keypair

Install the Solana CLI tools if you don’t already have them:

```bash
sh -c "$(curl -sSfL https://release.anza.xyz/stable/install)"                                                      
export PATH="$HOME/.local/share/solana/install/active_release/bin:$PATH"           
```

Generate a new keypair for the payer wallet:

```bash
solana-keygen new --outfile /home/pye/keypair.json
```

Restrict file permissions:

```bash
chmod 600 /home/pye/keypair.json
```

Note the public key in the output — this is the address you will fund with SOL.

#### Fund the wallet

Transfer SOL to the payer wallet’s public key from your existing wallet or exchange. You can verify the balance with:

```bash
solana balance /home/pye/keypair.json --url https://api.mainnet-beta.solana.com
```

#### How much SOL to hold

The payer wallet needs enough SOL to cover:

* **Reward transfers** — the total excess rewards owed to all lockups each cycle. This depends on the number of lockups, their stake amounts, and the commission terms.
* **Transaction fees** — a small amount (\~0.000005 SOL per transaction, batched at up to 50 transfers per transaction).

You can fund the wallet with as much as you are comfortable with to cover payouts into the future. As a starting recommendation, fund the wallet with enough SOL to cover at least 10 epochs of expected reward payouts. As soon as the payer has under 3 epochs left an automated 'low balance' alert email will be sent out. Monitor the balance regularly and top up before it runs low — if the wallet has insufficient funds, transfers will fail. However as soon as funds are topped up, the CLI will backfill and payout all outstanding payments in the past. You can top up funds through the Validator dashboard UI or by sending it to the payer keypair directly (obtained during setup).

### Configuration

All options can be set via CLI flags or environment variables. Environment variables are recommended for production deployments.

#### Required

| Variable      | Flag            | Description                                  |
| ------------- | --------------- | -------------------------------------------- |
| `PAYER`       | `--payer`       | Absolute path to the payer keypair JSON file |
| `PYE_API_KEY` | `--pye-api-key` | Your organization’s Pye API key              |

#### Optional

| Variable     | Flag           | Default                               | Description                                              |
| ------------ | -------------- | ------------------------------------- | -------------------------------------------------------- |
| `RPC_URL`    | `--rpc-url`    | `https://api.mainnet-beta.solana.com` | Solana RPC endpoint                                      |
| `API_URL`    | `--api-url`    | Pye production API                    | Pye backend URL (do not change unless instructed)        |
| `CYCLE_SECS` | `--cycle-secs` | `60`                                  | Seconds between polling cycles                           |
| `RUST_LOG`   | —              | `info`                                | Log verbosity: `error`, `warn`, `info`, `debug`, `trace` |

#### Environment file

Create a `.env` file in the same directory as the binary (or wherever you run the CLI from):

<pre class="language-bash"><code class="lang-bash"><strong>cd ~/pye-cli-2 
</strong><strong>
</strong><strong>cat > /home/pye/.env &#x3C;&#x3C;EOF
</strong>PAYER=/home/ubuntu/keypair.json
PYE_API_KEY=your-api-key-here
RPC_URL=https://api.mainnet-beta.solana.com
RUST_LOG=info
EOF
</code></pre>

The CLI loads `.env` from the current working directory on startup. When running via systemd, use the `EnvironmentFile` directive instead (see [Production Deployment](about:blank#production-deployment)).

### Usage

#### `validator-lockup-manager`

Runs continuously as a daemon, polling the Pye API and automatically distributing excess rewards.

```bash
pye-cli validator-lockup-manager \\
  --payer /home/pye/keypair.json \\
  --pye-api-key your-api-key
```

**Behavior:**

* Polls the Pye backend API every `-cycle-secs` seconds (default: 60) to check for pending reward payments
* The polling interval controls how often the CLI *checks* — it does not mean transfers happen every 60 seconds. The Pye backend determines when payments are ready (typically once per epoch after reward data is aggregated). If no payments are pending, the cycle is a no-op.
* For each payment where the expected amount exceeds the base amount, creates a SOL transfer to the lockup account
* Batches up to 50 transfer instructions per Solana transaction
* Transfers execute automatically with no confirmation prompt
* On failure, logs the error and continues to the next cycle without crashing

### Production Deployment

#### systemd service

Create the service file:

```bash
sudo tee /etc/systemd/system/pye-cli.service > /dev/null <<EOF
[Unit]
Description=Pye CLI V2 — Validator Lockup Manager
After=network.target

[Service]
Type=simple
User=pye
Group=pye
WorkingDirectory=/home/ubuntu/pye-cli-2
ExecStart=/home/ubuntu/pye-cli-2/target/release/pye-cli validator-lockup-manager
EnvironmentFile=/home/pye/.env
Restart=on-failure
RestartSec=30

[Install]
WantedBy=multi-user.target
EOF
```

Create the environment file:

```bash
sudo tee /home/ubuntu/.env > /dev/null <<EOF
PAYER=/home/ubuntu/keypair.json
PYE_API_KEY=your-api-key-here
RPC_URL=https://api.mainnet-beta.solana.com
RUST_LOG=info
EOF
sudo chmod 600 /home/ubuntu/.env
```

Enable and start:

```bash
sudo systemctl daemon-reload
sudo systemctl enable pye-cli
sudo systemctl start pye-cli
```

#### Monitoring

View live logs:

```bash
journalctl -u pye-cli -f
```

Logs are in JSON format (designed for CloudWatch ingestion). Example output:

```json
{"level":"INFO","fields":{"message":"handle_payments_to_be_sent: Payments: 12"}}
{"level":"INFO","fields":{"message":"Transaction sent successfully: 4xK9...mR2v"}}
{"level":"ERROR","fields":{"message":"PyeApiError: Status Code 401 Message: API Key not found"}}
```

Log entries include:

* Payment fetch results and counts
* Transaction signatures on successful transfers
* Errors encountered during processing

Check service status:

```bash
systemctl status pye-cli
```

### Reward Calculation

For each pending payment, the Pye backend computes the excess reward across all three reward streams (inflation, MEV tips, and block rewards) and returns pre-aggregated values. The CLI then calculates:

```
transfer_amount = expected_amount - base_amount
```

* **`expected_amount`** = what the staker is entitled to under their custom commission terms
* **`base_amount`** = what the staker already received through normal Solana staking mechanics
* If the transfer amount is zero, no transfer is made for that payment
* Transfers are batched at 50 instructions per Solana transaction to stay within compute limits

### Migrating from V1 to V2

*Skip this section if you are setting up the CLI for the first time.*

<details>

<summary>Migration Guide</summary>

V2 is a fundamentally different architecture. The V1 CLI was a heavy client that computed everything locally — it deserialized on-chain Pye accounts via Anchor, queried Jito’s MEV API directly, walked RPC slots to calculate block rewards, and reported metrics to InfluxDB. V2 replaces all of that with a single API call to the Pye backend, which now handles reward aggregation server-side. This means V2 has no Anchor dependency, no Jito integration, no on-chain account parsing, and no InfluxDB metrics. The result is a simpler binary with far fewer runtime dependencies and RPC calls.

#### When to migrate

The best time to migrate is **right after an epoch boundary, once V1 has finished processing the previous epoch’s rewards**. Watch the V1 logs (`journalctl -u pye-cli -f`) and wait for a clean sleep interval — do not stop V1 while it is actively submitting transactions. There is no risk of duplicate payments: the Pye backend tracks which payments have been sent, so V2 will only pick up pending payments that V1 has not already processed.

#### Step-by-step migration

**1. Stop the CLI and disable V1**

Wait for V1 to complete its current cycle, then stop it:

```bash
journalctl -u pye-cli -f   # watch for cycle completion, then Ctrl+C
sudo systemctl stop pye-cli
sudo systemctl disable pye-cli
```

**2. Contact Pye Team**

Let the Pye team know that you are migrating so that we can reset and remove payments already completed.

**3. Install and start using CLI V2**

Clone the new repository and build:

```bash
git clone <https://github.com/pyefi/pye-cli-2.git>
cd pye-cli-2
cargo build --release
```

**3. Obtain your API key**

V2 authenticates via an organization-scoped API key instead of a vote pubkey + issuer list. Your API key is provided during onboarding. If you haven’t received one, contact the Pye team.

**4. Update your environment file**

V1 environment:

```bash
# V1 — remove these
RPC=https://api.mainnet-beta.solana.com
PAYER=/home/pye/keypair.json
VOTE_PUBKEY=YourVoteAccountPubkey
ISSUERS=Issuer1,Issuer2
CONCURRENCY=50
BLOCK_RETRY_DELAY=1800
DRY_RUN=false
```

V2 environment:

```bash
# V2 — replace with these
RPC_URL=https://api.mainnet-beta.solana.com
PAYER=/home/pye/keypair.json
PYE_API_KEY=your-api-key-here
RUST_LOG=info
```

Note: `RPC` has been renamed to `RPC_URL`. The `VOTE_PUBKEY`, `ISSUERS`, `CONCURRENCY`, `BLOCK_RETRY_DELAY`, and `DRY_RUN` variables are no longer used and should be removed.

**5. Update your systemd unit file**

Replace the `ExecStart` line and `EnvironmentFile` path:

```bash
sudo tee /etc/systemd/system/pye-cli.service > /dev/null <<EOF
[Unit]
Description=Pye CLI V2 — Validator Lockup Manager
After=network.target

[Service]
Type=simple
User=pye
Group=pye
WorkingDirectory=/home/pye/pye-cli-2
ExecStart=/home/pye/pye-cli-2/target/release/pye-cli validator-lockup-manager
EnvironmentFile=/home/pye/.env
Restart=on-failure
RestartSec=30

[Install]
WantedBy=multi-user.target
EOF
```

**6. Start V2**

```bash
sudo systemctl daemon-reload
sudo systemctl enable pye-cli
sudo systemctl start pye-cli
journalctl -u pye-cli -f   # verify it starts cleanly
```

#### What changed

| Aspect                    | V1                                                         | V2                                                            |
| ------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------- |
| **Repository**            | `pyefi/pye-cli` (workspace)                                | `pyefi/pye-cli-2` (single crate)                              |
| **Solana SDK**            | v2                                                         | v3                                                            |
| **Reward computation**    | Local — Anchor deserialization, Jito API, RPC slot walking | Server-side — single Pye API call returns pre-computed values |
| **On-chain dependencies** | Anchor, `pye-core-cpi` library                             | None                                                          |
| **Metrics**               | `solana-metrics` (InfluxDB datapoints)                     | `tracing` (JSON logs for CloudWatch)                          |
| **Validator identity**    | `--vote-pubkey` + `--issuers` flags                        | Organization API key                                          |
| **Commands**              | `validator-pye-account-manager`, `transfer-excess-rewards` | `validator-lockup-manager`                                    |
| **Concurrency**           | `--concurrency` flag (parallel RPC)                        | Sequential batching (50 instructions/TX)                      |
| **Dry run**               | `--dry-run` flag                                           | Removed                                                       |
| **Error handling**        | Panics on most errors                                      | Logs errors and continues to next cycle                       |

#### Removed flags

The following V1 flags have no V2 equivalent:

* `-vote-pubkey` / `VOTE_PUBKEY` — the Pye backend identifies your validators from your API key
* `-issuers` / `ISSUERS` — lockup filtering is now handled server-side
* `-program-id` / `PROGRAM_ID` — V2 does not interact with on-chain Pye program accounts
* `-concurrency` / `CONCURRENCY` — V2 makes minimal RPC calls; no parallel request tuning needed
* `-block-retry-delay` / `BLOCK_RETRY_DELAY` — block reward calculation is now server-side
* `-dry-run` / `DRY_RUN` — removed in V2

</details>

### Troubleshooting & FAQ

<details>

<summary><strong>CLI exits with <code>ReadKeypairError</code></strong> </summary>

The payer keypair file path is invalid or the file is not readable. Verify the path and file permissions (`chmod 600`).

</details>

<details>

<summary><strong>Build fails or takes too long</strong></summary>

On `t3.micro` (1 GB RAM), the build may appear stuck or freeze during compilation of large crates like `rustls` or `brotli`. This is usually caused by the system running out of memory. Add swap space and retry — the build will resume where it left off:

```bash
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
cargo build --release
```

After the build completes, remove the swap file to reclaim disk space — the default 8 GB root volume is tight once build artifacts and Solana CLI tools are installed:

```bash
sudo swapoff /swapfile
sudo rm /swapfile
```

Alternatively, launch the instance with a 16 GB root volume to avoid space issues entirely and 2GB RAM to avoid issues with crate installation. The initial build takes \~8-10 minutes on a `t3.micro`. Subsequent builds after code changes are faster since dependencies are cached.

</details>

<details>

<summary><strong>Are there risks of duplicate transfers?</strong></summary>

There is a risk if you are running multiple CLIs or versions of the CLI. Ensure only one instance of the CLI is running per organization. Check with `systemctl status pye-cli` and `ps aux | grep pye-cli`.

</details>

<details>

<summary><strong><code>SolanaClientError</code> or RPC errors</strong></summary>

&#x20;The CLI could not communicate with the Solana RPC endpoint. Verify your `RPC_URL` is correct and reachable. If using the public mainnet RPC, note that it has rate limits — consider using a dedicated RPC provider for production.

</details>

<details>

<summary><strong>Transfers are not being made</strong></summary>

Check that the payer wallet has sufficient SOL to cover both the reward transfer amounts and transaction fees. The payer wallet is the source of all SOL sent to lockup accounts — not just fees. Top up the wallet and re-run or wait for the next cycle.

</details>

<details>

<summary><strong><code>ReqwestError: error sending request for url</code></strong></summary>

&#x20;The CLI could not reach the Pye backend API. Check that the server has outbound internet access and DNS resolution is working. You can test connectivity with: `curl -s <https://gwtgzlzfnztqhiulhgtm.supabase.co`>. If using a firewall or security group, ensure HTTPS (port 443) outbound traffic is allowed.

</details>

<details>

<summary><strong><code>PyeApiError</code> with “API Key not found”</strong></summary>

Your API key is invalid, expired, or not yet provisioned. Verify `PYE_API_KEY` is set correctly. If the issue persists, contact the Pye team to confirm your key is active.

</details>

<details>

<summary>For CLI users, are there any other consequence if the node is down outside epoch changes?</summary>

Yes. CLI v1 depends on the RPC node and Jito’s API. It requires knowing the active stake for the **previous epoch** to calculate rewards correctly.

There is no way to determine active stake for `current_epoch - 2`. This means missing epochs can result in unrecoverable reward calculation gaps.

There is a separate CLI command that allows calculating rewards for `current_epoch - 1`. If the CLI is started with the long-running manager command, you would want to use the transfer command and then restart the manager to wait for the next boundary.

</details>

<details>

<summary>For CLI users, how many epochs should avoid being missed? What happens to rewards for missed epochs?</summary>

You should avoid missing **any** epoch. If you miss an epoch and were supposed to pay lamports to a Lockup, the UI will highlight this error.

Currently there is no harsh protocol penalty — mostly social consequences. However, there has been exploration into allowing stakers to early-withdraw if payments are missed for a certain number of epochs.

Because stakers are locked up, you can make good on the payment in `epoch + 2` (as long as it’s before maturity). Stakers are still rewarded, but they may miss out on **compounding** for the missed epoch.

</details>

<details>

<summary>For CLI users, does the CLI need to be online at the exact moment of the epoch boundary? What happens if we need to reboot the server for maintenance.</summary>

There are two commands in CLI v1 (v0.1.3):

* **`validator-pye-account-manager`**
  * Long-running process
  * Waits for the *next* epoch boundary
  * If started late, it does **not** backfill missed epochs
* **`transfer-excess-rewards`**
  * One-shot command
  * If run in epoch `N`, it calculates rewards for epoch `N-1` and executes the transfer

**Safe timing considerations:**

* Avoid rebooting in the first \~12 hours after an epoch boundary
* MEV data (e.g., from Jito) can take hours to populate
* The middle of the epoch is safest

The lockup Payment Tracker uses checkpoint-based recovery, so **no data is missed after restarts**.

**Practical recommendation:**\
Schedule maintenance mid-epoch (≈ 1–1.5 days after epoch start).

</details>

<details>

<summary>For CLI users, does the CLI Hot Wallet (used for distributing rewards) need to be whitelisted/registered on-chain, or is it simply a funding source for gas/transactions? If it's just a funding source, can we rotate this wallet periodically without protocol interaction?</summary>

Yes — it is purely a funding source and can be rotated periodically **without protocol interaction**. This operation is done off-chain.

</details>

<details>

<summary>For CLI users, is it tied to an IP or can we run it again on a new server if it goes down for any reason?</summary>

CLI v1 was built without dependencies on Pye’s backend.

There are no IP restrictions other than:

* The RPC node being used
* Jito’s MEV API (currently no IP restrictions)

There is ongoing exploration into using durable nonces to mitigate double-spend risks if multiple instances are run simultaneously.

</details>

<details>

<summary>For CLI users of CLI V1, will migrating to CLI V2 break the V1 integration?</summary>

No, it won’t break it. It’s a completely separate code base and you can continue to use V1 if you so choose.

If you choose to migrate to V2, you will need to schedule a maintenance window in-between epochs to spin down V1 and spin up V2. At the next epoch boundary V2 will make the 1st payment.

Migration to V2 is straightforward, any node operator should have no issues running the commands to spin V2 up. From a state transition perspective, the important thing to understand is that V1 CLI is is winded down during this maintenance window and that the V2 CLI is spun up and will fund the next epoch payments.

</details>

<details>

<summary>For CLI users, how heavy are the RPC request costs?</summary>

It is efficiently written to reduce RPC calls. The two areas where it uses a decent amount of RPC calls is getting the block metadata where your validator was the leader and polling for the epoch boundary. The concurrency of get\_block calls can be limited by the —currency CLI argument. The epoch polling frequency can be adjusted via the —cycle-secs CLI argument.

For a single iteration (one epoch):

Total RPC Calls ≈

I # get\_program\_accounts (per issuer)

* (0 or 1) # get\_multiple\_accounts (if allow\_post\_maturity)
* (slots\_remaining / cycle\_secs) # get\_epoch\_info during wait
* 4 # get\_block\_time, get\_vote\_accounts, get\_leader\_schedule, get\_account(SlotHistory)
* B # get\_block (based on validator's blocks in epoch)
* P \* (3 to 6) # per pye\_account stake fetching
* P \* (1 to 2) # per pye\_account inflation reward
* T \* 2 # transfers (T = accounts with excess rewards, if not dry\_run)

Typical Example for a validator with:

* 1 issuer
* 500 blocks produced in the epoch
* 5 active pye accounts (no transient accounts)
* Not dry\_run, all 5 have excess rewards

≈ 1 + 100 + 4 + 500 + (5 \* 3) + (5 \* 1) + (5 \* 2)

≈ 1 + 100 + 4 + 500 + 15 + 5 + 10

≈ 635 RPC calls per iteration

</details>


# Buyers & Traders

Trading is currently in a closed beta with select users having access.

{% hint style="info" %}
The Pye orderbook is in early access. Sign up to the [waitlist](https://app.pye.fi/) to get early access trading.
{% endhint %}

## Who Buys on Pye

When a staker is selling their Principal Tokens (PT) or Reward Tokens (RT), there is a buyer on the other side of the trade, someone purchasing the staking rewards (RT) or locked principal (PT) at a discount.

Buyers on Pye are typically traders and SOL accumulators who want exposure to Solana rewards without running a validator or managing a stake account. They are directionally long on SOL and looking for better entry points or fixed returns over a defined time horizon.

There are two things to buy on the orderbook:

* **Principal Tokens (PT):** buy SOL at a discount, redeem 1:1 at maturity
* **Reward Tokens (RT):** buy the right to staking rewards from a specific validator until maturity

All Pye markets trade to SOL. Whether you're buying PTs or RTs, your return is denominated in SOL, so you always have a clear picture of how much SOL you're accumulating.

***

## The Core Incentive

Solana's annualized staking rewards typically run in the range of 4–7%. If you can buy PT or RT tokens at a discount greater than that, you are acquiring SOL more efficiently than simply staking. This is the clearest reason to buy on Pye: it is a direct, measurable improvement over holding or staking SOL passively.

***

## Buying SOL at a Discount (PT)

A PT is a claim on 1 SOL, redeemable at a fixed maturity date. Because it is a future asset traded today, it prices at a discount.

Buying a PT is a straightforward fixed-return trade: you pay less than 1 SOL today and receive exactly 1 SOL at maturity. The difference is your return locked in at the time of purchase, regardless of what happens to staking rates between now and maturity.

This is the lower-risk side of Pye. PT value is not affected by validator performance, MEV, or priority fee changes. It moves toward par as maturity approaches.

PTs are also safe from validator risk. Because they are wrapped in a tokenized stake account and represent the principal only, PT holders always redeem 1:1 for SOL at maturity, even if the validator goes offline before the maturity date. This makes PTs easier to price and understand than RTs, and the lower risk profile means they trade at a tighter discount.

{% hint style="success" %}
**Who this is for:** Traders who want to accumulate SOL at a discount with a defined time horizon, minimal variable exposure, and no validator risk.
{% endhint %}

***

## Buying Discount Staking Rewards (RT)

An RT is a claim on all staking rewards: inflation, MEV, and priority fees where shared, generated by a staked position until maturity. You don't own the underlying SOL. You own its productivity.

RT pricing is based on projected epoch-by-epoch rewards from deposit to maturity. Inflation forms the stable baseline. MEV and priority fees are variable and can increase RT value meaningfully depending on network conditions and how much a validator shares back to stakers.

RTs trade at a further discount than PTs because the return is variable and not guaranteed.

{% hint style="success" %}
**Who this is for:** Traders who want direct exposure to Solana staking rewards, want to speculate on validator performance, want to hedge SOL exposure without selling, or are looking for predictable ways to purchase SOL below spot market prices.
{% endhint %}

***

## Use Case: Accumulating SOL at a Better Entry Point

A buyer who is directionally long on SOL can use PTs to effectively dollar-cost average into SOL at a discount. Instead of buying 1 SOL at market price, they buy a PT for 0.93 SOL and receive 1 SOL at maturity, a 7% better entry point with no price risk on the underlying.

The trade is: give up liquidity for the maturity period in exchange for a guaranteed better entry.

***

## Use Case: Hedging SOL Exposure via RTs

A trader holding a large SOL position can buy RTs to gain additional SOL-denominated rewards exposure without adding to their spot position. RTs are high-beta to staking conditions, if MEV spikes or a validator starts sharing priority fees, RT holders benefit directly.

Conversely, a validator or large staker can sell RTs to lock in a fixed SOL amount today, transferring variable rewards risk to the buyer.

***

## How to Trade

All PT and RT transactions settle on Pye's on-chain orderbook. There are two order types:

**Limit orders:** place an order against a specific validator market at your target rate. Fills when a matching seller appears.

**Market orders:** fill immediately at the best available rate in a given market.


# Markets & Orderbook

How PT and RT markets are structured, created, and traded across validators on Pye.

{% hint style="info" %}
The Pye orderbook is in early access. Sign up to the [waitlist](https://app.pye.fi/) to get early access trading & the Pye Exchange.
{% endhint %}

Markets are created and managed on an onchain orderbook is the on-chain trading layer where all PT and RT transactions are matched and settled. Every deposit made through Pye routes through the orderbook.&#x20;

**Order types:**

* **Limit orders:** orders placed against a specific validator or LST market at a target rate. Fills when a matching counterparty appears.
* **Market orders:** fill immediately at the best available rate in a given market.

The orderbook accepts lockups that are aligned with the following fixed maturities schedule for 2026:

| Month     | Date         | Maturity (UTC) | Issuance Start | Issuance Close |
| --------- | ------------ | -------------- | -------------- | -------------- |
| June      | Jun 30, 2026 | `1751327940`   | `1738368000`   | `1751155140`   |
| September | Sep 30, 2026 | `1759276740`   | `1738368000`   | `1759103940`   |
| December  | Dec 31, 2026 | `1767225540`   | `1738368000`   | `1767052740`   |


# Fees & Economics

How Pye generates revenue and what fees participants pay on the platform.

## How Fees Work

Pye generates revenue through trading fees on the orderbook. Speedstake is free for validators. There are no fees to deposit or mint tokens.


# Points & Beta

More information will be released in the future.


# Glossary

Key terms and concepts you'll encounter when using Pye.

## Orderbook

Pye's on-chain trading layer where all Principal Token and Reward Token transactions are matched and settled. Every deposit made through Pye, whether via Speedstake or directly, routes through the orderbook. Buyers set limit orders at their target discount rate; stakers fill those orders when terms match. The orderbook supports individual limit and market orders.

## Speedstake

An [embeddable](/validators/speedstake) app that allows stakers to sell their future rewards and receive SOL immediately — without knowing about trading or navigating the Pye Exchange. Speedstake is the primary entry point for stakers and can be hosted as a standalone page or embedded directly on a validator's website. All transactions settle on Pye's orderbook.

## Discount Rate

The percentage below face value at which a Principal Token or Reward Token is priced. A staker selling future rewards at a 7% discount receives SOL today in exchange for forfeiting that 7% over the maturity period. For buyers, the discount represents their return.

## Maturity

The [date](/how-pye-works#fixed-maturities) on which [Principal](/how-pye-works#principal-tokens-pt) and [Reward](/how-pye-works#reward-tokens-rt) tokens expire and can be redeemed for SOL. Pye uses fixed quarterly maturities aligned to end-of-quarter dates. All markets on the platform share the same maturities to avoid liquidity fragmentation.

## Programmable Stake Account (PSA)

Pye's underlying [primitive](/how-pye-works#the-core-mechanism). A time-locked stake account that accepts SOL or existing stake accounts as deposits and splits them into PT and RT tokens. When paired with the Pye CLI, validators can use PSAs to issue custom commission structures to stakers beyond what is publicly set on-chain.

## Principal Token (PT)

A [token](/how-pye-works#principal-tokens-pt) representing the underlying SOL deposit, redeemable 1:1 at maturity. PTs earn no staking rewards — they are the "principal only" side of a split position. Because they are future assets traded today, they trade at a discount. Buying a PT is effectively locking in a fixed return on SOL.

## Reward Token (RT)

A [token](/how-pye-works#reward-tokens-rt) representing the right to all staking rewards generated by a staked position until maturity — including inflation, MEV, and priority fees (where shared by the validator). RTs do not include the underlying SOL principal. They are the rewards-only side of a split position.

## Whitelisted Validator

Validators must register with Pye before appearing on the platform. Registration gives validators access to all Pye features - Speedstake, marketplace listing, and CLI.

## Lockup

The fixed period during which a staker's SOL remains delegated to a validator through Pye. When a staker deposits into a Programmable Stake Account, their position is locked until a fixed date (default is set to quarterly maturity dates to concentrate liquidity). The [lockup](/validators/validator-dashboard/create-a-lockup) cannot be exited early by unstaking — but the PT and RT tokens representing that position can be sold on the orderbook at any time before maturity.

## Custom Commission CLI

A [command-line tool](/validators/validator-dashboard/custom-commissions-cli) that allows whitelisted validators to offer stakers custom commission structures outside of their public on-chain commission. Using the CLI, validators can set separate rates for inflation, MEV tips, and priority fees — specified in basis points — for specific stake accounts and lockup durations. This enables validators to offer differentiated terms to larger or longer-duration stakers without changing their public vote account commission. The CLI connects to the Validator Dashboard and handles reward calculation and distribution each epoch automatically.


# Products

The four core products that power the Pye ecosystem.

Pye is made up of four core products that work together. Each can be used independently, but they are designed to connect, Speedstake feeds the orderbook, the PSA underpins both, and the CLI and dashboard give validators a mechanism to create and manage new customizable stake products to retain and attract new stake.

***

## Speedstake

Speedstake is the primary entry point for stakers. It is an embeddable app that lets stakers sell their future rewards and receive SOL immediately, without navigating the full orderbook.

**What it does:**

* Accepts liquid SOL or staked SOL as deposits
* Detects existing staked positions automatically on wallet connect for whitelisted validators
* Lets stakers select a maturity date and deposit amount
* Checks available orderbook liquidity before the staker signs
* Executes the transaction and delivers SOL immediately

{% hint style="info" %}
You must be whitelisted by Pye first.  All transactions route through Pye's orderbook. Speedstake is free for whitelisted validators.
{% endhint %}

***

## Pye Exchange

The Pye Exchange is the on-chain trading layer where all PT and RT transactions are matched and settled. Every deposit made through Pye routes through the orderbook.

**Order types:**

* **Limit orders** — orders placed against a specific validator market at a target rate. Fills when a matching counterparty appears.
* **Market orders** — fill immediately at the best available rate in a given market.

All markets on the orderbook trade to SOL, so buyers always have a clear view of how much SOL they are accumulating regardless of which validator or market they are trading.

***

## Validator Dashboard

The Validator Dashboard is the management interface for validators on Pye. It handles everything from initial org setup to day-to-day lockup management — no new node, no changes to your existing vote account.

**What it includes:**

* Organization setup and validator registration
* Lockup creation — public vaults open to any staker, or private vaults scoped to specific wallet addresses
* Optional deposit caps for time-limited or promotional lockups
* Real-time TVL tracking across all active lockups
* Role-based permissions for teams managing multiple nodes
* CLI status monitoring for validators running custom commission distributions

Access the Validator Dashboard at [dashboard.pye.fi](https://dashboard.pye.fi) (must be whitelisted to add nodes).


# Risks & Security

The following is a non-exhaustive list of plausible security considerations & audits

***

## Audits

<table><thead><tr><th>Auditor</th><th>Version</th><th width="148.06640625">Date</th><th>Type</th><th>PDF</th></tr></thead><tbody><tr><td>Zellic</td><td>Pye V1</td><td>January 23, 2025</td><td>Security Review</td><td><a href="https://github.com/pyefi/security/blob/master/security_audits/zellic_january_2025_core_v1.pdf">Zellic Report</a></td></tr><tr><td>Sec3</td><td>Pye V1</td><td>March 19, 2025</td><td>Security Review</td><td><a href="https://github.com/pyefi/security/blob/master/security_audits/sec3_march_2025_core_v1.pdf">Sec3 Report</a></td></tr><tr><td>Neodyme</td><td>Pye V2</td><td>June 5, 2025</td><td>Security Review</td><td><a href="https://github.com/pyefi/security/blob/master/security_audits/neodyme_june_2025_core_v2.pdf">Neodyme Report</a></td></tr><tr><td>Sec3</td><td>Pye V2</td><td>November 2025</td><td>Security Review</td><td><a href="https://github.com/pyefi/security/blob/master/security_audits/sec3_november_2025_core_v2.pdf">Sec3 Report</a></td></tr><tr><td>Neodyme</td><td>Pye V2 (revised)</td><td>November 2025</td><td>Security Review</td><td><a href="https://github.com/pyefi/security/blob/master/security_audits/neodyme_novemember_2025_core_v2_revision.pdf">Neodyme Report</a></td></tr></tbody></table>

## Validator Going Offline

If a validator ceases operations before a maturity date, RT payments will stop. Any rewards accrued up to that point are safe and redeemable. Your PT is unaffected — it always redeems 1:1 for SOL at maturity. **Solana does not have slashing.**

{% hint style="warning" %}
Do your own research before choosing a validator or buying their rewards. Pye conducts due diligence before listing but does not have visibility into individual validator operations or financials.
{% endhint %}

***

## Commission Changes

Validators can change their commission structures over time. If a validator reduces what they share back to stakers, RTs on that market may be worth less than projected.

Review a validator's historical commission behavior before buying their RTs.

***

## Smart Contract Risk

Pye's official audit reports and verifications from independent security companies. Security is engineered into the protocol through a non-custodial architecture that ensures no one can ever take possession of validator identity or withdrawer keys. Instead, the system functions as a transparent wrapper on top of the native Solana Stake Program, where all Principal (PT) and Reward (RT) tokens remain redeemable at maturity effectively acting as a fungible [withdraw authority](https://solana.com/docs/references/staking/stake-accounts). However, bugs or vulnerabilities in on-chain programs could result in loss of funds. Pye's contracts have been audited — but no audit guarantees the absence of vulnerabilities.

***

## Counterparty Liquidity Risk

If orderbook liquidity thins out, your order may sit unfilled or rates may widen. This does not put your principal at risk. You can reduce order size, adjust your discount rate, or wait for liquidity to improve.

***


# Changelog

New updates and improvements

{% updates format="full" %}
{% update date="2026-03-19" tags="validators" %}

## Validator Dashboard Release v0.1.0

[**The Validator Dashboard is here**](https://dashboard.pye.fi/organization)

This is the first public release of the PYE Validator Dashboard — a dedicated hub for validators and node operators to manage their organizations, create lockups, track performance, and integrate with the PYE CLI. Everything operators need to participate in the PYE protocol, in one place.

#### Organization Onboarding & Management

* Multi-step onboarding flow: create your organization, set up your profile, add brand channels, and upload a logo
* Invite team members and assign Admin or Member roles
* Organization settings with branding, contact info, and social links

  Wallet-based authentication via Phantom, SquadsX, and Ledger — plus email magic link sign-in

<figure><picture><source srcset="/files/2QRgyGLbO8f7AfzoZOg3" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FgZPplktQhNiTCuabYaIr%2FScreenshot%202026-03-18%20at%202.59.33%E2%80%AFPM.png?alt=media&amp;token=4786455f-fee3-4e7b-b5e4-bf580c8fb33b" alt=""></picture><figcaption></figcaption></figure>

#### Organization Dashboard

* At-a-glance overview of validator stake, total SOL staked via PYE, and PYE Points
* Profit charts tracking earnings over time
* Quick-action shortcuts to create lockups, manage API keys, add nodes, and estimate profits

#### Lockup Management

* Tabbed dashboard for public, private, and expired lockups
  * Sortable columns: TVL, capacity, commission rates, projected APY, unique stakers, deposit status, and maturity date
* Create Lockup form with duration selection, commission configuration, and on-chain transaction signing
  * Auto-population of commission rates from CLI custom commissions when available

<figure><picture><source srcset="/files/HKZh9zzO17jg5SKsPMgp" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FEEhfK3iHkqvy6W24PXjD%2FScreenshot%202026-03-18%20at%202.59.06%E2%80%AFPM.png?alt=media&amp;token=8d9f2c9c-2fb8-4be0-8ff3-3d797e614000" alt=""></picture><figcaption></figcaption></figure>

<figure><picture><source srcset="/files/tj5ACCl7paYk3CoGTTyX" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FBEF31B3vM2dLHEwyRbct%2FScreenshot%202026-03-18%20at%203.02.46%E2%80%AFPM.png?alt=media&amp;token=22aefdf3-fc37-4647-8461-a2853c4549ff" alt=""></picture><figcaption></figcaption></figure>

#### Node Management

* Register validator nodes by vote account pubkey
* Upload node logos for branding across the platform
* Node verification status tracking (Verified / Pending)

#### Node Dashboard

* Per-node performance analytics with epoch-by-epoch reward breakdowns
* Backtested historical rewards powered by TopLedger data
* APY and rewards-per-SOL metrics

#### Custom Commissions & CLI Integration

* Generate and revoke API keys for CLI authentication
* Real-time CLI connection status monitoring (version, last sync, online/offline)
* Fund and manage your CLI paymaster balance directly from the dashboard
* Deposit SOL to your paymaster account with one click

<figure><picture><source srcset="/files/JQs1ePoAZesyF5TdHLxP" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FiDEKCVHcPmladErrXEjT%2FScreenshot%202026-03-18%20at%202.50.59%E2%80%AFPM.png?alt=media&amp;token=c96063b2-8d96-4521-a95b-bb7a63ede2e1" alt=""></picture><figcaption></figcaption></figure>

#### Claim Fees

* View accumulated trading fees from PT/RT activity in SOL and USD, once trading is live
* One-click fee claiming for organization admins

#### Profit Calculator&#x20;

* Estimate potential commission earnings across different scenarios
* Model various commission rate configurations

#### Platform & Infrastucture Dashboard

* Built on Next.js 16, React 19, and TypeScript with end-to-end type safety via tRPC
* Solana Wallet Standard integration with hardware wallet support
* Supabase authentication with row-level security
* OFAC geofencing for sanctioned regions
* Cloudflare Turnstile CAPTCHA on authentication flows
* Responsive design across mobile, tablet, and desktop
  {% endupdate %}

{% update date="2026-02-11" %}

## Beta Release v0.2.5

**Staking, UX polish, and platform hardening**

This release introduces a new flow for staking SOL to validators or migrating stake accounts, improves staking and redemption ergonomics, and continues to harden the app through accessibility and reliability improvements.

#### [Stake Sol / Migrate Stake Accounts ](https://app.pye.fi/stake)

* Ability to stake SOL into fixed-term lockups
* Ability to migrate existing stake accounts into fixed-term lockups
* Quarterly maturity selection (Q1, Q2, Q3 & Q4 2025)
* Upon staking, users receive **Principal Tokens (PT)** and **Reward Tokens (RT)** that represent locked stake and claim to rewards, respectively.
* PTs & RTs accessible in user dashboard
* PT & RT redemptions available in the lockup detail page
* Contextual FAQ

<figure><picture><source srcset="/files/uW6sr7Qj7ArpqYWOuA76" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FoEvEhuuTjpU9bQYpIMs0%2FStake%20Dark.png?alt=media&amp;token=70a71906-1085-4bbb-b815-7d4bca781283" alt=""></picture><figcaption></figcaption></figure>

<figure><picture><source srcset="/files/jbgRQDuVLxZGKxKDuSnS" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FdVypLxtw850BiNh5VIO6%2FFAQ%20Light.png?alt=media&amp;token=4567d3c7-886c-432a-b928-539f0a76ca34" alt=""></picture><figcaption></figcaption></figure>

#### Improvements & Bug Fixes

* Support for dual redeem and merging stake accounts in a single transaction
  * Improves redemption efficiency and reduces transaction overhead
* Removed Calculator from the navigation for non-validators
* Fixed geofence alert width

#### Accessibility Improvements

* Fixed multiple accessibility issues identified via automated audits:
  * Improved screen-reader support for charts, tables, dialogs, and selectors
  * Added accessible labels and hidden text where required
* These changes improve usability for assistive technologies without altering visual design

#### Reliability & Error Handling

* Introduced custom error boundaries to better isolate and recover from runtime errors

#### Internal updates

* Updated internal packages and UI libraries to the latest versions
* Continued improvements to internal tooling and testing infrastructure
  {% endupdate %}

{% update date="2026-01-30" %}

## Beta Release v0.2.4

#### Improvements & bug fixes

* Updated validator logos; fixed light/dark mode styling inconsistencies
* Fixed multiple bugs in the create lockup form
* Resolved issue where TVL displayed as 0 after maturity
* Added loading skeletons to charts
  {% endupdate %}

{% update date="2026-01-20" %}

## Beta Release v0.2.3

This release focuses on reliability, access control, and quality-of-life improvements across validator and staker flows, with an emphasis on preventing edge cases that came up during validator onboarding.

### Validators

#### Increased Lockup Durations (1–6 Months)

* We added preset lockup durations (1–6 months) to the lockup creation form
* Validators can now invite their stakers to delegate to them for up to 6 months at a time

<figure><picture><source srcset="/files/fQl0qqYBqM0WT5f9Mao1" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2F2TIm2Ic73uZEoM4LPIit%2FCreate%20Lockup%20-%20Light.png?alt=media&amp;token=c27df9e1-7c11-4de3-94c9-165dd9827490" alt=""></picture><figcaption></figcaption></figure>

#### Approval Pending Modals

* Validators awaiting whitelist approval are now explicitly blocked via a modal across:
  * Organization admin pages
  * Create lockup flows

<figure><picture><source srcset="/files/FGzwNc9OYOpjpfkZeSUW" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FUinW6mU6fSA8rtnJ3h59%2Fimage%20238.png?alt=media&amp;token=fb3ff002-735b-4da2-8e77-152b5e8175cb" alt=""></picture><figcaption></figcaption></figure>

#### Improvements

* Added the ability to automatically populate validator commission rates using public Stakewiz data
* Added geofence tooltips to the wallet connection button when access is restricted

<figure><picture><source srcset="/files/sc8WYPhGtB3KI0w4SXVC" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FLNN6tZH6FDtgLNOVnJY1%2FMatch%20public%20comissions%20light.png?alt=media&amp;token=03f9c57a-2e1b-481d-a84f-64d1a1f87393" alt=""></picture><figcaption></figcaption></figure>

#### Bug Fixes & Improvements

* Prevented validators from becoming stuck when geofenced
* Prevented users from removing themselves from an organization
* Hid the “Remove user” action for non-admin members
* Fixed an issue with Stakewiz endpoints affecting commission data
* Refactored CAPTCHA handling to improve reliability and reduce false failures

### Stakers

#### Improvements

* Added tooltips to staker dashboard charts to improve data clarity and interpretation

#### Bug Fixes

* Fixed an issue where trailing zeroes in stake size inputs were ignored
* Fixed a bug that could display NaN balances and block transactions
  {% endupdate %}

{% update date="2026-01-09" %}

## Beta Release v0.2.2

This release introduces validator organizations, enabling teams to securely manage access, members, and issuer keys under a shared organization.\
\
It lays the foundation for multi-user validator operations and improved operational security.

#### Validator Sign Up

* A dedicated sign up and sign in for validators, using email or Google authentication
* Designed for validator teams, not individual wallets

#### Create Organizations

* Organizations are shared environments where validator teams can launch & monitor their lockups
* Create a new organization or accept an invite from your team

<div align="left"><figure><picture><source srcset="/files/VvUjYtjE6q7soRAr3f04" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FSIwVEaXtgcWflv9WxMyb%2FCreate%20a%20new%20org%20Light.png?alt=media&amp;token=ef692860-c13a-415c-8a7f-de1335e872ff" alt=""></picture><figcaption></figcaption></figure></div>

#### Organization Admin

* Invite and remove users from your organization
* Manage issuer keys

<div align="left"><figure><picture><source srcset="/files/VDTLJGt4HtFxMQdziUvx" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FtByG0vqLBt3jExcYe5LV%2FUser%20Admin%20Light.png?alt=media&amp;token=d5e63dab-5dbe-4931-b513-15fde1842c4a" alt=""></picture><figcaption></figcaption></figure></div>

#### SolanaKit Upgrades

* Migrate from `@solana/web3.js` to `@solana/kit` (formerly known as web3.js v2)&#x20;
* Smaller bundle, better performance and improved security

#### App Versioning

* The current app version is now visible in the footer to improve transparency and support troubleshooting
  {% endupdate %}

{% update date="2025-12-19" %}

## Beta Release v0.2.1

With our first beta release, we’ve removed the waitlist and opened the app to stakers.\
\
This release introduces the core product experience for stakers and validators, including dashboards, lockup creation, and tools for monitoring performance across public and private lockups.

<figure><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2Flih79iCfszWzGPpfzaZi%2FArtboard%2020.svg?alt=media&amp;token=ae267895-6674-4f21-98c1-ab45dfcecb86" alt=""><figcaption></figcaption></figure>

#### User Dashboard

* Manage, monitor and redeem positions
* Benchmark your performance over time&#x20;
* Track your Pye Points

<figure><picture><source srcset="/files/LA47OKfn3cJ7TX1eHChE" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FYmo9fmm8zUokGbEPMTjb%2FGroup%201597887251.png?alt=media&amp;token=b919a7d9-e79f-4f1f-910f-d1e56d445434" alt=""></picture><figcaption></figcaption></figure>

#### Public Lockup Detail Page

* Stake and redeem for public lockups
* Learn about and monitor a lockup

<figure><picture><source srcset="/files/eV609OQV9YqifFBl7pnq" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2F0UCh8eItEx2NjDcVUtSd%2FLockup%20Detail%20Light.png?alt=media&amp;token=172bc8f4-0901-4cd5-ad57-1a891c5a8a61" alt=""></picture><figcaption></figcaption></figure>

#### Private Lockup Detail Page

* Validators can now create private lockups
* Stakers can remain anonymous
* Validators can offer private custom staking terms to customers

<figure><picture><source srcset="/files/ndaTRVOsMBBfJLzr2wtm" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FRjfCpL2fNgNHDlNHujiQ%2FInvite%20Light.png?alt=media&amp;token=a1d5b6b2-9260-44ae-a8aa-ce69a5bd8bbf" alt=""></picture><figcaption></figcaption></figure>

<figure><picture><source srcset="/files/9q64nGGExnVUxXTbGvi7" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2Fh1Chl4ul93UWtdlTmrxA%2FPrivateLockup%20Light.png?alt=media&amp;token=dce0d138-340d-462c-8f0a-d70cc4d51ab3" alt=""></picture><figcaption></figcaption></figure>

#### Validator Dashboard

* Track and compare historical performance against the network average
* Monitor public, private and expired lockups

<figure><picture><source srcset="/files/FPts0mlhjfEUGiOuPAI0" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FeKoF81zKHe7DPHBdaQKg%2FValidator%20Dashboard%20Light.png?alt=media&amp;token=4bfad5b8-162a-4179-9e9e-38601adc14b6" alt=""></picture><figcaption></figcaption></figure>

#### Create Lockups

* Create a new lockup for stakers on on app.pye.fi
* Set custom lockup terms
* Create public or private lockups for single depositors

<figure><picture><source srcset="/files/WuWR1WIwXZiI3WSFe3Ni" media="(prefers-color-scheme: dark)"><img src="https://425827464-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FyMLfgxuwTUZTVAfVtJk2%2Fuploads%2FH1Wk0y0qDblBRTuwpHbT%2FScreenshot%202026-01-08%20at%2015.37.19.png?alt=media&amp;token=23e3f17d-063c-495b-9e0d-f2e512100956" alt=""></picture><figcaption></figcaption></figure>
{% endupdate %}
{% endupdates %}


