Skip to content

Commit 2e9548d

Browse files
add default account state mint
1 parent 198a6ee commit 2e9548d

File tree

6 files changed

+268
-0
lines changed

6 files changed

+268
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
3+
# This script is for quick building & deploying of the program.
4+
# It also serves as a reference for the commands used for building & deploying Solana programs.
5+
# Run this bad boy with "bash cicd.sh" or "./cicd.sh"
6+
7+
cargo build-bpf --manifest-path=./program/Cargo.toml
8+
solana program deploy ./program/target/deploy/program.so
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"scripts": {
3+
"test": "yarn run ts-mocha -p ./tsconfig.json -t 1000000 ./tests/test.ts"
4+
},
5+
"dependencies": {
6+
"@metaplex-foundation/mpl-token-metadata": "^2.5.2",
7+
"@solana/spl-token": "^0.3.7",
8+
"@solana/web3.js": "^1.73.0",
9+
"borsh": "^0.7.0",
10+
"buffer": "^6.0.3",
11+
"fs": "^0.0.1-security"
12+
},
13+
"devDependencies": {
14+
"@types/bn.js": "^5.1.0",
15+
"@types/chai": "^4.3.1",
16+
"@types/mocha": "^9.1.1",
17+
"chai": "^4.3.4",
18+
"mocha": "^9.0.3",
19+
"ts-mocha": "^10.0.0",
20+
"typescript": "^4.3.5"
21+
}
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[package]
2+
name = "program"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
borsh = "0.9.3"
8+
borsh-derive = "0.9.1"
9+
solana-program = "1.10.26"
10+
spl-token = { version="3.3.0", features = [ "no-entrypoint" ] }
11+
spl-associated-token-account = { version="1.0.5", features = [ "no-entrypoint" ] }
12+
spl-token-2022 = {version = "0.6.1", features = [ "no-entrypoint" ] }
13+
14+
[lib]
15+
crate-type = ["cdylib", "lib"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use {
2+
borsh::{BorshDeserialize, BorshSerialize},
3+
solana_program::{
4+
account_info::{next_account_info, AccountInfo},
5+
entrypoint,
6+
entrypoint::ProgramResult,
7+
msg,
8+
program::invoke,
9+
pubkey::Pubkey,
10+
rent::Rent,
11+
system_instruction,
12+
sysvar::Sysvar,
13+
},
14+
spl_token_2022::{
15+
extension::{
16+
default_account_state::instruction::{
17+
initialize_default_account_state, update_default_account_state,
18+
},
19+
ExtensionType,
20+
},
21+
instruction as token_instruction,
22+
state::AccountState,
23+
state::Mint,
24+
},
25+
};
26+
27+
#[derive(BorshSerialize, BorshDeserialize, Debug)]
28+
pub struct CreateTokenArgs {
29+
pub token_decimals: u8,
30+
}
31+
32+
entrypoint!(process_instruction);
33+
34+
fn process_instruction(
35+
_program_id: &Pubkey,
36+
accounts: &[AccountInfo],
37+
instruction_data: &[u8],
38+
) -> ProgramResult {
39+
let args = CreateTokenArgs::try_from_slice(instruction_data)?;
40+
41+
let accounts_iter = &mut accounts.iter();
42+
43+
let mint_account = next_account_info(accounts_iter)?;
44+
let mint_authority = next_account_info(accounts_iter)?;
45+
let payer = next_account_info(accounts_iter)?;
46+
let rent = next_account_info(accounts_iter)?;
47+
let system_program = next_account_info(accounts_iter)?;
48+
let token_program = next_account_info(accounts_iter)?;
49+
50+
// Find the size for the account with the Extension
51+
let space = ExtensionType::get_account_len::<Mint>(&[ExtensionType::DefaultAccountState]);
52+
53+
// Get the required rent exemption amount for the account
54+
let rent_required = Rent::get()?.minimum_balance(space);
55+
56+
// Create the account for the Mint and allocate space
57+
msg!("Mint account address : {}", mint_account.key);
58+
invoke(
59+
&system_instruction::create_account(
60+
&payer.key,
61+
mint_account.key,
62+
rent_required,
63+
space as u64,
64+
token_program.key,
65+
),
66+
&[
67+
mint_account.clone(),
68+
payer.clone(),
69+
system_program.clone(),
70+
token_program.clone(),
71+
],
72+
)?;
73+
74+
// Initialize the Default Account State as Frozen
75+
invoke(
76+
&initialize_default_account_state(
77+
token_program.key,
78+
mint_account.key,
79+
&AccountState::Frozen,
80+
)
81+
.unwrap(),
82+
&[
83+
mint_account.clone(),
84+
token_program.clone(),
85+
system_program.clone(),
86+
],
87+
)?;
88+
89+
// Initialize the Token Mint
90+
invoke(
91+
&token_instruction::initialize_mint(
92+
&token_program.key,
93+
&mint_account.key,
94+
&mint_authority.key,
95+
Some(&mint_authority.key),
96+
args.token_decimals,
97+
)?,
98+
&[
99+
mint_account.clone(),
100+
mint_authority.clone(),
101+
token_program.clone(),
102+
rent.clone(),
103+
],
104+
)?;
105+
106+
// Update the Default Account State to Initialized
107+
invoke(
108+
&update_default_account_state(
109+
token_program.key,
110+
mint_account.key,
111+
payer.key,
112+
&[&payer.key],
113+
&AccountState::Initialized,
114+
)
115+
.unwrap(),
116+
&[
117+
mint_account.clone(),
118+
payer.clone(),
119+
token_program.clone(),
120+
system_program.clone(),
121+
],
122+
)?;
123+
124+
msg!("Mint created!");
125+
126+
Ok(())
127+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { PROGRAM_ID as TOKEN_METADATA_PROGRAM_ID } from "@metaplex-foundation/mpl-token-metadata";
2+
import {
3+
Connection,
4+
Keypair,
5+
PublicKey,
6+
SystemProgram,
7+
SYSVAR_RENT_PUBKEY,
8+
TransactionInstruction,
9+
Transaction,
10+
sendAndConfirmTransaction,
11+
} from "@solana/web3.js";
12+
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
13+
import * as borsh from "borsh";
14+
import { Buffer } from "buffer";
15+
16+
function createKeypairFromFile(path: string): Keypair {
17+
return Keypair.fromSecretKey(
18+
Buffer.from(JSON.parse(require("fs").readFileSync(path, "utf-8")))
19+
);
20+
}
21+
22+
class Assignable {
23+
constructor(properties) {
24+
Object.keys(properties).map((key) => {
25+
return (this[key] = properties[key]);
26+
});
27+
}
28+
}
29+
30+
class CreateTokenArgs extends Assignable {
31+
toBuffer() {
32+
return Buffer.from(borsh.serialize(CreateTokenArgsSchema, this));
33+
}
34+
}
35+
const CreateTokenArgsSchema = new Map([
36+
[
37+
CreateTokenArgs,
38+
{
39+
kind: "struct",
40+
fields: [["token_decimals", "u8"]],
41+
},
42+
],
43+
]);
44+
45+
describe("Create Token", async () => {
46+
const connection = new Connection(
47+
`https://api.devnet.solana.com/`,
48+
"confirmed"
49+
);
50+
const payer = createKeypairFromFile(
51+
require("os").homedir() + "/.config/solana/id.json"
52+
);
53+
const program = createKeypairFromFile(
54+
"./program/target/deploy/program-keypair.json"
55+
);
56+
57+
it("Create a Token-22 SPL-Token !", async () => {
58+
const mintKeypair: Keypair = Keypair.generate();
59+
60+
const instructionData = new CreateTokenArgs({
61+
token_decimals: 9,
62+
});
63+
64+
const instruction = new TransactionInstruction({
65+
keys: [
66+
{ pubkey: mintKeypair.publicKey, isSigner: true, isWritable: true }, // Mint account
67+
{ pubkey: payer.publicKey, isSigner: false, isWritable: true }, // Mint authority account
68+
{ pubkey: payer.publicKey, isSigner: true, isWritable: true }, // Transaction Payer
69+
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, // Rent account
70+
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }, // System program
71+
{ pubkey: TOKEN_2022_PROGRAM_ID, isSigner: false, isWritable: false }, // Token program
72+
],
73+
programId: program.publicKey,
74+
data: instructionData.toBuffer(),
75+
});
76+
77+
const signature = await sendAndConfirmTransaction(
78+
connection,
79+
new Transaction().add(instruction),
80+
[payer, mintKeypair]
81+
);
82+
83+
console.log(`Token Mint Address: `, mintKeypair.publicKey.toBase58());
84+
console.log(`Transaction Signature: `, signature);
85+
});
86+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"compilerOptions": {
3+
"types": ["mocha", "chai"],
4+
"typeRoots": ["./node_modules/@types"],
5+
"lib": ["es2015"],
6+
"module": "commonjs",
7+
"target": "es6",
8+
"esModuleInterop": true
9+
}
10+
}

0 commit comments

Comments
 (0)