Skip to content

Instantly share code, notes, and snippets.

@munanadi
Created September 1, 2021 16:06
Show Gist options
  • Select an option

  • Save munanadi/9f5fd4b1db9531727309a68923feb9a7 to your computer and use it in GitHub Desktop.

Select an option

Save munanadi/9f5fd4b1db9531727309a68923feb9a7 to your computer and use it in GitHub Desktop.
Create and Mint tokens for a given wallet.
import React, { useState, useEffect } from 'react'
import { Connection, PublicKey, Keypair, LAMPORTS_PER_SOL, SystemProgram, TransactionInstruction, SYSVAR_RENT_PUBKEY, Transaction } from '@solana/web3.js';
import { ASSOCIATED_TOKEN_PROGRAM_ID, MintLayout, AccountLayout, Token, TOKEN_PROGRAM_ID, u64 } from '@solana/spl-token';
import bs58 from 'bs58';
import { Buffer } from 'buffer';
import * as BufferLayout from 'buffer-layout';
// Need to deploy the contract and figure out how to create the account for data storage
const VOTING_CONTRACT_PROGRAMID = "";
const VOTING_CONTRACT_ACCOUNT = "";
const seed = "something";
function App() {
const [walletBalance, setWalletBalance] = useState(null);
const [address, setAddress] = useState(null);
const [mintAddress, setMintAddress] = useState(null);
const [tokenAccount, setTokenAccount] = useState(null);
const [numberOfTokens, setNumberOfTokens] = useState(0);
const createTokens = async () => {
let connection = getConnection();
// create new Account
const mintAccount = new Keypair();
try {
const createAccIx = SystemProgram.createAccount({
fromPubkey: getPublicKey(),
newAccountPubkey: mintAccount.publicKey,
lamports: LAMPORTS_PER_SOL,
space: MintLayout.span,
programId: TOKEN_PROGRAM_ID,
})
console.log(createAccIx)
// create mint init instruction
const createMintIx = Token.createInitMintInstruction(
TOKEN_PROGRAM_ID,
mintAccount.publicKey,
1,
getPublicKey(),
getPublicKey() ? getPublicKey() : null
)
console.log(createMintIx)
// Construct the transaction
let tx = new Transaction().add(createAccIx, createMintIx);
// Signature of the fee payer
tx.feePayer = getPublicKey();
tx.recentBlockhash = (await getRecentBlockhash()).blockhash;
console.log("Signatures done after this")
tx.sign(mintAccount);
const signedTransaction = await window.solana.request({
method: "signTransaction",
params: {
message: bs58.encode(tx.serializeMessage()),
},
});
// const signedTransaction = await window.solana.signTransaction(tx.serializeMessage());
console.log(signedTransaction);
const signature = bs58.decode(signedTransaction.signature);
const publicKey = new PublicKey(signedTransaction.publicKey);
tx.addSignature(publicKey, signature);
console.log(tx);
setMintAddress(mintAccount.publicKey.toBase58())
console.log(tx);
let si = await connection.sendRawTransaction(tx.serialize());
const hash = await connection.confirmTransaction(si);
console.log(hash);
} catch (e) {
setMintAddress(null);
alert(e.message);
console.log(e, e.message);
}
}
const getRecentBlockhash = async () => {
let connection = getConnection();
let blockhash = await connection.getRecentBlockhash("max");
return blockhash;
}
const getConnection = () => {
let connection = new Connection("http://localhost:8899", "confirmed");
return connection;
}
const getPublicKey = () => {
// Okay so I had my localnet offline and thus it was failing. Nothing to do with
// Publickey or Keypair
let userAddress = new PublicKey(window.solana.publicKey.toString());
return userAddress;
}
const handleRequestAirdrop = async () => {
// handle error case later -> Also one behind. Maybe react thing?
let connection = getConnection();
await connection.requestAirdrop(getPublicKey(), LAMPORTS_PER_SOL * 0.1)
getBalance();
}
const getBalance = async () => {
let connection = getConnection();
const res = await connection.getBalance(getPublicKey());
// console.log(res);
setWalletBalance(res);
}
// Just create the address of PDA here but init the account when you vote.
const getDerivedAccountAddress = async () => {
let checkAccountPubkey = await PublicKey.createWithSeed(getPublicKey(), seed, VOTING_CONTRACT_PROGRAMID);
return checkAccountPubkey;
}
const connectToWallet = async () => {
await window.solana.connect()
}
const handleConnectWallet = async () => {
// Check if phantom is installed or not and prompt to install it.
if (window.solana && window.solana.isPhantom) {
await connectToWallet();
// update address and balance of the wallet
setAddress(window.solana.publicKey.toString());
getBalance();
// getDerivedAccountAddress();
// console.log(getConnection())
} else {
alert("Phantom wallet is not installed. Please install.");
window.open("https://phantom.app/", "_target");
}
}
const createAssociatedTokenAccount = async () => {
let ownerAccount = getPublicKey();
let mintAccount = new PublicKey(`${mintAddress}`);
let associatedAccountAddress = (await PublicKey.createProgramAddress(
[ownerAccount.toBuffer(), mintAccount.toBuffer(), TOKEN_PROGRAM_ID.toBuffer()],
ASSOCIATED_TOKEN_PROGRAM_ID
));
console.log(associatedAccountAddress.toBase58())
let ix = new TransactionInstruction({
programId: ASSOCIATED_TOKEN_PROGRAM_ID,
data: Buffer.from([]),
keys: [
{ pubkey: ownerAccount, isSigner: true, isWritable: true },
{ pubkey: associatedAccountAddress, isSigner: false, isWritable: true },
{ pubkey: ownerAccount, isSigner: false, isWritable: false },
{ pubkey: mintAccount, isSigner: false, isWritable: false },
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
{ pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
]
});
let tx = new Transaction().add(ix);
tx.feePayer = getPublicKey();
tx.recentBlockhash = (await getRecentBlockhash()).blockhash;
const signedTransaction = await window.solana.request({
method: "signTransaction",
params: {
message: bs58.encode(tx.serializeMessage()),
},
});
// console.log(signedTransaction);
const signature = bs58.decode(signedTransaction.signature);
const publicKey = new PublicKey(signedTransaction.publicKey);
tx.addSignature(publicKey, signature);
let connection = getConnection();
console.log(tx);
let si = await connection.sendRawTransaction(tx.serialize());
const hash = await connection.confirmTransaction(si);
console.log(hash);
setTokenAccount(associatedAccountAddress.toBase58());
}
const createTokenAccount = async () => {
const tokenMintPubkey = new PublicKey(`${mintAddress}`);
const ownerPubkey = getPublicKey();
const connection = getConnection();
const balanceNeeded = await Token.getMinBalanceRentForExemptAccount(
connection
);
const newAccount = new Keypair();
const createAccIx = SystemProgram.createAccount({
fromPubkey: ownerPubkey,
newAccountPubkey: newAccount.publicKey,
lamports: balanceNeeded,
space: AccountLayout.span,
programId: TOKEN_PROGRAM_ID
});
const createTokenAccountIx = Token.createInitAccountInstruction(
TOKEN_PROGRAM_ID,
tokenMintPubkey,
newAccount.publicKey,
ownerPubkey
);
let tx = new Transaction().add(createAccIx, createTokenAccountIx);
tx.feePayer = ownerPubkey;
tx.recentBlockhash = (await getRecentBlockhash()).blockhash;
tx.sign(newAccount);
const signedTransaction = await window.solana.request({
method: "signTransaction",
params: {
message: bs58.encode(tx.serializeMessage()),
},
});
// console.log(signedTransaction);
const signature = bs58.decode(signedTransaction.signature);
const publicKey = new PublicKey(signedTransaction.publicKey);
tx.addSignature(publicKey, signature);
let si = await connection.sendRawTransaction(tx.serialize());
const hash = await connection.confirmTransaction(si);
console.log(hash);
setTokenAccount(newAccount.publicKey.toBase58());
}
const mintTokens = async () => {
const destinationAcc = new PublicKey(`${tokenAccount}`);
const tokenMintPubkey = new PublicKey(`${mintAddress}`)
const connection = getConnection();
const ownerPubkey = getPublicKey();
let amount = new u64(numberOfTokens, 10);
console.log(amount);
// return;
const mintIx = Token.createMintToInstruction(
TOKEN_PROGRAM_ID,
tokenMintPubkey,
destinationAcc,
ownerPubkey,
[],
amount
);
let tx = new Transaction().add(mintIx);
tx.feePayer = ownerPubkey;
tx.recentBlockhash = (await getRecentBlockhash()).blockhash;
const signedTransaction = await window.solana.request({
method: "signTransaction",
params: {
message: bs58.encode(tx.serializeMessage()),
},
});
// console.log(signedTransaction);
const signature = bs58.decode(signedTransaction.signature);
const publicKey = new PublicKey(signedTransaction.publicKey);
tx.addSignature(publicKey, signature);
console.log(tx);
let si = await connection.sendRawTransaction(tx.serialize());
const hash = await connection.confirmTransaction(si);
console.log(hash);
}
const createMultiSigAccount = async () => {
// Create a local account in browser to sign with client account for 2:2 multisig
let m = 2;
let connection = getConnection();
let secondAcount = new Keypair();
console.log(secondAcount.publicKey.toBase58(), "is the public key of the other account co signing this.")
console.log(secondAcount.secretKey.toString())
let multisigAcc = new Keypair();
console.log(multisigAcc.publicKey.toBase58(), "is the public key of the multisig account")
const balanceNeeded = await Token.getMinBalanceRentForExemptMultisig(
getConnection()
);
const transaction = new Transaction();
transaction.add(
SystemProgram.createAccount({
fromPubkey: getPublicKey(),
newAccountPubkey: multisigAcc.publicKey,
lamports: balanceNeeded,
space: MintLayout.span,
programId: TOKEN_PROGRAM_ID,
}),
);
// create the new account
let keys = [
{ pubkey: multisigAcc.publicKey, isSigner: false, isWritable: true },
{ pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false },
];
keys.push({ pubkey: getPublicKey(), isSigner: false, isWritable: false });
keys.push({ pubkey: secondAcount.publicKey, isSigner: false, isWritable: false });
const dataLayout = BufferLayout.struct([
BufferLayout.u8('instruction'),
BufferLayout.u8('m'),
]);
const data = Buffer.alloc(dataLayout.span);
dataLayout.encode(
{
instruction: 2, // InitializeMultisig instruction
m,
},
data,
);
transaction.add({
keys,
programId: TOKEN_PROGRAM_ID,
data,
});
// Send the two instructions
transaction.feePayer = getPublicKey();
transaction.recentBlockhash = (await getRecentBlockhash()).blockhash;
transaction.sign(multisigAcc);
const signedTransaction = await window.solana.request({
method: "signTransaction",
params: {
message: bs58.encode(transaction.serializeMessage()),
},
});
// console.log(signedTransaction);
const signature = bs58.decode(signedTransaction.signature);
const publicKey = new PublicKey(signedTransaction.publicKey);
transaction.addSignature(publicKey, signature);
let si = await connection.sendRawTransaction(transaction.serialize());
const hash = await connection.confirmTransaction(si);
console.log(hash);
}
return (
<div className="App">
{console.log("Render called")}
<h1>Multisig Custom Tokens</h1>
{!address && <p>Connect your wallet</p> && <button onClick={handleConnectWallet}>Connect Wallet</button>}
{address && <p>{address} is the user address that is connected right now!</p>}
{(walletBalance !== null) && <p>{walletBalance / LAMPORTS_PER_SOL} SOL is the amount of money this connected user has</p>}
{address && <button onClick={handleRequestAirdrop}>Request Airdrop</button>}
<br />
<div>
<h2>Create Custom Tokens</h2>
<button onClick={createTokens.bind(this)}>Create token</button>
<br />
{mintAddress && <p>{mintAddress} is the token address</p>}
</div>
<br />
<div>
<h2>Create Associated Token Account</h2>
{mintAddress && <p>{mintAddress} is taken as the Token ID</p>}
<p>The wallet owner is taken as the owning authority of the token.</p>
<p>Getting Associated Account does not work now.</p>
<button onClick={createAssociatedTokenAccount.bind(this)}>Create Associated Token Account</button>
<br />
<button onClick={createTokenAccount.bind(this)}>Create Token Account</button>
{tokenAccount && <p>{tokenAccount} is the token address</p>}
</div>
<div>
<h2>Mint Tokens</h2>
<p>Minting {mintAddress} </p>
<p>tokens for {address} </p>
<p>in this this account {tokenAccount}</p>
</div>
<label htmlFor="input">Enter the number of tokens you want to mint </label>
<input type="number" id="input" value={numberOfTokens} onChange={e => { setNumberOfTokens(e.target.value) }} />
<button onClick={mintTokens.bind(this)}>Mint Tokens</button>
<div>
<h3>Create Multisig Account</h3>
<button onClick={createMultiSigAccount.bind(this)}>Create multisig Account</button>
</div>
</div >
)
}
export default App
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment