Add rustdocs (#39)

This commit is contained in:
Jack May 2020-06-17 11:25:19 -07:00 committed by GitHub
parent f571493404
commit 9214d08be6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 197 additions and 134 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
bin
*/target/
.vscode
package-lock.json

View File

@ -24,7 +24,6 @@ install:
- clang-7 --version
- nvm install node
- node --version
- ./do.sh update
jobs:
include:

View File

@ -4,5 +4,7 @@ cd "$(dirname "$0")/.."
set -e
./do.sh update
./do.sh build memo
./do.sh doc memo
./do.sh test memo

View File

@ -1,11 +1,21 @@
#!/usr/bin/env bash
cd "$(dirname "$0")/../token/js"
set -e
npm install
npm run build:program
npm run test
npm run cluster:devnet
npm run start
(
cd "$(dirname "$0")/.."
./do.sh update
./do.sh build token
./do.sh doc token
./do.sh test token
)
(
cd "$(dirname "$0")/../token/js"
npm install
npm run build:program
npm run cluster:devnet
npm run start
)

1
do.sh
View File

@ -69,6 +69,7 @@ perform_action() {
update)
mkdir -p $sdkParentDir
./bpf-sdk-install.sh $sdkParentDir
./do.sh clean
;;
dump)
# Dump depends on tools that are not installed by default and must be installed manually

View File

@ -1 +1,5 @@
#![deny(missing_docs)]
//! A simple program that accepts a string of encoded characters and verifies that it parses. Currently handles UTF-8.
pub mod processor;

View File

@ -1,3 +1,5 @@
//! Program entrypoint definitions
use solana_sdk::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult, program_error::ProgramError,
pubkey::Pubkey,
@ -24,18 +26,12 @@ mod tests {
let program_id = Pubkey::new(&[0; 32]);
let string = b"letters and such";
assert_eq!(
Ok(()),
process_instruction(&program_id, &[], string)
);
assert_eq!(Ok(()), process_instruction(&program_id, &[], string));
let emoji = "🐆".as_bytes();
let bytes = [0xF0, 0x9F, 0x90, 0x86];
assert_eq!(emoji, bytes);
assert_eq!(
Ok(()),
process_instruction(&program_id, &[], &emoji)
);
assert_eq!(Ok(()), process_instruction(&program_id, &[], &emoji));
let mut bad_utf8 = bytes;
bad_utf8[3] = 0xFF; // Invalid UTF-8 byte

3
package-lock.json generated Normal file
View File

@ -0,0 +1,3 @@
{
"lockfileVersion": 1
}

56
token/Cargo.lock generated
View File

@ -169,15 +169,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8b15b261814f992e33760b1fca9fe8b693d8a65299f20c9901688636cfb746"
dependencies = [
"proc-macro2 1.0.18",
"quote 1.0.6",
"syn 1.0.30",
"quote 1.0.7",
"syn 1.0.31",
]
[[package]]
name = "num-traits"
version = "0.2.11"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
]
@ -227,40 +227,40 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.6"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2 1.0.18",
]
[[package]]
name = "serde"
version = "1.0.111"
version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d"
checksum = "736aac72d1eafe8e5962d1d1c3d99b0df526015ba40915cb3c49d042e92ec243"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_bytes"
version = "0.11.4"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf487fbf5c6239d7ea2ff8b10cb6b811cd4b5080d1c2aeed1dec18753c06e10"
checksum = "16ae07dd2f88a366f15bd0632ba725227018c69a1c8550a927324f8eb8368bb9"
dependencies = [
"serde",
]
[[package]]
name = "serde_derive"
version = "1.0.111"
version = "1.0.112"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250"
checksum = "bf0343ce212ac0d3d6afd9391ac8e9c9efe06b533c8d33f660f6390cc4093f57"
dependencies = [
"proc-macro2 1.0.18",
"quote 1.0.6",
"syn 1.0.30",
"quote 1.0.7",
"syn 1.0.31",
]
[[package]]
@ -301,18 +301,18 @@ dependencies = [
[[package]]
name = "solana-sdk-bpf-test"
version = "1.2.0"
version = "1.3.0"
[[package]]
name = "solana-sdk-macro"
version = "1.2.0"
version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf2fbfa29c0829943296a8bb907206692593fdead311ff302c4303c43e55b6d"
checksum = "9e76f29c489add350172c11ec1232b060276feffdf5344ef66cbd4dd844ada7a"
dependencies = [
"bs58",
"proc-macro2 1.0.18",
"quote 1.0.6",
"syn 1.0.30",
"quote 1.0.7",
"syn 1.0.31",
]
[[package]]
@ -345,33 +345,33 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.30"
version = "1.0.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93a56fabc59dce20fe48b6c832cc249c713e7ed88fa28b0ee0a3bfcaae5fe4e2"
checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6"
dependencies = [
"proc-macro2 1.0.18",
"quote 1.0.6",
"quote 1.0.7",
"unicode-xid 0.2.0",
]
[[package]]
name = "thiserror"
version = "1.0.19"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b13f926965ad00595dd129fa12823b04bbf866e9085ab0a5f2b05b850fbfc344"
checksum = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.19"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "893582086c2f98cde18f906265a65b5030a074b1046c674ae898be6519a7f479"
checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
dependencies = [
"proc-macro2 1.0.18",
"quote 1.0.6",
"syn 1.0.30",
"quote 1.0.7",
"syn 1.0.31",
]
[[package]]

View File

@ -6,7 +6,7 @@
"type": "git",
"url": "https://github.com/solana-labs/solana-program-library"
},
"testnetDefaultChannel": "v1.2.0",
"testnetDefaultChannel": "v1.2.2",
"scripts": {
"start": "babel-node cli/main.js",
"lint": "npm run pretty && eslint .",
@ -14,7 +14,7 @@
"flow": "flow",
"flow:watch": "watch 'flow' . --wait=1 --ignoreDirectoryPattern=/doc/",
"lint:watch": "watch 'npm run lint:fix' . --wait=1",
"bpf-sdk:update": "solana-bpf-sdk-install ../../bin && npm run clean:program",
"bpf-sdk:update": "mkdir -p ../../bin && solana-bpf-sdk-install ../../bin && npm run clean:program",
"build:program": "../../do.sh build token",
"clean:program": "../../do.sh clean token",
"test:program": "../../do.sh test token",

View File

@ -1,3 +1,5 @@
//! Error types
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use solana_sdk::{
@ -7,20 +9,28 @@ use solana_sdk::{
};
use thiserror::Error;
/// Errors that may be returned by the Token program
#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
pub enum TokenError {
/// Insufficient funds for the operation requested.
#[error("insufficient funds")]
InsufficientFunds,
/// Token types of the provided accounts don't match.
#[error("token mismatch")]
TokenMismatch,
/// A delegate is needed but the account provided is not a delegate.
#[error("not a delegate")]
NotDelegate,
/// Owner was not a signing member of the instruction.
#[error("no owner")]
NoOwner,
/// This token's supply is fixed and new tokens cannot be minted.
#[error("fixed supply")]
FixedSupply,
/// The account cannot be initialized because it is already being used.
#[error("AlreadyInUse")]
AlreadyInUse,
/// Cannot transfer token directly to a delegate account.
#[error("Destination is a delegate")]
DestinationIsDelegate,
}

77
token/src/instruction.rs Normal file
View File

@ -0,0 +1,77 @@
//! Instruction types
/// Specifies the financial specifics of a token.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct TokenInfo {
/// Total supply of tokens.
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place in the total supply.
pub decimals: u64,
}
/// Instructions supported by the token program.
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum Instruction {
/// Creates a new token and deposit all the newly minted tokens in an account.
///
/// # Accounts expected by this instruction:
///
/// 0. [writable, signer] New token to create.
/// 1. [writable] Account to hold all the newly minted tokens.
/// 2. Optional: [] Owner of the token, if present allows further minting of tokens.
NewToken(TokenInfo),
/// Creates a new account. The new account can either hold tokens or be a delegate
/// for another account.
///
/// # Accounts expected by this instruction:
///
/// 0. [writable, signer] New account being created.
/// 1. [] Owner of the new account.
/// 2. [] Token this account will be associated with.
/// 3. Optional: [] Source account that this account will be a delegate for.
NewAccount,
/// Transfers tokens from one account to another either directly or via a delegate.
///
/// # Accounts expected by this instruction:
///
/// 0. `[signer]` Owner of the source account.
/// 1. `[writable]` Source/Delegate account.
/// 2. `[writable]` Destination account.
/// 3. Optional: `[writable]` Source account if key 1 is a delegate account.
Transfer(u64),
/// Approves a delegate. A delegate account is given the authority to transfer
/// another accounts tokens without the other account's owner signing the transfer.
///
/// # Accounts expected by this instruction:
///
/// 0. [signer] Owner of the source account.
/// 1. [] Source account.
/// 2. [writable] Delegate account.
Approve(u64),
/// Sets a new owner of an account.
///
/// # Accounts expected by this instruction:
///
/// 0. [signer] Current owner of the account.
/// 1. [writable] account to change the owner of.
/// 2. [] New owner of the account.
SetOwner,
/// Mints new tokens to an account.
///
/// # Accounts expected by this instruction:
///
/// 0. [signer] Owner of the token.
/// 1. [writable] Token to mint.
/// 2. [writable] Account to mint tokens to.
MintTo(u64),
/// Burns tokens by removing them from an account and the total supply.
///
/// # Accounts expected by this instruction:
///
/// 0. [signer] Owner of the account to burn from.
/// 1. [writable] Account to burn from.
/// 2. [writable] Token being burned.
Burn(u64),
}

View File

@ -1,3 +1,8 @@
#![deny(missing_docs)]
//! An ERC20-like Token program for the Solana blockchain
pub mod error;
pub mod instruction;
pub mod processor;
pub mod state;

View File

@ -1,3 +1,5 @@
//! Program entrypoint definitions
use crate::{error::TokenError, state::State};
use solana_sdk::{
account_info::AccountInfo, entrypoint, entrypoint::ProgramResult,
@ -16,4 +18,4 @@ fn process_instruction<'a>(
return Err(error);
}
Ok(())
}
}

View File

@ -1,69 +1,67 @@
use crate::error::TokenError;
//! State transition types
use crate::{
error::TokenError,
instruction::{Instruction, TokenInfo},
};
use solana_sdk::{
account_info::AccountInfo, entrypoint::ProgramResult, info, program_error::ProgramError,
program_utils::next_account_info, pubkey::Pubkey,
};
use std::mem::size_of;
/// Represents a unique token type that all like accounts must be
/// associated with
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct TokenInfo {
/// Total supply of tokens
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place in the total supply
pub decimals: u64,
}
/// Represents a unique token type that all like token accounts must be
/// associated with
/// Represents a token type identified and identified by its public key. Accounts
/// are associated with a specific token type and only accounts with
/// matching types my inter-opt.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Token {
/// Total supply of tokens
/// The total supply of tokens.
pub info: TokenInfo,
/// Owner of this token
/// Optional token owner, used to mint new tokens. The owner may only
/// be provided during token creation. If no owner is present then the token
/// has a fixed supply and no further tokens may be minted.
pub owner: Option<Pubkey>,
}
/// Delegation details
/// Delegation details.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct AccountDelegate {
/// The source account for the tokens
/// The source account for the tokens.
pub source: Pubkey,
/// The original amount that this delegate account was authorized to spend up to
/// The original maximum amount that this delegate account was authorized to spend.
pub original_amount: u64,
}
/// Account that holds or may delegate tokens
/// Account that holds or may delegate tokens.
#[repr(C)]
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Account {
/// The kind of token this account holds
/// The type of token this account holds.
pub token: Pubkey,
/// Owner of this account
/// Owner of this account.
pub owner: Pubkey,
/// Amount of tokens this account holds
/// Amount of tokens this account holds.
pub amount: u64,
/// If `delegate` None, `amount` belongs to this account.
/// If `delegate` is None, `amount` belongs to this account.
/// If `delegate` is Option<_>, `amount` represents the remaining allowance
/// of tokens that may be transferred from the `source` account.
/// of tokens this delegate is authorized to transfer from the `source` account.
pub delegate: Option<AccountDelegate>,
}
/// Possible states to accounts owned by the token program
/// Token program states.
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum State {
/// Unallocated
/// Unallocated state, may be initialized into another state.
Unallocated,
/// Specifies a type of token
/// A token type.
Token(Token),
/// account
/// An account that holds an amount of tokens or was delegated the authority to transfer
/// tokens on behalf of another account.
Account(Account),
/// Invalid state
/// Invalid state, cannot be modified by the token program.
Invalid,
}
impl Default for State {
@ -72,64 +70,8 @@ impl Default for State {
}
}
/// Instructions supported by the token program
#[repr(C)]
#[derive(Clone, Debug, PartialEq)]
pub enum Instruction {
/// Create a new token
///
/// # Account references
/// 0. [WRITE, SIGNER] New token
/// 1. [WRITE] Account to hold the minted tokens
/// 2. Optional: [] Owner of the token
NewToken(TokenInfo),
/// Create a new account to hold tokens
///
/// # Account references
/// 0. [WRITE, SIGNER] New account
/// 1. [] Owner of the account
/// 2. [] Token this account is associated with
/// 3. Optional: [] Source account that this account is a delegate for
NewAccount,
/// Transfer tokens
///
/// # Account references
/// 0. [SIGNER] Owner of the source account
/// 1. [WRITE] Source/Delegate account
/// 2. [WRITE] Destination account
/// 3. Optional: [WRITE] Source account if key 1 is a delegate
Transfer(u64),
/// Approve a delegate
///
/// # Account references
/// 0. [SIGNER] Owner of the source account
/// 1. [] Source account
/// 2. [WRITE] Delegate account
Approve(u64),
/// Set a new owner of an account
///
/// # Account references
/// 0. [SIGNER] Current owner of the account
/// 1. [WRITE] account
/// 2. [] New owner of the account
SetOwner,
/// Mint new tokens
///
/// # Account references
/// 0. [SIGNER] Owner of the account
/// 1. [WRITE] Token to mint
/// 2. [WRITE] Account to mint to
MintTo(u64),
/// Set a new owner of an account
///
/// # Account references
/// 0. [SIGNER] Owner of the account to burn from
/// 1. [WRITE] Account to burn from
/// 2. [WRITE] Token being burned
Burn(u64),
}
impl<'a> State {
/// Processes a [NewToken](enum.Instruction.html) instruction.
pub fn process_new_token<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
info: TokenInfo,
@ -168,6 +110,7 @@ impl<'a> State {
State::Token(Token { info, owner }).serialize(&mut token_account_info.data.borrow_mut())
}
/// Processes a [NewAccount](enum.Instruction.html) instruction.
pub fn process_new_account<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
) -> ProgramResult {
@ -201,6 +144,7 @@ impl<'a> State {
State::Account(token_account).serialize(&mut new_account_data)
}
/// Processes a [Transfer](enum.Instruction.html) instruction.
pub fn process_transfer<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
amount: u64,
@ -263,6 +207,7 @@ impl<'a> State {
Ok(())
}
/// Processes an [Approve](enum.Instruction.html) instruction.
pub fn process_approve<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
amount: u64,
@ -313,6 +258,7 @@ impl<'a> State {
Ok(())
}
/// Processes a [SetOwner](enum.Instruction.html) instruction.
pub fn process_set_owner<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
) -> ProgramResult {
@ -351,6 +297,7 @@ impl<'a> State {
Ok(())
}
/// Processes a [MintTo](enum.Instruction.html) instruction.
pub fn process_mintto<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
amount: u64,
@ -400,6 +347,7 @@ impl<'a> State {
Ok(())
}
/// Processes a [Burn](enum.Instruction.html) instruction.
pub fn process_burn<I: Iterator<Item = &'a AccountInfo<'a>>>(
account_info_iter: &mut I,
amount: u64,
@ -470,6 +418,7 @@ impl<'a> State {
Ok(())
}
/// Processes an [Instruction](enum.Instruction.html).
pub fn process(
_program_id: &Pubkey,
accounts: &'a [AccountInfo<'a>],
@ -510,6 +459,7 @@ impl<'a> State {
}
}
/// Deserializes a byte buffer into a Token Program [State](struct.State.html)
pub fn deserialize(input: &'a [u8]) -> Result<Self, ProgramError> {
if input.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);
@ -537,6 +487,7 @@ impl<'a> State {
})
}
/// Serializes Token Program [State](struct.State.html) into a byte buffer
pub fn serialize(self: &Self, output: &mut [u8]) -> ProgramResult {
if output.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);
@ -568,6 +519,7 @@ impl<'a> State {
}
impl Instruction {
/// Deserializes a byte buffer into an [Instruction](enum.Instruction.html)
pub fn deserialize(input: &[u8]) -> Result<Self, ProgramError> {
if input.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);
@ -619,6 +571,7 @@ impl Instruction {
})
}
/// Serializes an [Instruction](enum.Instruction.html) into a byte buffer
pub fn serialize(self: &Self, output: &mut [u8]) -> ProgramResult {
if output.len() < size_of::<u8>() {
return Err(ProgramError::InvalidAccountData);