Getting Started with Vidya SDK
This comprehensive guide will walk you through setting up the Vidya SDK and building your first Web3 game. The SDK uses a Player-centric architecture that makes blockchain game development intuitive and powerful.
Core Concepts
The Vidya SDK is built around two main concepts:
- Player Object: The central hub for all player interactions
- Modular Item Class: Flexible item management with built-in methods
Prerequisites
Before you begin, ensure you have:
- Node.js 18+ (TypeScript/JavaScript), Unity 2021.3+, Godot 4.0+, or Unreal Engine 5+
- MetaMask or another Web3 wallet
- ETH on Arbitrum for gas fees (Bridge ETH)
- A Vidya Project ID (get one at vidya.game/developers)
Installation
- TypeScript/JavaScript
- Unity
- Godot
- Unreal Engine
npm install @vidya/sdk viem
# or
yarn add @vidya/sdk viem
# or
bun add @vidya/sdk viem
- Open Unity Package Manager (Window → Package Manager)
- Click + → "Add package from git URL"
- Enter:
https://github.com/vidyagames/vidya-unity-sdk.git
- Download the Vidya SDK addon from GitHub Releases
- Extract to
res://addons/vidya-sdk/ - Enable the plugin in Project Settings → Plugins
- Download the Vidya SDK plugin from Unreal Marketplace
- Install to your project's Plugins folder
- Enable in Edit → Plugins → Vidya SDK
Quick Start: Player Authentication
The SDK provides two ways to create a Player object:
Method 1: From Session (Recommended for Games)
- TypeScript
- Unity/C#
- Godot/GDScript
- Unreal/C++
import { VidyaSDK, Player } from '@vidya/sdk';
// Initialize SDK with your project ID
const sdk = new VidyaSDK({
projectId: 'YOUR_PROJECT_ID',
chainId: 42161, // Arbitrum One
});
// Authenticate and create Player from session
async function initializeGame() {
try {
// Connect wallet and authenticate
const session = await sdk.auth.connect();
// Create Player object from session
const player = await Player.fromSession(session);
console.log('Player authenticated:', player.address);
console.log('Session expires:', player.session.expiresAt);
// Now you can use the player object throughout your game
return player;
} catch (error) {
console.error('Authentication failed:', error);
}
}
using VidyaSDK;
using UnityEngine;
using System.Threading.Tasks;
public class GameManager : MonoBehaviour
{
private VidyaClient sdk;
private Player player;
async void Start()
{
// Initialize SDK
sdk = new VidyaClient(new VidyaConfig
{
ProjectId = "YOUR_PROJECT_ID",
ChainId = 42161 // Arbitrum One
});
// Authenticate player
await AuthenticatePlayer();
}
async Task AuthenticatePlayer()
{
try
{
// Connect and authenticate
var session = await sdk.Auth.Connect();
// Create Player from session
player = await Player.FromSession(session);
Debug.Log($"Player authenticated: {player.Address}");
Debug.Log($"Session expires: {player.Session.ExpiresAt}");
}
catch (System.Exception e)
{
Debug.LogError($"Authentication failed: {e.Message}");
}
}
}
extends Node
var sdk: VidyaSDK
var player: Player
func _ready():
# Initialize SDK
sdk = VidyaSDK.new()
sdk.initialize({
"project_id": "YOUR_PROJECT_ID",
"chain_id": 42161 # Arbitrum One
})
# Connect authentication signal
sdk.auth_completed.connect(_on_auth_completed)
# Start authentication
sdk.authenticate()
func _on_auth_completed(session: Session):
if session:
# Create Player from session
player = await Player.from_session(session)
print("Player authenticated: ", player.address)
print("Session expires: ", player.session.expires_at)
else:
print("Authentication failed")
#include "VidyaSDK.h"
void AGameManager::BeginPlay()
{
Super::BeginPlay();
// Initialize SDK
UVidyaSDK* SDK = UVidyaSDK::GetInstance();
SDK->Initialize("YOUR_PROJECT_ID", 42161);
// Bind authentication callback
SDK->OnAuthCompleted.AddDynamic(this, &AGameManager::OnAuthCompleted);
// Start authentication
SDK->Authenticate();
}
void AGameManager::OnAuthCompleted(const FVidyaSession& Session)
{
if (Session.IsValid())
{
// Create Player from session
Player = UPlayer::FromSession(Session);
UE_LOG(LogVidya, Log, TEXT("Player authenticated: %s"), *Player->GetAddress());
UE_LOG(LogVidya, Log, TEXT("Session expires: %s"), *Session.ExpiresAt.ToString());
}
}
Method 2: From Wallet (Direct Connection)
- TypeScript
import { Player } from '@vidya/sdk';
import { createWalletClient, custom } from 'viem';
import { arbitrum } from 'viem/chains';
// Create wallet client (e.g., from MetaMask)
const walletClient = createWalletClient({
chain: arbitrum,
transport: custom(window.ethereum),
});
// Create Player directly from wallet
const player = await Player.fromWallet(walletClient, {
projectId: 'YOUR_PROJECT_ID',
});
console.log('Player connected:', player.address);
Working with the Player Object
Once you have a Player object, you can access all game modules through it:
- TypeScript
- Unity/C#
// Access different modules through the player
const player = await Player.fromSession(session);
// Inventory module
const inventory = await player.inventory.getItems();
const weapons = await player.inventory.getItems({
category: 'weapon'
});
// Marketplace module
const listings = await player.marketplace.getListings();
// Equipment module
const equipped = await player.equipment.getEquipped();
// Stats module
const stats = await player.stats.get();
// Access modules through player
var inventory = await player.Inventory.GetItems();
var weapons = await player.Inventory.GetItems(new ItemFilter {
Category = "weapon"
});
var listings = await player.Marketplace.GetListings();
var equipped = await player.Equipment.GetEquipped();
var stats = await player.Stats.Get();
Item Management with the Modular Item Class
The Item class provides built-in methods for all common operations:
- TypeScript
- Unity/C#
- Godot/GDScript
// Get items using flexible predicates
const player = await Player.fromSession(session);
// Get a specific item by ID
const sword = await player.inventory.getItem(
item => item.id === 'legendary-sword-001'
);
// Get items by category
const potions = await player.inventory.getItems(
item => item.category === 'consumable' && item.name.includes('Potion')
);
// Get items by rarity
const rareItems = await player.inventory.getItems(
item => item.rarity >= 3
);
// Item operations
if (sword) {
// Transfer to another player
await sword.transfer(recipientAddress, 1);
// Equip the item
await sword.equip();
// List on marketplace
await sword.list({
price: '100',
currency: 'VIDYA',
duration: 7 * 24 * 60 * 60 // 7 days
});
// Consume (for consumables)
if (potions.length > 0) {
await potions[0].consume(1);
}
}
// Get items with predicates
var sword = await player.Inventory.GetItem(
item => item.Id == "legendary-sword-001"
);
var potions = await player.Inventory.GetItems(
item => item.Category == "consumable" && item.Name.Contains("Potion")
);
var rareItems = await player.Inventory.GetItems(
item => item.Rarity >= 3
);
// Item operations
if (sword != null)
{
// Transfer
await sword.Transfer(recipientAddress, 1);
// Equip
await sword.Equip();
// List on marketplace
await sword.List(new ListingParams
{
Price = "100",
Currency = "VIDYA",
Duration = TimeSpan.FromDays(7)
});
}
// Consume potions
if (potions.Count > 0)
{
await potions[0].Consume(1);
}
# Get items with custom filters
var sword = await player.inventory.get_item(func(item):
return item.id == "legendary-sword-001"
)
var potions = await player.inventory.get_items(func(item):
return item.category == "consumable" and "Potion" in item.name
)
# Item operations
if sword:
# Transfer
await sword.transfer(recipient_address, 1)
# Equip
await sword.equip()
# List on marketplace
await sword.list({
"price": "100",
"currency": "VIDYA",
"duration": 7 * 24 * 60 * 60
})
Complete Example: Building a Game Interface
HTML Interface
Create index.html:
<!DOCTYPE html>
<html>
<head>
<title>Vidya Game - Player-Centric Demo</title>
<style>
body {
font-family: 'Inter', -apple-system, sans-serif;
max-width: 1200px;
margin: 0 auto;
padding: 20px;
background: #0a0a0e;
color: #fff;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.button {
background: #F8FF50;
color: #000;
border: none;
padding: 12px 24px;
font-size: 16px;
cursor: pointer;
text-transform: uppercase;
font-weight: bold;
border-radius: 4px;
transition: all 0.2s;
}
.button:hover {
background: #f5fc2a;
transform: translateY(-2px);
}
.button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.player-info {
background: #1a1a1f;
padding: 20px;
border-radius: 8px;
margin-bottom: 2rem;
}
.tabs {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.tab {
padding: 10px 20px;
background: #2a2a2f;
border: none;
color: #fff;
cursor: pointer;
border-radius: 4px;
}
.tab.active {
background: #8B5CF6;
}
.content {
background: #1a1a1f;
padding: 20px;
border-radius: 8px;
}
.inventory {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: 15px;
}
.item {
background: #2a2a2f;
border: 2px solid #3a3a3f;
padding: 15px;
border-radius: 8px;
transition: all 0.2s;
}
.item:hover {
border-color: #8B5CF6;
transform: translateY(-2px);
}
.item-actions {
display: flex;
gap: 10px;
margin-top: 10px;
}
.item-actions button {
padding: 5px 10px;
font-size: 12px;
}
.error {
background: #ef4444;
color: white;
padding: 10px;
border-radius: 4px;
margin: 10px 0;
}
.success {
background: #10b981;
color: white;
padding: 10px;
border-radius: 4px;
margin: 10px 0;
}
</style>
</head>
<body>
<div class="header">
<h1>Vidya Game Demo</h1>
<button id="connectBtn" class="button">Connect Player</button>
</div>
<div id="playerInfo" class="player-info" style="display: none;">
<h3>Player Details</h3>
<p>Address: <span id="playerAddress"></span></p>
<p>Session Expires: <span id="sessionExpires"></span></p>
</div>
<div id="messages"></div>
<div id="gameContent" style="display: none;">
<div class="tabs">
<button class="tab active" data-tab="inventory">Inventory</button>
<button class="tab" data-tab="marketplace">Marketplace</button>
<button class="tab" data-tab="equipment">Equipment</button>
</div>
<div class="content">
<div id="inventory" class="tab-content"></div>
<div id="marketplace" class="tab-content" style="display: none;"></div>
<div id="equipment" class="tab-content" style="display: none;"></div>
</div>
</div>
<script type="module">
import { VidyaSDK, Player } from 'https://unpkg.com/@vidya/sdk/dist/index.js';
// Initialize SDK
const sdk = new VidyaSDK({
projectId: 'demo-project', // Replace with your project ID
chainId: 42161,
});
let player = null;
// UI Elements
const connectBtn = document.getElementById('connectBtn');
const playerInfo = document.getElementById('playerInfo');
const gameContent = document.getElementById('gameContent');
const messages = document.getElementById('messages');
// Show message
function showMessage(message, type = 'info') {
const div = document.createElement('div');
div.className = type === 'error' ? 'error' : 'success';
div.textContent = message;
messages.appendChild(div);
setTimeout(() => div.remove(), 5000);
}
// Connect player
connectBtn.onclick = async () => {
try {
connectBtn.disabled = true;
connectBtn.textContent = 'Connecting...';
// Authenticate and create Player object
const session = await sdk.auth.connect();
player = await Player.fromSession(session);
// Update UI
document.getElementById('playerAddress').textContent = player.address;
document.getElementById('sessionExpires').textContent =
new Date(player.session.expiresAt).toLocaleString();
playerInfo.style.display = 'block';
gameContent.style.display = 'block';
connectBtn.textContent = 'Connected';
showMessage('Player connected successfully!', 'success');
// Load initial data
await loadInventory();
} catch (error) {
showMessage(`Connection failed: ${error.message}`, 'error');
connectBtn.disabled = false;
connectBtn.textContent = 'Connect Player';
}
};
// Tab switching
document.querySelectorAll('.tab').forEach(tab => {
tab.onclick = () => {
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
tab.classList.add('active');
document.querySelectorAll('.tab-content').forEach(content => {
content.style.display = 'none';
});
const tabName = tab.dataset.tab;
document.getElementById(tabName).style.display = 'block';
// Load content based on tab
if (tabName === 'inventory') loadInventory();
else if (tabName === 'marketplace') loadMarketplace();
else if (tabName === 'equipment') loadEquipment();
};
});
// Load inventory
async function loadInventory() {
if (!player) return;
const inventoryDiv = document.getElementById('inventory');
inventoryDiv.innerHTML = '<p>Loading inventory...</p>';
try {
// Get all items
const items = await player.inventory.getItems();
if (items.length === 0) {
inventoryDiv.innerHTML = '<p>No items in inventory</p>';
return;
}
inventoryDiv.innerHTML = '<div class="inventory"></div>';
const grid = inventoryDiv.querySelector('.inventory');
items.forEach(item => {
const itemDiv = document.createElement('div');
itemDiv.className = 'item';
itemDiv.innerHTML = `
<h4>${item.name}</h4>
<p>Category: ${item.category}</p>
<p>Quantity: ${item.balance}</p>
<p>Rarity: ${item.rarity}</p>
<div class="item-actions">
<button class="button" onclick="equipItem('${item.id}')">Equip</button>
<button class="button" onclick="listItem('${item.id}')">List</button>
${item.category === 'consumable' ?
`<button class="button" onclick="consumeItem('${item.id}')">Use</button>` : ''}
</div>
`;
grid.appendChild(itemDiv);
});
// Make functions available globally for onclick handlers
window.equipItem = async (itemId) => {
try {
const item = await player.inventory.getItem(i => i.id === itemId);
await item.equip();
showMessage(`Equipped ${item.name}!`, 'success');
loadEquipment();
} catch (error) {
showMessage(`Failed to equip: ${error.message}`, 'error');
}
};
window.listItem = async (itemId) => {
try {
const item = await player.inventory.getItem(i => i.id === itemId);
const price = prompt('Enter price in VIDYA:');
if (!price) return;
await item.list({
price: price,
currency: 'VIDYA',
duration: 7 * 24 * 60 * 60
});
showMessage(`Listed ${item.name} for ${price} VIDYA!`, 'success');
} catch (error) {
showMessage(`Failed to list: ${error.message}`, 'error');
}
};
window.consumeItem = async (itemId) => {
try {
const item = await player.inventory.getItem(i => i.id === itemId);
await item.consume(1);
showMessage(`Used ${item.name}!`, 'success');
loadInventory();
} catch (error) {
showMessage(`Failed to consume: ${error.message}`, 'error');
}
};
} catch (error) {
inventoryDiv.innerHTML = `<p class="error">Failed to load inventory: ${error.message}</p>`;
}
}
// Load marketplace
async function loadMarketplace() {
if (!player) return;
const marketplaceDiv = document.getElementById('marketplace');
marketplaceDiv.innerHTML = '<p>Loading marketplace...</p>';
try {
const listings = await player.marketplace.getListings();
if (listings.length === 0) {
marketplaceDiv.innerHTML = '<p>No active listings</p>';
return;
}
marketplaceDiv.innerHTML = '<div class="inventory"></div>';
const grid = marketplaceDiv.querySelector('.inventory');
listings.forEach(listing => {
const listingDiv = document.createElement('div');
listingDiv.className = 'item';
listingDiv.innerHTML = `
<h4>${listing.item.name}</h4>
<p>Price: ${listing.price} ${listing.currency}</p>
<p>Seller: ${listing.seller.slice(0, 6)}...${listing.seller.slice(-4)}</p>
<div class="item-actions">
<button class="button" onclick="buyItem('${listing.id}')">Buy</button>
</div>
`;
grid.appendChild(listingDiv);
});
window.buyItem = async (listingId) => {
try {
await player.marketplace.buy(listingId);
showMessage('Purchase successful!', 'success');
loadMarketplace();
loadInventory();
} catch (error) {
showMessage(`Purchase failed: ${error.message}`, 'error');
}
};
} catch (error) {
marketplaceDiv.innerHTML = `<p class="error">Failed to load marketplace: ${error.message}</p>`;
}
}
// Load equipment
async function loadEquipment() {
if (!player) return;
const equipmentDiv = document.getElementById('equipment');
equipmentDiv.innerHTML = '<p>Loading equipment...</p>';
try {
const equipped = await player.equipment.getEquipped();
if (Object.keys(equipped).length === 0) {
equipmentDiv.innerHTML = '<p>No items equipped</p>';
return;
}
equipmentDiv.innerHTML = '<div class="inventory"></div>';
const grid = equipmentDiv.querySelector('.inventory');
Object.entries(equipped).forEach(([slot, item]) => {
const itemDiv = document.createElement('div');
itemDiv.className = 'item';
itemDiv.innerHTML = `
<h4>${slot.toUpperCase()}</h4>
<p>${item.name}</p>
<p>Stats: +${item.stats?.attack || 0} ATK, +${item.stats?.defense || 0} DEF</p>
<div class="item-actions">
<button class="button" onclick="unequipItem('${slot}')">Unequip</button>
</div>
`;
grid.appendChild(itemDiv);
});
window.unequipItem = async (slot) => {
try {
await player.equipment.unequip(slot);
showMessage(`Unequipped ${slot}!`, 'success');
loadEquipment();
loadInventory();
} catch (error) {
showMessage(`Failed to unequip: ${error.message}`, 'error');
}
};
} catch (error) {
equipmentDiv.innerHTML = `<p class="error">Failed to load equipment: ${error.message}</p>`;
}
}
</script>
</body>
</html>
TypeScript Implementation
Create game.ts:
import { VidyaSDK, Player, Item } from '@vidya/sdk';
class VidyaGame {
private sdk: VidyaSDK;
private player: Player | null = null;
constructor(projectId: string) {
this.sdk = new VidyaSDK({
projectId,
chainId: 42161, // Arbitrum One
});
}
async initialize(): Promise<void> {
try {
// Authenticate player
const session = await this.sdk.auth.connect();
this.player = await Player.fromSession(session);
console.log('Player initialized:', this.player.address);
// Set up event listeners
this.setupEventListeners();
} catch (error) {
console.error('Failed to initialize:', error);
throw error;
}
}
private setupEventListeners(): void {
if (!this.player) return;
// Listen for item received events
this.player.events.on('ItemReceived', (event) => {
console.log('New item received:', event);
this.onItemReceived(event.item);
});
// Listen for item consumed events
this.player.events.on('ItemConsumed', (event) => {
console.log('Item consumed:', event);
this.onItemConsumed(event.itemId, event.amount);
});
// Listen for equipment changes
this.player.events.on('ItemEquipped', (event) => {
console.log('Item equipped:', event);
this.onItemEquipped(event.item, event.slot);
});
}
// Inventory management
async getInventory(): Promise<Item[]> {
if (!this.player) throw new Error('Player not initialized');
return this.player.inventory.getItems();
}
async getWeapons(): Promise<Item[]> {
if (!this.player) throw new Error('Player not initialized');
return this.player.inventory.getItems(
item => item.category === 'weapon' && item.equipmentSlot === 'mainHand'
);
}
async getConsumables(): Promise<Item[]> {
if (!this.player) throw new Error('Player not initialized');
return this.player.inventory.getItems(
item => item.category === 'consumable'
);
}
// Item operations
async equipItem(itemId: string): Promise<void> {
if (!this.player) throw new Error('Player not initialized');
const item = await this.player.inventory.getItem(
i => i.id === itemId
);
if (!item) throw new Error('Item not found');
await item.equip();
}
async consumeItem(itemId: string, amount: number = 1): Promise<void> {
if (!this.player) throw new Error('Player not initialized');
const item = await this.player.inventory.getItem(
i => i.id === itemId
);
if (!item) throw new Error('Item not found');
if (item.category !== 'consumable') throw new Error('Item is not consumable');
await item.consume(amount);
}
async listItemForSale(itemId: string, price: string, currency: string = 'VIDYA'): Promise<void> {
if (!this.player) throw new Error('Player not initialized');
const item = await this.player.inventory.getItem(
i => i.id === itemId
);
if (!item) throw new Error('Item not found');
await item.list({
price,
currency,
duration: 7 * 24 * 60 * 60, // 7 days
});
}
// Marketplace operations
async getMarketplaceListings(filter?: {
category?: string;
minPrice?: string;
maxPrice?: string;
}): Promise<any[]> {
if (!this.player) throw new Error('Player not initialized');
const listings = await this.player.marketplace.getListings(filter);
return listings;
}
async purchaseItem(listingId: string): Promise<void> {
if (!this.player) throw new Error('Player not initialized');
await this.player.marketplace.buy(listingId);
}
// Crafting operations
async getCraftingRecipes(): Promise<any[]> {
if (!this.player) throw new Error('Player not initialized');
return this.player.crafting.getRecipes();
}
async craftItem(recipeId: string, quantity: number = 1): Promise<void> {
if (!this.player) throw new Error('Player not initialized');
await this.player.crafting.craft(recipeId, quantity);
}
// Event handlers
private onItemReceived(item: Item): void {
// Update UI, show notification, etc.
console.log(`Received ${item.name}!`);
}
private onItemConsumed(itemId: string, amount: number): void {
// Update UI, apply effects, etc.
console.log(`Consumed ${amount} of item ${itemId}`);
}
private onItemEquipped(item: Item, slot: string): void {
// Update character stats, visuals, etc.
console.log(`Equipped ${item.name} to ${slot}`);
}
}
// Usage example
async function main() {
const game = new VidyaGame('YOUR_PROJECT_ID');
try {
await game.initialize();
// Get inventory
const inventory = await game.getInventory();
console.log('Inventory:', inventory);
// Get specific items
const weapons = await game.getWeapons();
console.log('Weapons:', weapons);
// Equip first weapon
if (weapons.length > 0) {
await game.equipItem(weapons[0].id);
}
// Get marketplace listings
const listings = await game.getMarketplaceListings({
category: 'weapon',
maxPrice: '1000',
});
console.log('Weapon listings:', listings);
} catch (error) {
console.error('Game error:', error);
}
}
main();
Advanced Features
🔐 Session Management
// Check session validity
if (player.session.isExpired()) {
// Refresh session
await player.refreshSession();
}
// Get remaining session time
const timeLeft = player.session.getTimeUntilExpiry();
console.log(`Session expires in ${timeLeft} seconds`);
📊 Player Statistics
// Get player stats
const stats = await player.stats.get();
console.log('Level:', stats.level);
console.log('Experience:', stats.experience);
console.log('Achievements:', stats.achievements);
// Update stats (server-side only)
await player.stats.addExperience(100);
await player.stats.unlockAchievement('first_kill');
🎯 Quest System
// Get active quests
const quests = await player.quests.getActive();
// Complete quest objectives
await player.quests.completeObjective(questId, objectiveId);
// Claim quest rewards
await player.quests.claimRewards(questId);
💰 Currency Management
// Get balances
const balances = await player.wallet.getBalances();
console.log('VIDYA:', balances.VIDYA);
console.log('Gold:', balances.gold);
// Transfer tokens
await player.wallet.transfer({
to: recipientAddress,
amount: '100',
currency: 'VIDYA'
});
Best Practices
1. Error Handling
Always wrap SDK calls in try-catch blocks:
try {
await player.inventory.getItems();
} catch (error) {
if (error.code === 'INSUFFICIENT_BALANCE') {
// Handle specific error
} else {
// Handle general error
}
}
2. Optimistic Updates
Update UI immediately for better UX:
// Optimistic UI update
updateUIOptimistically(item);
try {
await item.equip();
} catch (error) {
// Revert UI on failure
revertUIUpdate(item);
}
3. Batch Operations
Use batch operations when possible:
// Instead of multiple calls
for (const itemId of itemIds) {
await player.inventory.getItem(i => i.id === itemId);
}
// Use a single call
const items = await player.inventory.getItems(
i => itemIds.includes(i.id)
);
4. Caching
Implement caching for frequently accessed data:
class GameCache {
private cache = new Map();
private ttl = 60000; // 1 minute
async get(key: string, fetcher: () => Promise<any>) {
const cached = this.cache.get(key);
if (cached && Date.now() - cached.timestamp < this.ttl) {
return cached.data;
}
const data = await fetcher();
this.cache.set(key, { data, timestamp: Date.now() });
return data;
}
}
Troubleshooting
Common Issues
-
"Player not authenticated"
- Ensure you've called
Player.fromSession()orPlayer.fromWallet() - Check if the session has expired
- Ensure you've called
-
"Transaction failed"
- Verify sufficient gas (ETH) in wallet
- Check network connection
- Ensure correct chain (Arbitrum One)
-
"Item not found"
- Verify item ID is correct
- Check if player owns the item
- Ensure inventory is synced
Debug Mode
Enable debug logging:
const sdk = new VidyaSDK({
projectId: 'YOUR_PROJECT_ID',
chainId: 42161,
debug: true, // Enable debug logs
});
Migration Guide
If you're migrating from an older version:
From v1.x to v2.x
// Old way
const items = await sdk.inventory.getPlayerItems(playerAddress);
// New way
const player = await Player.fromSession(session);
const items = await player.inventory.getItems();
Key Changes
- Player-centric API: All operations now go through the Player object
- Item methods: Items now have built-in methods (transfer, equip, list, consume)
- Flexible queries: Use predicates instead of fixed filters
- Session management: Built-in session handling with automatic refresh
Next Steps
- 📖 Read the full API documentation
- 🎮 Explore example games
- 🛠️ Check out the SDK docs
- 💬 Join our Discord community