Skip to content
This repository was archived by the owner on Sep 28, 2025. It is now read-only.
Open
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
2 changes: 1 addition & 1 deletion app/gem-bank/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"@gemworks/gem-farm-ts": "^0.26.3",
"@metaplex/js": "^4.9.0",
"@project-serum/anchor": "0.26.0",
"@solana/spl-token": "^0.1.8",
"@solana/spl-token": "^0.3.7",
"@solana/wallet-adapter-base": "^0.7.1",
"@solana/wallet-adapter-wallets": "^0.11.3",
"@solana/web3.js": "^1.31.0",
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
"@msgpack/msgpack": "^2.8.0",
"@project-serum/anchor": "0.26.0",
"@solana/spl-token": "^0.3.7",
"@solana/spl-token-018": "npm:@solana/spl-token@0.1.8",
"@solana/wallet-adapter-base": "^0.8.1",
"@solana/web3.js": "^1.73.0",
"exponential-backoff": "^3.1.0"
Expand Down
48 changes: 11 additions & 37 deletions src/gem-common/account-utils.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import {
AccountInfo,
ASSOCIATED_TOKEN_PROGRAM_ID,
MintInfo,
Token,
Account,
getAccount,
getAssociatedTokenAddress,
TOKEN_PROGRAM_ID,
//@ts-ignore
} from '@solana/spl-token-018';
TokenAccountNotFoundError,
TokenError
} from '@solana/spl-token';
import {AccountInfo, Connection, Keypair, PublicKey} from '@solana/web3.js';

export interface ITokenData {
tokenMint: PublicKey;
tokenAcc: PublicKey;
owner: PublicKey;
token: Token;
token: PublicKey;
}

export class AccountUtils {
Expand Down Expand Up @@ -48,40 +48,14 @@ export class AccountUtils {

// --------------------------------------- Token account

async deserializeToken(mint: PublicKey): Promise<Token> {
//doesn't matter which keypair goes here, we just need some key for instantiation
const throwawayKeypair = Keypair.fromSecretKey(
Uint8Array.from([
208, 175, 150, 242, 88, 34, 108, 88, 177, 16, 168, 75, 115, 181, 199,
242, 120, 4, 78, 75, 19, 227, 13, 215, 184, 108, 226, 53, 111, 149, 179,
84, 137, 121, 79, 1, 160, 223, 124, 241, 202, 203, 220, 237, 50, 242,
57, 158, 226, 207, 203, 188, 43, 28, 70, 110, 214, 234, 251, 15, 249,
157, 62, 80,
])
);
return new Token(this.conn, mint, TOKEN_PROGRAM_ID, throwawayKeypair);
}

async deserializeTokenMint(mint: PublicKey): Promise<MintInfo> {
const t = await this.deserializeToken(mint);
return t.getMintInfo();
}

async deserializeTokenAccount(
mint: PublicKey,
tokenAccount: PublicKey
): Promise<AccountInfo> {
const token = await this.deserializeToken(mint);
return token.getAccountInfo(tokenAccount);
): Promise<Account> {
return await getAccount(this.conn, tokenAccount);
}

async findATA(mint: PublicKey, owner: PublicKey): Promise<PublicKey> {
return Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mint,
owner,
true
);
return getAssociatedTokenAddress(mint, owner, true);
}
}
58 changes: 21 additions & 37 deletions src/gem-common/browser-wallet.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
import {
AccountLayout as TokenAccountLayout,
createAssociatedTokenAccountInstruction,
createInitializeMintInstruction,
getMinimumBalanceForRentExemptMint,
createMintToInstruction,
MintLayout,
TOKEN_PROGRAM_ID,
getAssociatedTokenAddress,
createInitializeAccountInstruction,
getMinimumBalanceForRentExemptAccount,
} from '@solana/spl-token';
import {
Connection,
Keypair,
Expand All @@ -7,13 +19,6 @@ import {
SystemProgram,
Transaction,
} from '@solana/web3.js';
import {
AccountLayout as TokenAccountLayout,
ASSOCIATED_TOKEN_PROGRAM_ID,
MintLayout,
Token,
TOKEN_PROGRAM_ID,
} from '@solana/spl-token';
import { AccountUtils } from './account-utils';
import { SignerWalletAdapter } from '@solana/wallet-adapter-base';

Expand All @@ -38,7 +43,7 @@ export class BrowserWallet extends AccountUtils {
decimals: number
): Promise<[PublicKey, TxWithSigners]> {
const mintAccount = Keypair.generate();
const balanceNeeded = await Token.getMinBalanceRentForExemptMint(this.conn);
const balanceNeeded = await getMinimumBalanceForRentExemptMint(this.conn);
const tx = new Transaction({
feePayer: payer,
recentBlockhash: (await this.conn.getRecentBlockhash()).blockhash,
Expand All @@ -51,8 +56,7 @@ export class BrowserWallet extends AccountUtils {
space: MintLayout.span,
programId: TOKEN_PROGRAM_ID,
}),
Token.createInitMintInstruction(
TOKEN_PROGRAM_ID,
createInitializeMintInstruction(
mintAccount.publicKey,
decimals,
authority,
Expand All @@ -74,16 +78,7 @@ export class BrowserWallet extends AccountUtils {
feePayer: payer,
recentBlockhash: (await this.conn.getRecentBlockhash()).blockhash,
});
tx.add(
Token.createMintToInstruction(
TOKEN_PROGRAM_ID,
mint,
dest,
authority,
[],
amount
)
);
tx.add(createMintToInstruction(mint, dest, authority, amount));

return { tx, signers: [] };
}
Expand Down Expand Up @@ -130,28 +125,22 @@ export class BrowserWallet extends AccountUtils {
isAssociated: boolean
): Promise<[PublicKey, TxWithSigners]> {
const newAccount = Keypair.generate();
let balanceNeeded = await Token.getMinBalanceRentForExemptAccount(
this.conn
);
let balanceNeeded = await getMinimumBalanceForRentExemptAccount(this.conn);
const tx = new Transaction({
feePayer: payer,
recentBlockhash: (await this.conn.getRecentBlockhash()).blockhash,
});
if (isAssociated) {
const associatedAddress = await Token.getAssociatedTokenAddress(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
const associatedAddress = await getAssociatedTokenAddress(
mint,
authority
);
tx.add(
Token.createAssociatedTokenAccountInstruction(
ASSOCIATED_TOKEN_PROGRAM_ID,
TOKEN_PROGRAM_ID,
mint,
createAssociatedTokenAccountInstruction(
payer,
associatedAddress,
authority,
payer
mint
)
);

Expand All @@ -167,12 +156,7 @@ export class BrowserWallet extends AccountUtils {
})
);
tx.add(
Token.createInitAccountInstruction(
TOKEN_PROGRAM_ID,
mint,
newAccount.publicKey,
authority
)
createInitializeAccountInstruction(newAccount.publicKey, mint, authority)
);

return [newAccount.publicKey, { tx, signers: [newAccount] }];
Expand Down
43 changes: 19 additions & 24 deletions src/gem-common/node-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ import {
import { BN } from '@project-serum/anchor';
import { AccountUtils, ITokenData } from './account-utils';
//@ts-ignore
import { NATIVE_MINT, Token, TOKEN_PROGRAM_ID } from '@solana/spl-token-018';
import {
createAssociatedTokenAccount,
createMint,
createWrappedNativeAccount, mintTo,
NATIVE_MINT,
TOKEN_PROGRAM_ID
} from '@solana/spl-token';

export class NodeWallet extends AccountUtils {
wallet: anchor.Wallet; //node wallet
Expand Down Expand Up @@ -44,44 +50,33 @@ export class NodeWallet extends AccountUtils {
async createMint(
decimals: number,
authority: Keypair = this.wallet.payer
): Promise<Token> {
return Token.createMint(
): Promise<PublicKey> {
return createMint(
this.conn,
authority,
authority.publicKey,
authority.publicKey,
decimals,
TOKEN_PROGRAM_ID
);
}

async createNativeMint() {
return new Token(
this.conn,
NATIVE_MINT,
TOKEN_PROGRAM_ID,
this.wallet.payer
);
}

async createAndFundATA(
token: Token,
token: PublicKey,
owner: PublicKey,
amount: BN
): Promise<PublicKey> {
if (token.publicKey == NATIVE_MINT) {
const account = await Token.createWrappedNativeAccount(
this.conn,
TOKEN_PROGRAM_ID,
owner,
this.wallet.payer,
amount.toNumber()
if (token == NATIVE_MINT) {
const account = await createWrappedNativeAccount(
this.conn,
this.wallet.payer,
owner,
amount.toNumber()
);
return account;
} else {
const account = await token.createAssociatedTokenAccount(owner);
const account = await createAssociatedTokenAccount(this.conn, this.wallet.payer, token, owner);
if (amount.toNumber() > 0) {
await token.mintTo(account, this.wallet.payer, [], amount.toNumber());
await mintTo(this.conn, this.wallet.payer, token, account, this.wallet.payer, amount.toNumber());
}
return account;
}
Expand All @@ -94,7 +89,7 @@ export class NodeWallet extends AccountUtils {
const token = await this.createMint(0);
const tokenAcc = await this.createAndFundATA(token, owner, amount);
return {
tokenMint: token.publicKey,
tokenMint: token,
tokenAcc,
owner,
token,
Expand Down
15 changes: 8 additions & 7 deletions tests/gem-bank/gem-bank.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import chai, { assert, expect } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { describe } from 'mocha';
import { createMetadata } from '../metaplex';
import { TokenAccountNotFoundError } from "@solana/spl-token";

chai.use(chaiAsPromised);

Expand Down Expand Up @@ -207,7 +208,7 @@ describe.only('gem bank', () => {
assert(vaultAcc.rarityPoints.eq(gemAmount));

const gemBoxAcc = await gb.fetchGemAcc(gem.tokenMint, gemBox);
assert(gemBoxAcc.amount.eq(gemAmount));
assert(gemBoxAcc.amount === BigInt(gemAmount.toString()));
assert.equal(gemBoxAcc.mint.toBase58(), gem.tokenMint.toBase58());
assert.equal(gemBoxAcc.owner.toBase58(), vaultAuth.toBase58());

Expand Down Expand Up @@ -239,11 +240,11 @@ describe.only('gem bank', () => {
assert(vaultAcc2.rarityPoints.eq(oldGemCount.sub(gemAmount)));

const gemAcc = await gb.fetchGemAcc(gem.tokenMint, gem.tokenAcc);
assert(gemAcc.amount.eq(gemAmount));
assert(gemAcc.amount === BigInt(gemAmount.toString()));

//these accounts are expected to close on emptying the gem box
await expect(gb.fetchGemAcc(gem.tokenMint, gemBox)).to.be.rejectedWith(
'Failed to find account'
TokenAccountNotFoundError
);
await expect(gb.fetchGDRAcc(GDR)).to.be.rejectedWith(
'Account does not exist'
Expand All @@ -258,10 +259,10 @@ describe.only('gem bank', () => {
await prepWithdrawal(vaultOwner, gem.owner, smallerAmount);

const gemAcc = await gb.fetchGemAcc(gem.tokenMint, gem.tokenAcc);
assert(gemAcc.amount.eq(smallerAmount));
assert(gemAcc.amount === BigInt(smallerAmount.toString()));

const gemBoxAcc = await gb.fetchGemAcc(gem.tokenMint, gemBox);
assert(gemBoxAcc.amount.eq(new BN(1)));
assert(gemBoxAcc.amount === BigInt(1));

const GDRAcc = await gb.fetchGDRAcc(GDR);
assert(GDRAcc.gemCount.eq(new BN(1)));
Expand All @@ -277,11 +278,11 @@ describe.only('gem bank', () => {
await prepWithdrawal(vaultOwner, randomWallet.publicKey, gemAmount);

const gemAcc = await gb.fetchGemAcc(gem.tokenMint, missingATA);
assert(gemAcc.amount.eq(gemAmount));
assert(gemAcc.amount === BigInt(gemAmount.toString()));

//these accounts are expected to close on emptying the gem box
await expect(gb.fetchGemAcc(gem.tokenMint, gemBox)).to.be.rejectedWith(
'Failed to find account'
TokenAccountNotFoundError
);
await expect(gb.fetchGDRAcc(GDR)).to.be.rejectedWith(
'Account does not exist'
Expand Down
Loading