Skip to content

Commit 2ec60fa

Browse files
feat: solana (#355)
* add ethereum and solana sections remove outdated frame border * feat: include solana in the navbar and body page * feat: add first page of solana docs * feat: account arhitecture * feat: program reference * feat: add errors docs * feat: events docs * feat: official deployment feat: add git source hyperlinks fix: add events hyperlinks * account git hyperlinks * change main to specific git commit * iaro feedback * shorter title * polish text * improve token diagrams * note about early stage
1 parent 4231f0c commit 2ec60fa

19 files changed

Lines changed: 2075 additions & 21 deletions

config/sidebars.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const sidebars: SidebarsConfig = {
1010
conceptsSidebar: [{ dirName: "concepts", type: "autogenerated" }],
1111
guidesSidebar: [{ dirName: "guides", type: "autogenerated" }],
1212
referencesSidebar: [{ dirName: "reference", type: "autogenerated" }],
13+
solanaSidebar: [{ dirName: "solana", type: "autogenerated" }],
1314
supportSidebar: [{ dirName: "support", type: "autogenerated" }],
1415
};
1516

config/theme-config.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,12 @@ const navbar: Preset.ThemeConfig["navbar"] = {
114114
position: "left",
115115
to: "/apps/features/overview",
116116
},
117-
117+
{
118+
activeBasePath: "/solana",
119+
label: "Solana",
120+
position: "left",
121+
to: "/solana/sablier-on-solana",
122+
},
118123
{
119124
activeBasePath: "/support",
120125
label: "Support",
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
id: "sablier-on-solana"
3+
sidebar_position: 1
4+
title: "Sablier on Solana"
5+
---
6+
7+
:::note
8+
9+
This part of the documentation is in its early stages and will be continuously improved over time. We're actively working on the content to include more guides, examples, and detailed explanations.
10+
11+
:::
12+
13+
## Introduction
14+
15+
Welcome to the Sablier on Solana documentation.
16+
17+
This section assumes you are familiar with the Sablier Protocol and its Ethereum high level concepts. Here, we focus on what's specific to the Solana blockchain and how it differs from Ethereum.
18+
19+
For more information on the original Sablier Protocol, refer to the [main documentation](../concepts/01-what-is-sablier.mdx).
20+
You can also find information about [Streaming](../concepts/02-streaming.md) and
21+
[Airdrops](../concepts/05-merkle-airdrops.mdx) in the Concepts section.
22+
23+
## SolSab
24+
25+
[SolSab](https://github.com/sablier-labs/solsab) is a collection of protocols featuring two main Solana programs: **Sablier Lockup** and **Sablier Merkle Instant**. While not all protocols available for Ethereum are currently available for Solana, we aim to bring the same protocols to Solana in future iterations.
26+
27+
:::important
28+
29+
Unlike Ethereum, the programs here adhere to the best practices of Solana development and are **upgradeable** for
30+
greater security.
31+
32+
:::
33+
34+
### Lockup
35+
36+
The official deployment can be found at the address: `4EauRKrNErKfsR4XetEZJNmvACGHbHnHV4R5dvJuqupC`
37+
38+
- [Mainnet](https://solscan.io/account/4EauRKrNErKfsR4XetEZJNmvACGHbHnHV4R5dvJuqupC)
39+
- [Devnet](https://solscan.io/account/4EauRKrNErKfsR4XetEZJNmvACGHbHnHV4R5dvJuqupC?cluster=devnet)
40+
41+
Sablier Lockup is a token distribution protocol that enables onchain vesting and payments. Our flagship model is the
42+
linear stream, which distributes tokens on a continuous, by-the-second basis.
43+
44+
The way it works is that the creator of a payment stream first deposits a specific amount of SPL or Token2022 tokens. The program then progressively allocates the funds to the recipient, who can access them as they become
45+
available over time. The payment rate is influenced by various factors, including the start and end times, as well as
46+
the total amount of tokens deposited.
47+
48+
#### Key differences from the Ethereum [Lockup](../concepts/lockup/01-overview.md) protocol
49+
50+
- The Solana program includes only the Linear streaming model, not the Dynamic and Tranched models. See the available shapes for the Linear model
51+
[here](../concepts/lockup/02-stream-shapes.mdx#lockup-linear).
52+
- Due to the limitations of the [Token Metadata](https://developers.metaplex.com/token-metadata) NFT standard on Solana, we cannot have non-transferable NFTs.
53+
- Tokens transferred during stream creation are placed in a dedicated Stream ATA ([Associated Token Account](https://www.alchemy.com/overviews/associated-token-account)), instead of all tokens being held in the Lockup contract as on Ethereum.
54+
- We do not have hooks for the `cancel` and `withdraw` functionalities due to limitations in how Solana works.
55+
56+
### Merkle Instant
57+
58+
The official deployment can be found at the address: `7XrxoQejBoGouW4V3aozTSwub7xSDjYqB4Go7YLjF9rV`
59+
60+
- [Mainnet](https://solscan.io/account/7XrxoQejBoGouW4V3aozTSwub7xSDjYqB4Go7YLjF9rV)
61+
- [Devnet](https://solscan.io/account/7XrxoQejBoGouW4V3aozTSwub7xSDjYqB4Go7YLjF9rV?cluster=devnet)
62+
63+
Merkle Instant is a program that enables the creation of token airdrop campaigns using Merkle trees, allowing users to
64+
instantly claim and receive their allocation through a single transaction.
65+
66+
#### Key differences from the Ethereum [Airdrops](../concepts/05-merkle-airdrops.mdx) protocols
67+
68+
- The Solana program includes only the Instant airdrop model, not the Vesting airdrop models.
69+
- Due to the nature of Solana's account architecture, we have a single program that handles both the creation and the claiming. In contrast to Ethereum, where we have a factory contract that deploys a stand-alone contract for each airdrop campaign.
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
---
2+
id: "lockup"
3+
sidebar_position: 1
4+
title: "Lockup"
5+
---
6+
7+
This section focuses on the architecture of accounts created or used in the most important instructions of the Lockup
8+
program.
9+
10+
## Account architecture
11+
12+
### Sablier Lockup program
13+
14+
The `sablier_lockup` program implements these main functionalities:
15+
16+
- `initialize`
17+
- `create_with_timestamps_ll`
18+
- `cancel`
19+
- `withdraw`
20+
- `renounce`
21+
22+
We will go into the details and specifics of each one later. For now, we will focus only on the accounts being created.
23+
24+
```mermaid
25+
flowchart TD
26+
A[Sablier Lockup Program] --> B[initialize]
27+
A --> C[create_with_timestamps_ll]
28+
A --> D[cancel]
29+
A --> E[withdraw]
30+
A --> F[renounce]
31+
```
32+
33+
### `initialize` Instruction
34+
35+
```mermaid
36+
flowchart TD
37+
A[Initializer] -->|calls| B[initialize]
38+
39+
B --> |creates| C((treasury))
40+
B --> |creates| D((nft_collection_ata))
41+
B --> |creates| E((nft_collection_data))
42+
B --> |creates| F((nft_collection_master_edition))
43+
B --> |creates| G((nft_collection_metadata))
44+
B --> |creates| H((nft_collection_mint))
45+
```
46+
47+
- **NFT collection data PDA**: stores collection configuration and metadata
48+
- **NFT collection mint PDA**: serves as the master mint authority for all stream NFTs
49+
- **NFT collection metadata PDA**: created via Metaplex CPI
50+
- **NFT collection master edition PDA**: created via Metaplex CPI
51+
- **NFT collection ATA**: associated token account owned by treasury to hold the collection NFT token
52+
53+
The
54+
[Treasury PDA](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/lockup/src/state/treasury.rs#L5-L10)
55+
stores this data:
56+
57+
```mermaid
58+
flowchart TD
59+
C((treasury)) --> C1([fee_collector])
60+
C --> C2([chainlink_program])
61+
C --> C3([chainlink_sol_usd_feed])
62+
```
63+
64+
### `create_with_timestamps_ll` Instruction
65+
66+
#### Pre-existing accounts required:
67+
68+
- Deposit Token
69+
- NFT Collection
70+
71+
```mermaid
72+
flowchart TD
73+
A[Sender] -->|calls| B[create_with_timestamps_ll]
74+
75+
B --> |creates| C((stream_nft_mint))
76+
C0((nft_collection_mint)) -.-> |authority for| C
77+
B --> |creates| D((stream_data))
78+
B --> |creates| H((stream_data_ata))
79+
H -.-> |for| H1((deposit_token_mint))
80+
81+
B --> |creates| C1((recipient_stream_nft_ata))
82+
B --> |creates| C2((stream_nft_master_edition))
83+
B --> |creates| C3((stream_nft_metadata))
84+
```
85+
86+
The **Stream NFT Mint** also serves as the "Stream ID" for the `cancel`, `renounce`, and `withdraw` instructions.
87+
88+
Each
89+
[Stream Data](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/lockup/src/state/lockup.rs#L14-L24)
90+
account stores the following parameters:
91+
92+
```mermaid
93+
flowchart TD
94+
A((Stream Data))
95+
A --> A1([amounts])
96+
A --> A2([deposit_token_mint])
97+
A --> A3([is_cancelable])
98+
A --> A4([is_depleted])
99+
A --> A5([salt])
100+
A --> A6([sender])
101+
A --> A7([timestamps])
102+
A --> A8([was_canceled])
103+
```
104+
105+
Each
106+
[amount](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/lockup/src/state/lockup.rs#L4-L10)
107+
data structure consists of the following components:
108+
109+
```mermaid
110+
flowchart TD
111+
A([amounts])
112+
A --> A1([deposited])
113+
A --> A2([withdrawn])
114+
A --> A3([refunded])
115+
```
116+
117+
Each
118+
[timestamps](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/lockup/src/state/lockup.rs#L28-L32)
119+
data structure consists of the following components:
120+
121+
```mermaid
122+
flowchart TD
123+
A([timestamps])
124+
A --> A1([cliff])
125+
A --> A2([end])
126+
A --> A3([start])
127+
```
128+
129+
## The Flow of the Deposit Token
130+
131+
### `create_with_timestamps_ll` Instruction
132+
133+
```mermaid
134+
sequenceDiagram
135+
actor Sender
136+
participant Lockup
137+
participant TokenProgram as Token Program
138+
participant Accounts as Token Accounts<br/>Sender ATA & StreamData ATA
139+
140+
Sender->>Lockup: create_with_timestamps_ll()
141+
Lockup->>TokenProgram: CPI: transfer()
142+
TokenProgram-->>Accounts: Move tokens<br/>Sender ATA → StreamData ATA
143+
```
144+
145+
### `cancel` Instruction
146+
147+
Only the sender can cancel a stream.
148+
149+
```mermaid
150+
sequenceDiagram
151+
actor Sender
152+
participant Lockup
153+
participant TokenProgram as Token Program
154+
participant Accounts as Token Accounts<br/> StreamData ATA & Sender ATA
155+
156+
Sender->>Lockup: cancel()
157+
Lockup->>TokenProgram: CPI: transfer()
158+
TokenProgram-->>Accounts: Move tokens<br/> StreamData ATA → Sender ATA
159+
```
160+
161+
### `withdraw` Instruction
162+
163+
```mermaid
164+
sequenceDiagram
165+
actor Recipient
166+
participant Lockup
167+
participant TokenProgram as Token Program
168+
participant Accounts as Token Accounts<br/> StreamData ATA & WithdrawalRecipient ATA
169+
170+
Recipient->>Lockup: withdraw(withdrawal_recipient)
171+
Lockup->>TokenProgram: CPI: transfer()
172+
TokenProgram -->> Accounts: Move tokens<br/> StreamData ATA → WithdrawalRecipient ATA
173+
```
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
---
2+
id: "merkle-instant"
3+
sidebar_position: 2
4+
title: "Merkle Instant"
5+
---
6+
7+
This section focuses on the architecture of accounts created or used in the most important instructions of the Merkle
8+
Instant program.
9+
10+
## Account architecture
11+
12+
### Sablier Merkle Instant program
13+
14+
The `sablier_merkle_instant` program implements the following main functionalities:
15+
16+
- `initialize`
17+
- `create_campaign`
18+
- `claim`
19+
- `clawback`
20+
21+
We will go into the details and specifics of each one later. For now, we will focus only on the accounts being created.
22+
23+
```mermaid
24+
flowchart TD
25+
A[Sablier Merkle Instant Program] --> B[initialize]
26+
A --> C[create_campaign]
27+
A --> D[claim]
28+
A --> E[clawback]
29+
```
30+
31+
### `initialize` Instruction
32+
33+
```mermaid
34+
flowchart TD
35+
A[Initializer] --> |calls| B[initialize]
36+
37+
B --> |creates| C((treasury))
38+
```
39+
40+
The
41+
[Treasury PDA](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/merkle_instant/src/state/treasury.rs#L5-L10)
42+
stores this data:
43+
44+
```mermaid
45+
flowchart TD
46+
C((treasury)) --> C1([fee_collector])
47+
C --> C2([chainlink_program])
48+
C --> C3([chainlink_sol_usd_feed])
49+
```
50+
51+
### `create_campaign` Instruction
52+
53+
```mermaid
54+
flowchart TD
55+
A[Campaign Creator] --> |calls| B[create_campaign]
56+
57+
B --> |creates| C((campaign))
58+
B --> |creates| D((campaign_ata))
59+
D -.-> |for| D1((airdrop_token_mint))
60+
```
61+
62+
Each
63+
[Campaign](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/merkle_instant/src/state/campaign.rs#L8-L20)
64+
account stores the following parameters:
65+
66+
```mermaid
67+
flowchart TD
68+
A((campaign)) --> A1([airdrop_token_mint])
69+
A --> A2([campaign_start_time])
70+
A --> A3([creator])
71+
A --> A4([expiration_time])
72+
A --> A5([first_claim_time])
73+
A --> A6([ipfs_cid])
74+
A --> A7([merkle_root])
75+
A --> A8([name])
76+
```
77+
78+
### `claim` Instruction
79+
80+
```mermaid
81+
flowchart TD
82+
A[Claimer] -->|calls| B[claim]
83+
84+
B --> |creates| C((claim_receipt))
85+
B --> |creates| D((recipient_ata))
86+
D -.-> |for| D1((airdrop_token_mint))
87+
```
88+
89+
The
90+
[Claim receipt](https://github.com/sablier-labs/solsab/blob/e1085fe87ea3d02556156ee446e820d150af483e/programs/merkle_instant/src/state/claim_receipt.rs#L6)
91+
account serves as proof of claim for the given recipient.
92+
93+
## The Flow of the Airdrop Token
94+
95+
### `create_campaign` Instruction
96+
97+
This instruction does not perform the airdrop token transfer, but the transfer is expected to be made as a separate
98+
transaction. Therefore, the campaign ATA is assumed to be funded after the campaign creation.
99+
100+
### `claim` Instruction
101+
102+
```mermaid
103+
sequenceDiagram
104+
actor Claimer
105+
participant MerkleInstant
106+
participant TokenProgram as Token Program
107+
participant Accounts as Token Accounts<br/>Campaign ATA & Recipient ATA
108+
109+
Claimer->>MerkleInstant: claim(recipient)
110+
MerkleInstant->>TokenProgram: CPI: transfer()
111+
TokenProgram-->>Accounts: Move tokens<br/>Campaign ATA → Recipient ATA
112+
```
113+
114+
### `clawback` Instruction
115+
116+
```mermaid
117+
sequenceDiagram
118+
actor CampaignCreator
119+
participant MerkleInstant
120+
participant TokenProgram as Token Program
121+
participant Accounts as Token Accounts<br/>Campaign ATA & CampaignCreator ATA
122+
123+
CampaignCreator->>MerkleInstant: clawback()
124+
MerkleInstant->>TokenProgram: CPI: transfer()
125+
TokenProgram-->>Accounts: Move tokens<br/>Campaign ATA → CampaignCreator ATA
126+
```
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"collapsed": false,
3+
"label": "Accounts Architecture",
4+
"position": 2
5+
}

0 commit comments

Comments
 (0)