Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 44 additions & 20 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,27 @@ on:
branches: [main]

jobs:
format_and_lint_interface:
name: Format & Lint Interface
runs-on: ubuntu-latest
steps:
- name: Git Checkout
uses: actions/checkout@v4

- name: Setup Environment
uses: ./.github/actions/setup
with:
clippy: true
rustfmt: true
cargo-cache-key: cargo-interface-lint
cargo-cache-fallback-key: cargo-interface

- name: Format
run: pnpm interface:format

- name: Lint
run: pnpm interface:lint

format_and_lint_programs:
name: Format & Lint Programs
runs-on: ubuntu-latest
Expand Down Expand Up @@ -81,26 +102,6 @@ jobs:
- name: Run cargo-audit
run: pnpm rust:audit

semver_rust:
name: Check semver Rust
runs-on: ubuntu-latest
steps:
- name: Git Checkout
uses: actions/checkout@v4

- name: Setup Environment
uses: ./.github/actions/setup
with:
cargo-cache-key: cargo-semver

- name: Install cargo-audit
uses: taiki-e/install-action@v2
with:
tool: cargo-semver-checks

- name: Run semver checks
run: pnpm rust:semver

spellcheck_rust:
name: Spellcheck Rust
runs-on: ubuntu-latest
Expand Down Expand Up @@ -138,6 +139,9 @@ jobs:
- name: Build Programs
run: pnpm programs:build

- name: Build p-memo
run: pnpm p-memo:build

- name: Upload Program Builds
uses: actions/upload-artifact@v4
with:
Expand All @@ -151,6 +155,23 @@ jobs:
path: ./**/*.so
key: ${{ runner.os }}-builds-${{ github.sha }}

test_interface:
name: Test Interface
runs-on: ubuntu-latest
needs: format_and_lint_interface
steps:
- name: Git Checkout
uses: actions/checkout@v4

- name: Setup Environment
uses: ./.github/actions/setup
with:
cargo-cache-key: cargo-interface-tests
cargo-cache-fallback-key: cargo-interface

- name: Test
run: pnpm interface:test

test_programs:
name: Test Programs
runs-on: ubuntu-latest
Expand All @@ -169,6 +190,9 @@ jobs:
- name: Test Programs
run: pnpm programs:test

- name: Test p-memo
run: pnpm p-memo:test

generate_clients:
name: Check Client Generation
runs-on: ubuntu-latest
Expand Down
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "2"
members = ["clients/rust", "p-memo", "program"]
members = ["clients/rust", "interface", "p-memo", "program"]

[workspace.metadata.cli]
solana = "2.3.4"
Expand Down
18 changes: 18 additions & 0 deletions interface/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "spl-memo-interface"
version = "1.0.0"
description = "Solana Program Library Memo Interface"
authors = ["Solana Labs Maintainers <maintainers@solanalabs.com>"]
repository = "https://github.com/solana-labs/solana-program-library"
license = "Apache-2.0"
edition = "2021"

[dependencies]
solana-instruction = "2.2.1"
solana-pubkey = "2.2.1"

[lib]
crate-type = ["lib"]

[package.metadata.docs.rs]
targets = ["x86_64-unknown-linux-gnu"]
37 changes: 37 additions & 0 deletions interface/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use {
solana_instruction::{AccountMeta, Instruction},
solana_pubkey::Pubkey,
};

/// Build a memo instruction, possibly signed
///
/// Accounts expected by this instruction:
///
/// 0. `..0+N` `[signer]` Expected signers; if zero provided, instruction will
/// be processed as a normal, unsigned spl-memo
pub fn build_memo(program_id: &Pubkey, memo: &[u8], signer_pubkeys: &[&Pubkey]) -> Instruction {
Instruction {
program_id: *program_id,
accounts: signer_pubkeys
.iter()
.map(|&pubkey| AccountMeta::new_readonly(*pubkey, true))
.collect(),
data: memo.to_vec(),
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_build_memo() {
let program_id = Pubkey::new_unique();
let signer_pubkey = Pubkey::new_unique();
let memo = "🐆".as_bytes();
let instruction = build_memo(&program_id, memo, &[&signer_pubkey]);
assert_eq!(memo, instruction.data);
assert_eq!(instruction.accounts.len(), 1);
assert_eq!(instruction.accounts[0].pubkey, signer_pubkey);
}
}
17 changes: 17 additions & 0 deletions interface/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#![deny(missing_docs)]

//! An interface for programs that accept a string of encoded characters and
//! verifies that it parses, while verifying and logging signers.

/// Instruction type
pub mod instruction;

/// Legacy symbols from Memo version 1
pub mod v1 {
solana_pubkey::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
}

/// Symbols from Memo version 3
pub mod v3 {
solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
}
15 changes: 10 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
{
"private": true,
"scripts": {
"programs:build": "zx ./scripts/program/build.mjs",
"programs:test": "zx ./scripts/program/test.mjs",
"programs:format": "zx ./scripts/program/format.mjs",
"programs:lint": "zx ./scripts/program/lint.mjs",
"interface:test": "zx ./scripts/rust/test.mjs interface",
"interface:format": "zx ./scripts/rust/format.mjs interface",
"interface:lint": "zx ./scripts/rust/lint.mjs interface",
"programs:build": "zx ./scripts/rust/build-sbf.mjs program",
"programs:test": "zx ./scripts/rust/test-sbf.mjs program",
"programs:format": "zx ./scripts/rust/format.mjs program",
"programs:lint": "zx ./scripts/rust/lint.mjs program",
"p-memo:build": "zx ./scripts/rust/build-sbf.mjs p-memo",
"p-memo:test": "zx ./scripts/rust/test-sbf.mjs p-memo",
"solana:check": "zx ./scripts/check-solana-version.mjs",
"solana:link": "zx ./scripts/link-solana-version.mjs",
"generate": "pnpm generate:clients",
Expand All @@ -22,7 +27,7 @@
"clients:rust:test": "zx ./scripts/client/test-rust.mjs",
"template:upgrade": "zx ./scripts/upgrade-template.mjs",
"rust:spellcheck": "cargo spellcheck --code 1",
"rust:audit": "zx ./scripts/audit-rust.mjs",
"rust:audit": "zx ./scripts/rust/audit.mjs",
"rust:semver": "cargo semver-checks"
},
"devDependencies": {
Expand Down
1 change: 1 addition & 0 deletions program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ solana-msg = "2.2.1"
solana-program-entrypoint = "2.3.0"
solana-program-error = "2.2.2"
solana-pubkey = "2.2.1"
spl-memo-interface = { path = "../interface", version = "1.0.0" }

[dev-dependencies]
solana-program-test = "2.3.6"
Expand Down
40 changes: 6 additions & 34 deletions program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,12 @@ pub mod processor;
pub use {
solana_account_info, solana_instruction, solana_msg, solana_program_entrypoint,
solana_program_error, solana_pubkey,
spl_memo_interface::{
v1,
v3::{check_id, id, ID},
},
};
use {
solana_instruction::{AccountMeta, Instruction},
solana_pubkey::Pubkey,
};

/// Legacy symbols from Memo version 1
pub mod v1 {
solana_pubkey::declare_id!("Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo");
}

solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
use {solana_instruction::Instruction, solana_pubkey::Pubkey};

/// Build a memo instruction, possibly signed
///
Expand All @@ -32,27 +26,5 @@ solana_pubkey::declare_id!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr");
/// 0. `..0+N` `[signer]` Expected signers; if zero provided, instruction will
/// be processed as a normal, unsigned spl-memo
pub fn build_memo(memo: &[u8], signer_pubkeys: &[&Pubkey]) -> Instruction {
Instruction {
program_id: id(),
accounts: signer_pubkeys
.iter()
.map(|&pubkey| AccountMeta::new_readonly(*pubkey, true))
.collect(),
data: memo.to_vec(),
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_build_memo() {
let signer_pubkey = Pubkey::new_unique();
let memo = "🐆".as_bytes();
let instruction = build_memo(memo, &[&signer_pubkey]);
assert_eq!(memo, instruction.data);
assert_eq!(instruction.accounts.len(), 1);
assert_eq!(instruction.accounts[0].pubkey, signer_pubkey);
}
spl_memo_interface::instruction::build_memo(&id(), memo, signer_pubkeys)
}
13 changes: 0 additions & 13 deletions scripts/program/build.mjs

This file was deleted.

29 changes: 0 additions & 29 deletions scripts/program/format.mjs

This file was deleted.

20 changes: 0 additions & 20 deletions scripts/program/test.mjs

This file was deleted.

File renamed without changes.
10 changes: 10 additions & 0 deletions scripts/rust/build-sbf.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env zx
import 'zx/globals';
import {
cliArguments,
workingDirectory,
} from '../utils.mjs';

const [folder, ...args] = cliArguments();
const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml');
await $`cargo-build-sbf --manifest-path ${manifestPath} ${args}`;
23 changes: 23 additions & 0 deletions scripts/rust/format.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env zx
import 'zx/globals';
import {
cliArguments,
getToolchainArgument,
partitionArguments,
popArgument,
workingDirectory,
} from '../utils.mjs';

const [folder, ...formatArgs] = cliArguments();

const fix = popArgument(formatArgs, '--fix');
const [cargoArgs, fmtArgs] = partitionArguments(formatArgs, '--');
const toolchain = getToolchainArgument('format');

const manifestPath = path.join(workingDirectory, folder, 'Cargo.toml');

if (fix) {
await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- ${fmtArgs}`;
} else {
await $`cargo ${toolchain} fmt --manifest-path ${manifestPath} ${cargoArgs} -- --check ${fmtArgs}`;
}
Loading