Skip to content

Commit

Permalink
fix: rm mint address input param (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
wei3erHase authored Oct 6, 2024
1 parent d520202 commit f8b51b3
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 110 deletions.
73 changes: 52 additions & 21 deletions js/src/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ import { Connection, PublicKey, Keypair } from '@solana/web3.js';
import fs from 'fs';
import { Numberu64, generateRandomSeed } from './utils';
import { CreateSchedule } from './state';
import { create, TOKEN_VESTING_PROGRAM_ID } from './main';
import {
create,
VESTING_PROGRAM_ID,
DEVNET_VESTING_PROGRAM_ID,
TOKEN_MINT,
initializeUnlock,
unlock,
} from './main';
import { signAndSendInstructions } from '@bonfida/utils';

/**
*
* Simple example of a linear unlock.
*
* This is just an example, please be careful using the vesting contract and test it first with test tokens.
*
Expand All @@ -23,15 +28,19 @@ const wallet = Keypair.fromSecretKey(
const LOCK_OWNER = new PublicKey('');
const LOCK_OWNER_TOKEN_ACCOUNT = new PublicKey('');

/** Info about the deposit (to interact with) */
const LOCK_SEED = '';

/** Token info */
const MINT = new PublicKey('');
const DECIMALS = 0;
const DECIMALS = 9;

/** Amount to give per schedule */
const LOCKED_AMOUNT = 0;
/** Amount to lock */
const LOCKED_AMOUNT = 10;

/** Your RPC connection */
const connection = new Connection('');
const DEVNET = true;
const program = DEVNET ? DEVNET_VESTING_PROGRAM_ID : VESTING_PROGRAM_ID;

/** Do some checks before sending the tokens */
const checks = async () => {
Expand All @@ -41,7 +50,7 @@ const checks = async () => {

// @ts-ignore
const parsed = tokenInfo.value.data.parsed;
if (parsed.info.mint !== MINT.toBase58()) {
if (parsed.info.mint !== TOKEN_MINT.toBase58()) {
throw new Error('Invalid mint');
}
if (parsed.info.owner !== LOCK_OWNER.toBase58()) {
Expand All @@ -56,10 +65,9 @@ const checks = async () => {
const lock = async () => {
await checks();
const schedule: CreateSchedule = new CreateSchedule(
/** Has to be in seconds */
/** Has to be 0 | 3 | 6 | 12 mths (in seconds) */
// @ts-ignore
new Numberu64(60),
/** Don't forget to add decimals */
new Numberu64(0), // unlocked with withdrawal period
// @ts-ignore
new Numberu64(LOCKED_AMOUNT * Math.pow(10, DECIMALS)),
);
Expand All @@ -69,26 +77,49 @@ const lock = async () => {

const instruction = await create(
connection,
TOKEN_VESTING_PROGRAM_ID,
program,
// @ts-ignore
Buffer.from(seed),
wallet.publicKey,
LOCK_OWNER_TOKEN_ACCOUNT,
MINT,
schedule,
);

const tx = await signAndSendInstructions(connection, [], wallet, instruction);

console.log(`Transaction: ${tx}`);
};

const txInfo = await connection.getConfirmedTransaction(tx, 'confirmed');
if (txInfo && !txInfo.meta?.err) {
console.log(
txInfo?.transaction.instructions[2].data.slice(1, 32 + 1).toString('hex'),
);
} else {
throw new Error('Transaction not confirmed.');
}
const initUnlock = async () => {
await checks();

const instruction = await initializeUnlock(
connection,
VESTING_PROGRAM_ID,
// @ts-ignore
Buffer.from(LOCK_SEED),
);

const tx = await signAndSendInstructions(connection, [], wallet, instruction);

console.log(`Transaction: ${tx}`);
};

const withdraw = async () => {
await checks();

const instruction = await unlock(
connection,
program,
// @ts-ignore
Buffer.from(LOCK_SEED),
);

const tx = await signAndSendInstructions(connection, [], wallet, instruction);

console.log(`Transaction: ${tx}`);
};

lock();
// initUnlock();
// withdraw();
7 changes: 1 addition & 6 deletions js/src/instructions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,10 @@ export function createCreateInstruction(
vestingTokenAccountKey: PublicKey,
sourceTokenAccountOwnerKey: PublicKey,
sourceTokenAccountKey: PublicKey,
mintAddress: PublicKey,
schedule: CreateSchedule,
seeds: Array<Buffer | Uint8Array>,
): TransactionInstruction {
let buffers = [
Buffer.from(Int8Array.from([1]).buffer),
Buffer.concat(seeds),
mintAddress.toBuffer(),
];
let buffers = [Buffer.from(Int8Array.from([1]).buffer), Buffer.concat(seeds)];

buffers.push(schedule.toBuffer());

Expand Down
33 changes: 20 additions & 13 deletions js/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,22 @@ import { ContractInfo, CreateSchedule } from './state';
import bs58 from 'bs58';

/**
* The vesting schedule program ID on testnet
* TODO: replace with mainnet ID
* The vesting schedule program ID
*/
export const TOKEN_VESTING_PROGRAM_ID = new PublicKey(
'3F15CLnQjHqMCHLn2g7vuDULiRuJDiEMSZQXMoVVUGtA',
export const VESTING_PROGRAM_ID = new PublicKey(
'BHJWdCprG1HUiCZh1jhA4mJfAiXEGJXUn4pjnZXB3fGp'
);

export const TOKEN_MINT = new PublicKey(
'AxfBPA1yi6my7VAjqB9fqr1AgYczuuJy8tePnNUDDPpW'
);

export const DEVNET_VESTING_PROGRAM_ID = new PublicKey(
'HGhyAuNiYRa6oN55eGGP1MYGVve7epwT8WX6qbWxgYxM'
);

export const DEVNET_TOKEN_MINT = new PublicKey(
'FrnSwyMzw2u6DB2bQUTpia9mRHqeujdUF2bomY8Zt5BX',
);

/**
Expand All @@ -46,13 +57,12 @@ export async function create(
seedWord: Buffer | Uint8Array,
payer: PublicKey,
possibleSourceTokenPubkey: PublicKey | null,
mintAddress: PublicKey,
schedule: CreateSchedule,
): Promise<Array<TransactionInstruction>> {
// If no source token account was given, use the associated source account
if (possibleSourceTokenPubkey == null) {
possibleSourceTokenPubkey = await getAssociatedTokenAddress(
mintAddress,
TOKEN_MINT,
payer,
true,
);
Expand All @@ -66,7 +76,7 @@ export async function create(
);

const vestingTokenAccountKey = await getAssociatedTokenAddress(
mintAddress,
TOKEN_MINT,
vestingAccountKey,
true,
);
Expand Down Expand Up @@ -97,7 +107,7 @@ export async function create(
payer,
vestingTokenAccountKey,
vestingAccountKey,
mintAddress,
TOKEN_MINT,
),
createCreateInstruction(
programId,
Expand All @@ -107,7 +117,6 @@ export async function create(
vestingTokenAccountKey,
payer,
possibleSourceTokenPubkey,
mintAddress,
schedule,
[seedWord],
),
Expand All @@ -127,7 +136,6 @@ export async function unlock(
connection: Connection,
programId: PublicKey,
seedWord: Buffer | Uint8Array,
mintAddress: PublicKey,
): Promise<Array<TransactionInstruction>> {
seedWord = seedWord.slice(0, 31);
const [vestingAccountKey, bump] = await PublicKey.findProgramAddress(
Expand All @@ -137,7 +145,7 @@ export async function unlock(
seedWord = Buffer.from(seedWord.toString('hex') + bump.toString(16), 'hex');

const vestingTokenAccountKey = await getAssociatedTokenAddress(
mintAddress,
TOKEN_MINT,
vestingAccountKey,
true,
);
Expand Down Expand Up @@ -171,7 +179,6 @@ export async function initializeUnlock(
connection: Connection,
programId: PublicKey,
seedWord: Buffer | Uint8Array,
mintAddress: PublicKey,
): Promise<Array<TransactionInstruction>> {
seedWord = seedWord.slice(0, 31);
const [vestingAccountKey, bump] = await PublicKey.findProgramAddress(
Expand All @@ -181,7 +188,7 @@ export async function initializeUnlock(
seedWord = Buffer.from(seedWord.toString('hex') + bump.toString(16), 'hex');

const vestingTokenAccountKey = await getAssociatedTokenAddress(
mintAddress,
TOKEN_MINT,
vestingAccountKey,
true,
);
Expand Down
30 changes: 6 additions & 24 deletions js/src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,26 +45,18 @@ export class Schedule {

export class VestingScheduleHeader {
destinationAddress!: PublicKey;
mintAddress!: PublicKey;
isInitialized!: boolean;

constructor(
destinationAddress: PublicKey,
mintAddress: PublicKey,
isInitialized: boolean,
) {
constructor(destinationAddress: PublicKey, isInitialized: boolean) {
this.destinationAddress = destinationAddress;
this.mintAddress = mintAddress;
this.isInitialized = isInitialized;
}

static fromBuffer(buf: Buffer): VestingScheduleHeader {
const destinationAddress = new PublicKey(buf.slice(0, 32));
const mintAddress = new PublicKey(buf.slice(32, 64));
const isInitialized = buf[64] == 1;
const isInitialized = buf[32] == 1;
const header: VestingScheduleHeader = {
destinationAddress,
mintAddress,
isInitialized,
};
return header;
Expand All @@ -73,29 +65,19 @@ export class VestingScheduleHeader {

export class ContractInfo {
destinationAddress!: PublicKey;
mintAddress!: PublicKey;
schedule!: Schedule;

constructor(
destinationAddress: PublicKey,
mintAddress: PublicKey,
schedule: Schedule,
) {
constructor(destinationAddress: PublicKey, schedule: Schedule) {
this.destinationAddress = destinationAddress;
this.mintAddress = mintAddress;
this.schedule = schedule;
}

static fromBuffer(buf: Buffer): ContractInfo | undefined {
const header = VestingScheduleHeader.fromBuffer(buf.slice(0, 65));
const header = VestingScheduleHeader.fromBuffer(buf.slice(0, 33));
if (!header.isInitialized) {
return undefined;
}
const schedule = Schedule.fromBuffer(buf.slice(65, 81));
return new ContractInfo(
header.destinationAddress,
header.mintAddress,
schedule,
);
const schedule = Schedule.fromBuffer(buf.slice(33, 49));
return new ContractInfo(header.destinationAddress, schedule);
}
}
1 change: 0 additions & 1 deletion js/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"extends": "@tsconfig/recommended/tsconfig.json",
"ts-node": {
"compilerOptions": {
"module": "commonjs",
Expand Down
17 changes: 1 addition & 16 deletions program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ impl Arbitrary for VestingInstruction {
1 => {
let schedule: [Schedule; 10] = u.arbitrary()?;
let key_bytes: [u8; 32] = u.arbitrary()?;
let mint_address: Pubkey = Pubkey::new_from_array(key_bytes);
let key_bytes: [u8; 32] = u.arbitrary()?;
return Ok(Self::Create {
seeds,
mint_address,
schedule: schedule,
});
}
Expand Down Expand Up @@ -79,7 +77,6 @@ pub enum VestingInstruction {
/// 4. `[writable]` The source spl-token account
Create {
seeds: [u8; 32],
mint_address: Pubkey,
schedule: Schedule,
},
/// Unlocks a simple vesting contract (SVC) - can only be invoked by the program itself
Expand Down Expand Up @@ -122,12 +119,7 @@ impl VestingInstruction {
.get(..32)
.and_then(|slice| slice.try_into().ok())
.unwrap();
let mint_address = rest
.get(32..64)
.and_then(|slice| slice.try_into().ok())
.map(Pubkey::new_from_array)
.ok_or(InvalidInstruction)?;
let offset = 64;
let offset = 32;
let time_delta = rest
.get(offset..offset + 8)
.and_then(|slice| slice.try_into().ok())
Expand All @@ -141,7 +133,6 @@ impl VestingInstruction {
let schedule = Schedule { time_delta, amount };
Self::Create {
seeds,
mint_address,
schedule,
}
}
Expand Down Expand Up @@ -171,12 +162,10 @@ impl VestingInstruction {
}
Self::Create {
seeds,
mint_address,
schedule,
} => {
buf.push(1);
buf.extend_from_slice(seeds);
buf.extend_from_slice(&mint_address.to_bytes());
buf.extend_from_slice(&schedule.time_delta.to_le_bytes());
buf.extend_from_slice(&schedule.amount.to_le_bytes());
}
Expand Down Expand Up @@ -225,12 +214,10 @@ pub fn create(
vesting_token_account_key: &Pubkey,
source_token_account_owner_key: &Pubkey,
source_token_account_key: &Pubkey,
mint_address: &Pubkey,
schedule: Schedule,
seeds: [u8; 32],
) -> Result<Instruction, ProgramError> {
let data = VestingInstruction::Create {
mint_address: *mint_address,
seeds,
schedule,
}
Expand Down Expand Up @@ -306,15 +293,13 @@ mod test {

#[test]
fn test_instruction_packing() {
let mint_address = Pubkey::new_unique();

let original_create = VestingInstruction::Create {
seeds: [50u8; 32],
schedule: Schedule {
amount: 42,
time_delta: 250,
},
mint_address: mint_address.clone(),
};
let packed_create = original_create.pack();
let unpacked_create = VestingInstruction::unpack(&packed_create).unwrap();
Expand Down
Loading

0 comments on commit f8b51b3

Please sign in to comment.