Player Profile

@staratlas/player-profile

Introduction

Welcome to the Player Profile, brought to you by Star Atlas! This open protocol empowers developers to seamlessly create and manage decentralized profiles on the Solana blockchain. Dive into a world where game and application profiles are not bound by central control, ensuring greater trust, transparency, and user autonomy.

The Player Profile Program allows users to manage their identity and access keys. Users can create a list of public keys associated with their profile and set permissions for each key. Identity is no longer tied to a key and is instead tied to a profile, allowing for key rotation, complex ownership structures, and more. No CPI is required to check a key that signs on behalf of a profile.

Package
Description
Version
Docs

@staratlas/player-profile

TypeScript bindings for the player-profile program

Installation

npm i @staratlas/player-profile

Examples

From the Star-Atlas-Cookbook and for https://build.staratlas.com/

TypeScript Code Explanation

This is a TypeScript code example demonstrating how to interact with the Solana blockchain using the @project-serum/anchor and @solana/web3.js libraries. The code fetches player profiles from a Solana account using the readAllFromRPC function.

  1. Importing Libraries

import { Program } from "@project-serum/anchor"; 
import { Connection, Keypair } from "@solana/web3.js";

The code imports the following libraries:

  • @project-serum/anchor: a library for building Solana applications using TypeScript.

  • @solana/web3.js: a library for interacting with the Solana blockchain.

  1. Importing Custom Functions

import { readAllFromRPC } from "@staratlas/data-source"; 
import { PLAYER_PROFILE_IDL, PlayerProfile } from "@staratlas/player-profile";

The code imports custom functions and types:

  • readAllFromRPC: a function for reading data from Solana accounts.

  • PLAYER_PROFILE_IDL and PlayerProfile: types related to player profiles.

  1. Importing Shared Functions

import { newConnection, newAnchorProvider } from "../../shared/anchor-setup"; 
import { loadKeypair } from "../../shared/wallet-setup";

The code imports shared functions:

  • newConnection and newAnchorProvider: functions for creating a Solana connection and anchor provider.

  • loadKeypair: a function for loading a Keypair from a file.

  1. Constants

const PLAYER_PROFILE_PROGRAM_ID = "pprofELXjL5Kck7Jn5hCpwAL82DpTkSYBENzahVtbc9";

The code defines a constant:

  • PLAYER_PROFILE_PROGRAM_ID: the ID of the player profile program.

  1. Main Function

const main = async (connection: Connection, myWallet: Keypair) => { // ... };

The code defines an asynchronous function called main that takes two arguments:

  • connection: a Solana connection.

  • myWallet: a Keypair representing the user's wallet.

  1. Creating Provider and Program

const provider = newAnchorProvider(connection, myWallet); 
const playerProfileProgram = new Program( PLAYER_PROFILE_IDL, PLAYER_PROFILE_PROGRAM_ID, provider, );

The code creates an anchor provider and a program:

  • provider: an instance of the newAnchorProvider function.

  • playerProfileProgram: an instance of the Program class, which is used to interact with the player profile program.

  1. Reading Player Profiles

const myProfiles = await readAllFromRPC( connection, playerProfileProgram as any, PlayerProfile, 'processed', [
{ 
memcmp: {
 offset: PlayerProfile.MIN_DATA_SIZE + 2, 
 bytes: myWallet.publicKey.toBase58(), 
 },
  },
   ], 
    );

The code reads all player profiles from the Solana account using the readAllFromRPC function:

  • myProfiles: an array of player profiles.

  • The memcmp object is used to filter profiles based on the user's wallet public key.

  1. Handling Player Profiles

if (myProfiles.length === 0) {
 throw 'no player profile found'; 
 }
for (let index = 0; index < myProfiles.length; index++) { 
const thisProfile = myProfiles[index]; 
if (thisProfile.type === 'error') throw new Error('Error reading account');
console.log(JSON.stringify(thisProfile, null, 2));
}

The code handles the player profiles:

  • If no profiles are found, it throws an error.

  • Otherwise, it logs each profile to the console using JSON.stringify.

  1. Environment Variables

const wallet = process.env.WALLET_PATH || "/home/user/.config/solana/id.json"; 
const rpcEndpoint = process.env.RPC_ENDPOINT || "https://mainnet.helius-rpc.com/?api-key="; 
const rpcWebsocket = process.env.RPC_WEBSOCKET || "wss://rpc.helius.xyz/?api-key=";
const myWallet = loadKeypair(wallet); 
const connection = newConnection(rpcEndpoint, rpcWebsocket);

The code sets environment variables:

  • wallet: the path to the user's wallet file.

  • rpcEndpoint and rpcWebsocket: the RPC endpoint and WebSocket URL for interacting with the Solana network.

  1. Running the Main Function

main(connection, myWallet);

The code runs the main function with the created connection and wallet.

import { Program } from "@project-serum/anchor";
import { Connection, Keypair } from "@solana/web3.js";

import { readAllFromRPC } from "@staratlas/data-source";
import { PLAYER_PROFILE_IDL, PlayerProfile } from "@staratlas/player-profile";

import { newConnection, newAnchorProvider } from "../../shared/anchor-setup";
import { loadKeypair } from "../../shared/wallet-setup";

const PLAYER_PROFILE_PROGRAM_ID = "pprofELXjL5Kck7Jn5hCpwAL82DpTkSYBENzahVtbc9"

const main = async (connection: Connection, myWallet: Keypair) => {
    console.log("Example 02: Sage Player Profile");

    const provider = newAnchorProvider(connection, myWallet);
    const playerProfileProgram = new Program(
        PLAYER_PROFILE_IDL,
        PLAYER_PROFILE_PROGRAM_ID,
        provider,
    );

    const myProfiles = await readAllFromRPC(
        connection,
        playerProfileProgram as any,
        PlayerProfile,
        'processed',
        [
            {
                memcmp: {
                    offset: PlayerProfile.MIN_DATA_SIZE + 2,
                    bytes: myWallet.publicKey.toBase58(),
                },
            },
        ],
    );

    if (myProfiles.length === 0) {
        throw 'no player profile found';
    }

    for (let index = 0; index < myProfiles.length; index++) {
        const thisProfile = myProfiles[index];
        if (thisProfile.type === 'error') throw new Error('Error reading account');

        console.log(JSON.stringify(thisProfile, null, 2));
    }
};

// cd examples/02-sage-player-profile
// bun run index.ts
const wallet = process.env.WALLET_PATH || "/home/user/.config/solana/id.json"
const rpcEndpoint = process.env.RPC_ENDPOINT || "https://mainnet.helius-rpc.com/?api-key=";
const rpcWebsocket = process.env.RPC_WEBSOCKET || "wss://rpc.helius.xyz/?api-key=";

const myWallet = loadKeypair(wallet);
const connection = newConnection(rpcEndpoint, rpcWebsocket);
main(connection, myWallet);

Last updated

Was this helpful?