Privy is a Solana application for receiving spam-free private messages through a sharable user link. The receiver pays the transaction fees using a relayer backend service while ensuring client-side message encryption. The project implements token management, categorization, passkey mechanisms, link disabling, and single-message reception.
-
User 1 - Message Receiver
- Sign up using Solana wallet and create a username and password
- Buy tokens (currently Devnet SOL)
- Share the link and start receiving messages
- Optionally configure account and categories
-
User 2 - Message Sender
- Access the shared link and type a message
- Optionally type a passkey (to reduce spam user 1 can set)
- Click send message
- Client-side message encryption
- Spam-free private messaging via a sharable user link
- Receiver pays transaction fees through a relayer backend service
- Token management, categorization, passkey mechanisms
- Link disabling and single-message receiving features
- Founders/Managers: Individuals who want to receive critical private feedback.
- Farcaster/Web3 Socials Users: Users who want to receive private messages from their followers.
- Smart Contract (Program): Rust, Solana, Anchor Lang, Chai Tests
- Backend: Rust, Actix Web, Postgres, Diesel, Anchor Client
- Frontend: React, TypeScript, Ant Design, FingerprintJS, @solana/web3.js
- TypeScript SDK:
- Encryption utilities (used by Program tests & Frontend)
- Program interaction functions (used by Program tests & Frontend)
- Server API call functions (used by Server tests & Frontend)
-
User 1 (Message Receiver)
- Sign Up: Sign up using Solana wallet and create a username and password.
- Token Purchase: Select the token amount and click buy.
- Space Allocation: Calculate the amount of space required for storing messages and send allocate_space transactions with create_user transactions.
- Account Configuration: Configure account and categories settings, which will require users to pay for the transaction fees.
-
User 2 (Message Sender)
- Access the link
- Frontend client makes first call to backend
- Backend retrieves the user address mapped to the username.
- Queries user PDA account from the blockchain using the address and the user fingerprint row from the DB.
- Checks whether the user is allowed to send a message and returns the appropriate response to the client.
- If the user is allowed to send a message, the client encrypts the message using the user's public address received from the previous API call and sends the data to the server.
- The server again retrieves the PDA account, performs sanity checks, and makes a blockchain transaction to insert the data.
- Transaction Fees: The relayer server pays transaction fees on behalf of User 1 (message receiver).
- Username to Address Mapping: Stores the mapping in off-chain storage due to Solana's account size limitations.
- Spam Reduction: Stores end-user browser fingerprints in an off-chain database based on user or user-category settings.
- On-Chain Data Checks: Performs checks before inserting data on-chain as we are storing off-chain encrypted data.
- Symmetric Encryption: Utilizes symmetric encryption for categories and username fields in the user PDA account data. Encryption algorithm implemented in both Rust (backend) and TypeScript (frontend/sdk).
- Asymmetric Encryption: Implemented a password-based RSA asymmetric encryption algorithm for encrypting sensitive data, which in our case is the private messages users receive. This ensures messages are private from middlemen (including the program owner), making the system truly trustless.
- Data Compression: Currently implemented the Brotli compression algorithm for data compression before storing. (The plan is to move to zk-compression in the future.)
Accounts
-
PrivyUser
: Represents a user's account storing their username, token limit, categories, messages, and a bump seed for PDA (Program Derived Address). -
PrivyConfig
: Stores the program's configuration data, including the owner's public key and the conversion rate of tokens per SOL.
Instructions
-
initialize_privy_config
: Initializes the Privy program's configuration with the specified tokens per SOL rate. -
update_privy_config
: Updates the existing Privy program configuration with a new tokens per SOL rate. -
withdraw_balance
: Allows the program owner to withdraw a specified amount of SOL from the program's account. -
create_user
: Creates a new Privy user account with a username, categories, and an initial deposit of SOL. -
update_username
: Updates the username of an existing Privy user account. -
add_tokens
: Adds additional SOL to a Privy user account, increasing their token limit. -
allocate_space
: Allocates additional space in the Privy user account for storing data such as messages. -
insert_message
: Inserts an encrypted message into the messages vector of a Privy user account. -
update_category
: Updates the categories associated with a Privy user account, typically used for message filtering and categorization.
Table: fingerprints
Column | Type | Description |
---|---|---|
id |
Varchar | Primary key, unique identifier for the fingerprint |
user_categories |
Varchar | Stores user-specific category data |
Table: users
Column | Type | Description |
---|---|---|
user_addr |
Varchar | Primary key, unique user address |
user_name |
Varchar | Username associated with the user |
password_salt |
Varchar | Salt used for password hashing |
password_pubkey |
Varchar | Public key used for password encryption |
This repo contains the Solana program source code and client-side program tests written in TypeScript.
├── .vscode # Program keypairs
├── frontend # Solana program source code
├── server # Backend server helper bash scripts
├── program # TypeScript source folder
├── sdk # TypeScript source folder
└── README.md
- Follow the program guide and deploy the program.
- Follow the server guide, run the db migrations, and start the server.
- For running the frontend, install the dependencies along with the sdk and start the server.
- Optimise program's compute units
- Wallet standard encryption (Onchain)
- Fully onchain with ZK Compression