https://github.com/bluntbrain/solana-cross-program-invocation
This project shows how one Solana program calls another program. The main focus is on Cross-Program Invocation (CPI).
https://github.com/bluntbrain/solana-cross-program-invocation
Last synced: 17 days ago
JSON representation
This project shows how one Solana program calls another program. The main focus is on Cross-Program Invocation (CPI).
- Host: GitHub
- URL: https://github.com/bluntbrain/solana-cross-program-invocation
- Owner: bluntbrain
- Created: 2025-08-15T18:29:48.000Z (12 months ago)
- Default Branch: master
- Last Pushed: 2025-08-23T08:13:12.000Z (11 months ago)
- Last Synced: 2025-10-28T22:34:51.696Z (9 months ago)
- Language: TypeScript
- Size: 10.7 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Solana Cross-Program Invocation (CPI) Project
[](https://www.rust-lang.org/)
[](https://solana.com/)
[](https://www.typescriptlang.org/)
This project shows how one Solana program calls another program. The main focus is on Cross-Program Invocation (CPI).
## How It Works
We have three programs:
1. **Double Contract** - A simple counter that doubles numbers
2. **CPI Contract** - Calls the double contract using CPI
3. **PDA Contract** - Demonstrates Program Derived Addresses (PDAs)
The CPI contract doesn't do the math itself. Instead, it calls the double contract to handle the counting logic.
## Project Structure
```
cpi-in-solana/
├── cpi-contract/
│ ├── src/lib.rs # Main CPI program
│ └── Cargo.toml
├── double-contract/
│ ├── src/lib.rs # Counter program that gets called
│ └── Cargo.toml
├── pda-contract/
│ ├── src/lib.rs # PDA demonstration program
│ └── Cargo.toml
└── client/
├── index.test.ts # Tests both programs
└── package.json
```
## The CPI Program
The important part is in `cpi-contract/src/lib.rs`. Here's what it does:
1. Takes two accounts: data account and double contract address
2. Creates an instruction to call the double contract
3. Uses `invoke()` to make the CPI call
4. Passes the data account to the other program
```rust
let instruction = Instruction {
program_id: *double_contract_address.key,
accounts: vec![AccountMeta {
is_signer: true,
is_writable: true,
pubkey: *data_account.key,
}],
data: vec![],
};
invoke(&instruction, &[data_account.clone()])?;
```
This is the core of CPI - one program creating an instruction for another program and calling it.
## Setup
```bash
git clone
cd cpi-in-solana
# Install dependencies
npm run setup
# Build both programs
npm run build
# Run tests
npm run test
```
## Testing
The tests show the CPI in action. They:
1. Deploy both programs to a local blockchain
2. Create accounts and fund them
3. Call the CPI program
4. Verify the double contract was executed
You can see this working in `client/cpi.test.ts`.
## Key Concepts
**Cross-Program Invocation (CPI)**: When one Solana program calls another program during execution.
**invoke()**: The function that makes CPI calls happen. It takes an instruction and the accounts needed.
**invoke_signed()**: Special CPI function that allows programs to sign on behalf of Program Derived Addresses (PDAs). Used when the calling program needs to act as a signer for accounts it owns.
**Program Derived Addresses (PDAs)**: Special accounts owned by programs but without private keys. They're derived deterministically from seeds and the program ID, enabling programs to control accounts programmatically.
**Account Passing**: Accounts get passed from the calling program to the called program. Both programs can read and modify them.
**Program Composition**: Instead of writing one big program, you can split logic into smaller programs that call each other.
## Build Commands
```bash
npm run build:cpi # Build the CPI program
npm run build:double # Build the double counter
npm run build:pda # Build the PDA program
npm run build # Build all programs
npm run test # Run the tests
npm run clean # Clean build files
```