Creating & Managing Players

Overview

Players are the most important part of any game. Without players, there's no game! MetaFab makes it incredibly easy to create and manage players for your game with full access to blockchain interactions, player data storage and much more.

You can think of a Player for your game as a fully managed account controlled by your players. Each player account created through MetaFab is automatically assigned a managed wallet that has the ability to gaslessly interact with your game's currencies and smart contracts for the blockchains you use.

In this guide, we're going to cover patterns on how to create players for your game, gaslessly interact with your game's currencies, give players game currency and more.

Guide

Step 1: Get your Game's publishedKey

First, we'll need to get our game's publishedKey. This is a unique, publicly shareable key assigned to your game that is used when interacting with different API endpoints.

For creating players, this key is used to associate your newly created player with your Game for the player creation API request. You game's published key should look something like game_pk_FULLKEYHERE.

You can login/authenticate as your game to get its publishedKey and credentials here: GET /v1/games

Step 2: Create your First Player

Let's create our first player. Player creation can be done directly in your game client, or through a server-side process you create. Either is acceptable depending on your desired implementation and use case.

To create a player for our game, we're going to use the POST /v1/players endpoint.

You'll need to provide the following arguments to create a player using the player creation endpoint.

  • username: A unique player username within your game. For our example we'll use arkdev
  • password: A password to login/authenticate as the player account. For best security practices, this should be provided by your players and not stored by you. For our example we'll use testing

Additionally, we'll provide our game's publishedKey for the X-Game-Key header.

After we successfully make the API request to create our player, we'll receive a response with a Player object that looks something like this.

{
  "id": "4548a4b1-acad-4965-a865-1771e81d0a81",
  "gameId": "c77bdae7-72a1-49ef-bf88-904d39ece5a4",
  "walletId": "45dfa238-9a40-4c8b-9929-3b4be6cbdca1",
  "username": "arkdev",
  "accessToken": "ACCESS_TOKEN_REDACTED_FOR_GUIDE",
  "updatedAt": "2022-09-27T16:19:43.354Z",
  "createdAt": "2022-09-27T16:19:43.354Z",
  "wallet": {
    "id": "45dfa238-9a40-4c8b-9929-3b4be6cbdca1",
    "address": "0xB8FA3a15464291D893ce90e848e3860886189358"
  },
  "walletDecryptKey": "bb6aebb024c3211e44a07be2c4c4a2e6c7a4241c095d446ea834664bccb1dfc2"
}

We've successfully created our first player! Next, let's give them some of our game currency we created in our previous guide.

Step 3 (Optional): Mint Currency & Give it to our Player

We're going to give our newly created player some of our game's currency. To do that, we'll use the POST /currencies/{currencyId}/mint endpoint.

In this example, we'll use the following arguments to make our API request to mint some game currency and give it to our player in a single request.

  • currencyId: This is the id of our previously created game currency. From our previous guide, we'll use 543711df-085d-4ac8-86e1-7f6eb97cbaf0. Your id will be different than this guide. If you can't remember or find your currency's id use the GET /v1/currencies endpoint to get a list of your game's currency(s), including their id(s).
  • amount: The amount of game currency we want to create, we'll use the value 100 to create 100 of our game currency.
  • address OR walletId: The last argument is an EVM wallet address or MetaFab wallet id you want to mint and give the currency to. In this example, we'll use the wallet id of our newly created player from our example, 45dfa238-9a40-4c8b-9929-3b4be6cbdca1. Alternatively, we could use the player's direct wallet address of 0xB8FA3a15464291D893ce90e848e3860886189358 for the address argument instead - the outcome would be the same. Your player's wallet id or address will be different than the ones we've given in this example!

Additionally, we'll supply our game's secretKey for the X-Authorization header and walletDecryptKey for the X-Wallet-Decrypt-Key header. You can get your game's secret key from GET /v1/games

After we successfully make the API request to mint and give game currency to our player, we'll receive a response with a Transaction object that looks something like this.

Please note: Because minting and giving game currency interacts with the blockchain and submits a transaction to for your game currency's smart contract, it can take up to a few seconds for this endpoint to respond.

{
  "id": "c9fd0bc7-fd7f-4af2-aa67-a626a611cc48",
  "contractId": "33b924c6-6fee-4515-a685-bf3a6451e455",
  "walletId": "20af2b18-1b1a-44db-9a0d-1e9335647db8",
  "function": "mint",
  "args": [
    "0xB8FA3a15464291D893ce90e848e3860886189358",
    {
      "hex": "0x056bc75e2d63100000",
      "type": "BigNumber"
    }
  ],
  "hash": "0xd609deadc07df3edecca853592362e5a908ce6f48d938c1795885af3bcf380e1",
  "updatedAt": "2022-09-27T16:35:25.234Z",
  "createdAt": "2022-09-27T16:35:25.233Z"
}

If you receive a 200 response, the transaction was confirmed successfully on the blockchain. If you want to verify this transaction, you can take the hash value of the returned Transaction object and search it on PolygonScan (Because our game currency is on the Polygon blockchain). For example: https://polygonscan.com/tx/0xd609deadc07df3edecca853592362e5a908ce6f48d938c1795885af3bcf380e1

Step 4 (Optional): Transfer Currency as a Player

We'll take this guide a little further by giving a quick example on how to transfer game currency as a player. All blockchain transactions by player accounts are gasless and done through MetaFab's various API endpoints.

First, we'll need to deposit some MATIC token into the fundingWallet for our Game. Our game has 2 wallets - a wallet (Primary wallet used for contract deployment and direct interaction by our Game itself) and our fundingWallet which hold a balance of native token for the chain our players are interacting with our contract on, and uses its balance to cover player transaction fees. To learn more about this, head over to this article.

After we've deposited 1 or 2 MATIC token into our fundingWallet, we can transact on behalf of our players with our game's contracts through MetaFab API endpoints.

Let's transfer some of our game currency from our Player back to our game's primary wallet.

To do this, we'll use the POST /v1/currencies/{currencyId}/transfers endpoint. We'll use the following arguments for our request.

  • currencyId: This is the id of game currency. We'll use 543711df-085d-4ac8-86e1-7f6eb97cbaf0. Your id will be different than this guide.
  • address OR walletId: An EVM wallet address or MetaFab wallet id you want to transfer currency to. For this example, we'll use the wallet id of our game's primary wallet.
  • amount: The amount of currency we want to transfer. For this example we'll transfer 15.45 of our game currency.
  • reference: This is an optional uint256 that can be provided with a transfer, this can be useful for identifying items or services a transfer may have been made to pay for. We won't include this for this example.

Additionally we'll provide our player's accessToken for the X-Authorization header as well as the walletDecryptKey for our player's account for the X-Wallet-Decryt-Key header.

After we successfully make a request to transfer our game currency, we'll receive a response with a Transaction object that looks something like this.

{
  "id": "01dd7428-fd82-4438-a43a-b49658b40a68",
  "contractId": "33b924c6-6fee-4515-a685-bf3a6451e455",
  "walletId": "45dfa238-9a40-4c8b-9929-3b4be6cbdca1",
  "function": "transferWithFee",
  "args": [
    "0xB8FA3a15464291D893ce90e848e3860886189358",
    {
      "hex": "0xd6696d2473c90000",
      "type": "BigNumber"
    }
  ],
  "hash": "0x9f9186de3c03c9b38d4d65136a7f3b3ec6ceaae00cd8385d97d1ebd62111e6ac",
  "updatedAt": "2022-09-27T17:08:08.546Z",
  "createdAt": "2022-09-27T17:08:08.545Z"
}

We've successfully transferred some of our game currency!

Step 5 (Optional): Set Player Data

One of the last but important things we can do with players is save arbitrary data relevant to our game uniquely to each player. This is useful for saving things like player character stats, player preferences, and much more.

MetaFab implements a system that allows you to store 2 types of data. Public data and Protected data. This data is stored and retrieved as JSON objects.

  • Public data is data that can be read by anyone and overwritten by the player or game.
  • Protected data is data that can be read by anyone but ONLY overwritten by the game.

Additionally, player data is written using a deep merge system. This means that when you update a player's data, you do not need to resave a player's entire public or protected data object each time. You only need to save the object properties specific to your player's data object that you wish to override against their currently saved data.

Let's save some public and protected data for our player using the POST /v1/players/{playerId}/data endpoint. We'll use the following arguments for our request.

  • playerId: This is the id of a player specific to our game that we want to update the data for.
  • protectedData: This is data that only the parent Game for the player can write. You can set any arbitrary JSON data object. For this example we'll use the following JSON object: {"level": 10, "inGame": false, "luckyNumbers": [1,4,31], "lastMatch": {"id": 1241}}
  • publicData: This is data that the parent Game or player can write. You can set any arbitrary JSON data object. For this example we'll use the following JSON object: {"difficulty": "easy"}

Additionally, we'll supply our game's secretKey for the X-Authorization header. This allows us to set protectedData for the player as the game. If we use the player's accessToken for this endpoint, we can only set publicData.

After we successfully make the API request to create our game currency, we'll receive a response with a Player Data object that looks something like this..

{
  "updatedAt": 1668033446,
  "protectedData": {
    "level": 10,
    "inGame": false,
    "luckyNumbers": [1, 4, 31],
    "lastMatch": {
      "id": 1241
    },
    "offChainInventory": {
      "rock": 1251,
      "feather": 222,
      "battery": 513,
      "wood": 742
    }
  },
  "publicData": {
    "difficulty": "easy"
  }
}

Finally, we can retrieve the set player data for any player using the GET /v1/players/{playerId}/data endpoint.

Common Implementation Patterns

Client-Side Player Account Creation & Management

When we think about designing our player registration flow, one common way we can do this is through directly implementing player registration that is entirely managed by our game client, game website, game application, etc.

This implementation pattern would look something like this..

  • A player has downloaded our game or is on our game's website, etc. They get to a registration page that requests a username and password to create the player's account.
  • The provided username and password is submitted to the player creation endpoint POST /v1/players. We receive a 200 status response containing a Player object in the response body.
  • Next, we'll store the player's Player object in storage locally. The Player object contains authentication related credentials like their accessToken.
  • Anytime the player needs to do some kind of interaction like transfer currency, or interact with another smart contract managed through MetaFab, we can grab their Player object containing their credentials that we've stored locally and use those from the client to make a MetaFab API request to whatever resource they are interacting with.
  • Note: Client side implementations require exposing your game's publishedKey - this is a secure, intended use case of publishedKey.

Server-Side Player Account Creation & Management

In more advance cases, we may want our game's own backend to manage interactions or partial interactions with the MetaFab APIs. This is another common pattern.

This could look something like...

  • A player has downloaded our game or is on our game's website, etc. They get to our registration page and are required to provide their email and password as well as some other data specific to our game.
  • The provided email, password and additional data are submitted to our game's backend.
  • Our game's backend processes this data, maybe creates a database entry for our player in our game's database, and then makes an API request to MetaFab's API to create a player linked to the player in the backend database of our game.
  • The returned Player object from MetaFab is stored in the game's backend database, or could be returned down to the client for the player. This approach would allow you to submit transactions on behalf of a player directly from your game server, or from the game client.

What’s Next