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
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 usearkdev
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 usetesting
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 theid
of our previously created game currency. From our previous guide, we'll use543711df-085d-4ac8-86e1-7f6eb97cbaf0
. Yourid
will be different than this guide. If you can't remember or find your currency'sid
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 value100
to create 100 of our game currency.address
ORwalletId
: 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 of0xB8FA3a15464291D893ce90e848e3860886189358
for theaddress
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 theid
of game currency. We'll use543711df-085d-4ac8-86e1-7f6eb97cbaf0
. Yourid
will be different than this guide.address
ORwalletId
: 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 transfer15.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 theid
of a player specific to our game that we want to update the data for.protectedData
: This is data that only the parentGame
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 parentGame
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
andpassword
to create the player's account. - The provided
username
andpassword
is submitted to the player creation endpoint POST /v1/players. We receive a200
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 ofpublishedKey
.
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
andpassword
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.
Updated 3 months ago