Skip to main content

What are Game Tokens?

Game tokens are cryptocurrencies that power your game economy. Players can earn tokens for achievements, spend them on items, or trade them with other players.
Tokens exist on the blockchain, so players truly own them. They can hold, trade, or sell tokens even outside your game.

Token Use Cases

Play-to-Earn
  • Reward players with tokens for completing levels
  • Players can sell earned tokens for real money
In-Game Currency
  • Use tokens to buy items, upgrades, or cosmetics
  • More transparent than traditional in-game currencies
Governance
  • Token holders vote on game updates
  • Community-driven game development
Staking
  • Players stake tokens to earn rewards
  • Incentivizes long-term holding

Creating a Game Token

G3Engine makes it easy to launch your own token:

Using Pump.fun (Solana)

Pump.fun is the easiest way to launch a Solana token:
import { executeTokenLaunch } from '@/lib/web3Runtime';

const result = await executeTokenLaunch(
  ctx,
  "My Game Token",           // Token name
  "MGT",                     // Token symbol
  "https://cdn.game.com/token-logo.png"  // Token image
);

console.log(`Token created: ${result.tokenMint}`);
console.log(`Transaction: ${result.txHash}`);
Pump.fun tokens start on a bonding curve. As players buy, the price increases. Once enough liquidity is reached, the token “graduates” to Raydium DEX.

Token Info Structure

export interface TokenInfo {
  mint: string;              // Unique token address
  name: string;              // "My Game Token"
  symbol: string;            // "MGT" (2-5 characters)
  balance: number;           // Player's balance
  decimals: number;          // Precision (usually 9 for Solana, 18 for EVM)
  imageUri?: string;         // Token logo URL
  
  // Pump.fun specific
  isPumpToken?: boolean;           // Launched on Pump.fun?
  bondingCurveComplete?: boolean;  // Graduated to DEX?
  priceInSol?: number;             // Current price
}

Example Token

const gameToken: TokenInfo = {
  mint: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  name: "Adventure Quest Token",
  symbol: "AQT",
  balance: 1000,
  decimals: 9,
  imageUri: "https://cdn.game.com/aqt-logo.png",
  isPumpToken: true,
  bondingCurveComplete: false,
  priceInSol: 0.00001
}

Game Economy Configuration

Configure how tokens work in your game:
export interface GameEconomyConfig {
  rewardTokenMint: string | null;  // Which token to use for rewards
  rewardPerLevel: number;           // Tokens earned per level
  tipJarEnabled: boolean;           // Can players tip each other?
  itemPrices: Array<{               // In-game item prices
    itemId: string;                 // Item identifier
    priceToken: string;             // Which token to use
    amount: number;                 // How many tokens
  }>;
}

Example Economy

const economy: GameEconomyConfig = {
  rewardTokenMint: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
  rewardPerLevel: 10,
  tipJarEnabled: true,
  itemPrices: [
    {
      itemId: "sword_legendary",
      priceToken: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
      amount: 100
    },
    {
      itemId: "health_potion",
      priceToken: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
      amount: 5
    }
  ]
}

Rewarding Players

Give players tokens for achievements:

Level Completion Rewards

Use the Blueprint “Reward Player” node or call directly:
import { executeBuyToken } from '@/lib/web3Runtime';

// When player completes a level
const rewardAmount = economy.rewardPerLevel;

// Transfer tokens to player
await airdropTokens(
  playerWalletAddress,
  economy.rewardTokenMint,
  rewardAmount
);

Achievement Rewards

const achievements = [
  { id: 'first_win', reward: 50 },
  { id: 'speed_run', reward: 100 },
  { id: 'perfect_game', reward: 500 }
];

// When player unlocks achievement
const achievement = achievements.find(a => a.id === unlockedId);
if (achievement) {
  await airdropTokens(
    playerWalletAddress,
    economy.rewardTokenMint,
    achievement.reward
  );
}
Make sure you have enough tokens in your treasury wallet to distribute rewards. Running out of tokens will break your reward system.

Token-Gated Content

Require players to hold tokens to access content:
import { executeTokenGate } from '@/lib/web3Runtime';

const result = await executeTokenGate(
  ctx,
  economy.rewardTokenMint,  // Which token to check
  100                        // Minimum balance required
);

if (result.hasAccess) {
  // Player has enough tokens, grant access
  unlockPremiumLevel();
} else {
  // Show "You need 100 tokens to access this"
  showTokenGateMessage(100 - result.balance);
}

Buying and Selling Tokens

Let players trade tokens:

Buying Tokens (Pump.fun)

import { executeBuyToken } from '@/lib/web3Runtime';

const result = await executeBuyToken(
  ctx,
  tokenMint,      // Which token to buy
  0.1,            // Amount of SOL to spend
  1               // Slippage tolerance (1%)
);

addNotification(`Bought ${result.tokensReceived} tokens!`);

Selling Tokens (Pump.fun)

import { executeSellToken } from '@/lib/web3Runtime';

const result = await executeSellToken(
  ctx,
  tokenMint,      // Which token to sell
  1000,           // Number of tokens to sell
  1               // Slippage tolerance (1%)
);

addNotification(`Sold for ${result.solReceived} SOL!`);
Slippage tolerance is how much price change you’ll accept. 1% means the transaction fails if price moves more than 1% before it confirms.

Viewing Player Tokens

Display all tokens a player owns:
import { useWeb3Store } from '@/store/web3Store';

function TokenList() {
  const { tokens } = useWeb3Store();
  
  return (
    <div>
      <h2>Your Tokens</h2>
      {tokens.map(token => (
        <div key={token.mint}>
          {token.imageUri && <img src={token.imageUri} alt={token.name} />}
          <h3>{token.name} ({token.symbol})</h3>
          <p>Balance: {token.balance.toLocaleString()}</p>
          {token.priceInSol && (
            <p>Price: {token.priceInSol} SOL</p>
          )}
        </div>
      ))}
    </div>
  );
}

Token Pricing

Get the current price of a token:
import { executeGetTokenPrice } from '@/lib/web3Runtime';

const result = await executeGetTokenPrice(ctx, tokenMint);

console.log(`Price: ${result.priceInSol} SOL`);
console.log(`Market Cap: ${result.marketCap} SOL`);

In-Game Store

Let players buy items with tokens:
function GameStore() {
  const { economy, tokens } = useWeb3Store();
  
  const buyItem = async (item: typeof economy.itemPrices[0]) => {
    // Check if player has enough tokens
    const playerToken = tokens.find(t => t.mint === item.priceToken);
    
    if (!playerToken || playerToken.balance < item.amount) {
      alert('Not enough tokens!');
      return;
    }
    
    // Transfer tokens from player to game treasury
    await transferTokens(
      item.priceToken,
      item.amount,
      gameTreasuryAddress
    );
    
    // Give player the item
    givePlayerItem(item.itemId);
  };
  
  return (
    <div>
      {economy.itemPrices.map(item => (
        <div key={item.itemId}>
          <h3>{item.itemId}</h3>
          <p>Price: {item.amount} tokens</p>
          <button onClick={() => buyItem(item)}>Buy</button>
        </div>
      ))}
    </div>
  );
}

Token Transfers

Players can send tokens to each other:
// Send tokens from one player to another
async function transferTokens(
  tokenMint: string,
  amount: number,
  recipientAddress: string
) {
  // Implementation depends on blockchain:
  // - Solana: SPL Token transfer
  // - EVM: ERC-20 transfer
  
  const tx = await createTokenTransfer(
    tokenMint,
    amount,
    recipientAddress
  );
  
  await ctx.signTransaction(tx);
  return tx.signature;
}

Tip Jar

Let players tip each other:
if (economy.tipJarEnabled) {
  const tipPlayer = async (recipientAddress: string, amount: number) => {
    await transferTokens(
      economy.rewardTokenMint,
      amount,
      recipientAddress
    );
    
    addNotification(`Tipped ${amount} tokens!`);
  };
}

Checking Token Balance

Check a specific token balance:
import { executeCheckBalance } from '@/lib/web3Runtime';

const result = await executeCheckBalance(ctx, tokenMint);
console.log(`Balance: ${result.balance}`);

Token State Management

The Web3 store manages token state:
const web3Store = useWeb3Store();

// Add a token to the list
web3Store.addToken({
  mint: "...",
  name: "New Token",
  symbol: "NEW",
  balance: 0,
  decimals: 9
});

// Update all tokens
web3Store.setTokens(newTokenList);

// Update economy config
web3Store.updateEconomy({
  rewardPerLevel: 20  // Increase rewards
});

Best Practices

Token economies are complex. Start simple and iterate based on player behavior.

Do’s

  • Start with conservative reward rates
  • Monitor token supply and inflation
  • Provide multiple ways to earn AND spend tokens
  • Test thoroughly on devnet/testnet first
  • Be transparent about tokenomics

Don’ts

  • Don’t promise financial returns (legal issues)
  • Don’t make rewards too easy to farm
  • Don’t lock players out if they run out of tokens
  • Don’t make sudden economy changes without notice
  • Don’t launch on mainnet without auditing

Transaction History

Track all token transactions:
export interface Web3Transaction {
  id: string;
  type: 'token_launch' | 'buy' | 'sell' | 'transfer' | 'airdrop';
  signature: string;         // Blockchain transaction hash
  status: 'pending' | 'confirmed' | 'failed';
  description: string;
  timestamp: number;
}

const { transactions } = useWeb3Store();

// Show recent transactions
transactions
  .filter(tx => tx.type === 'buy' || tx.type === 'sell')
  .forEach(tx => {
    console.log(`${tx.type}: ${tx.status} - ${tx.description}`);
  });

Next Steps

NFT Support

Add NFT collectibles to your game

Solana Integration

Deep dive into Solana features

Build docs developers (and LLMs) love