Your First Program on Expload

Typical Use Cases

Crypto Assets and the Marketplace

The most obvious advantage of being integrated with the Expload platform is the ability to replace ordinary in-game assets with crypto assets. The users' ownership of assets is protected by the Pravda Blockchain. Furthermore, users can sell assets for XGold and XPlatinum on the Expload Marketplace.

You can find the detailed guidelines on the marketplace integration here.

XGold-Based Monetization

By replacing your premium currency (gold/diamonds/... purchased for fiat money) with XGold you can gain an abundance of opportunities, notably: - There is no need for developing any payment solution in your game, since players buy XGold directly from Expload and you can just use Expload's and XGold's easy-to-use API. - Players from other games on the Expload Platform can comfortably migrate to your game — buy items in one game and sell in another. - You can implement a variety of economic concepts in your game: allow users to play for money or let them rent virtual property from each other. The only limit is your imagination.

XGold & XPlatinum

XGold

XGold is basically not a real cryptocurrency, but rather a crypto token, which is issued by Expload and sold to players at a fixed price. Players cannot exchange XGold for fiat money, they can only use it within the games. XGold that is spent within the games is credited to the game developers, who can further exchange it for fiat money with Expload.

XPlatinum

XPlatinum is a fully-fledged cryptocurrency, which can only be bought or sold on crypto exchanges. For certain uses of XPlatinum, the supply of additional personal data may be required, such as ID card / passport verification.

Unity Integration Example

We will draw on the example of Expulsum, a card game integrated with the Expload platform, which is based on The Game of Pure Strategy, invented by Merrill Flood in the 1930s.

Contract Sample

The contract below is used to process the gaming activities such as the placing of bets and distribution of winnings .

namespace Expload
{

    using Pravda;
    using System;

    [Program]
    public class Game {

        // Mapping storing people's bets
        private Mapping<string, long> bets = new Mapping<string, long>();

        // XGold program address
        private Bytes _XGAddress = Bytes.VOID_ADDRESS;

        private void AssertIsProgramOwner()
        {
            if (Info.Sender() != Info.ProgramAddress()){
                Error.Throw("Only program owner can do this.");
            }
        }

        public void SetXGAddress(Bytes address)
        {
            AssertIsProgramOwner();
            _XGAddress = address;
        }

        public void MakeBet(string roomId, long bet)
        {
            ProgramHelper.Program<XGold>(_XGAddress).Spend(Info.ProgramAddress(), bet);
            bets[StdLib.BytesToHex(Info.Sender()) + roomId] = bet;
        }

        public bool CheckBet(Bytes address, string roomId, long bet)
        {
            return bets[StdLib.BytesToHex(address) + roomId] == bet;
        }

        public void GivePrize(Bytes winner, long amount)
        {
            AssertIsProgramOwner();
            ProgramHelper.Program<XGold>(_XGAddress).Refund(Info.ProgramAddress(),
                winner, amount);
        }

        public void RefundBet(Bytes address, string roomId)
        {
            AssertIsProgramOwner();
            ProgramHelper.Program<XGold>(_XGAddress).Refund(Info.ProgramAddress(),
                address, bets[StdLib.BytesToHex(address)  + roomId]);
            bets[StdLib.BytesToHex(address) + roomId] = 0;
        }
    }
}

Let's see how this works. The game server's matchmaking service finds 3 players who will be playing together and gives them a roomId. Then players call the MakeBet function and pay the required amount of XGold. The game server waits till the CheckBet for all the 3 players returns true and only then starts the game. If it takes too long for a certain player to pay, the game is cancelled, the placed bets are refunded with the use of the RefundBet function. If the game successfully proceeds till the end, the game server distributes the prizes using the GivePrize function.

Unity Code Sample

In this case, all that the Unity game client has to do is to call the MakeBet function, everything else is handled server-side. But before you are able to call any functions, you should handle Expload App authentication and get the user's nickname to be displayed in-game. Let's see how Expulsum developers have solved these issues:

All of these functions use dApp API, every section provides a link to the respective part of the dApp API documentation.

Game Server Authorization

dAppAPI

public static async Task<string> Authenticate()
{
    try
    {
        var message = Encoding.UTF8.GetBytes("DEPS").ToHex();

        var signed = await dappUrl
            .AppendPathSegment("auth")
            .WithTimeout(10)
            .ConfigureRequest(c => c.JsonSerializer = camelCaseSerializer)
            .PostJsonAsync(new { App = "DEPS", Bytes = message })
            .ReceiveJson<PravdaResponce<SignResponce>>();

        return signed.Data.SignedData;
    }
    catch (Exception ex)
    {
        throw new NetworkingException(NetworkingExceptionReason.ExploadApp, ex);
    }
}

Get User's Address

dApp API

public static async Task<string> GetAddress()
{
    try
    {
        var addressResp = await dappUrl
            .AppendPathSegment("address")
            .WithTimeout(10)
            .ConfigureRequest(c => c.JsonSerializer = camelCaseSerializer)
            .GetJsonAsync<PravdaResponce<string>>();

        return addressResp.Data;
    }
    catch (Exception ex)
    {
        throw new NetworkingException(NetworkingExceptionReason.ExploadApp, ex);
    }
}

Get User's Nickname

dApp API

public static async Task<string> GetNickname(string address)
{
    try
    {
        var nicknameResp = await dappUrl
            .AppendPathSegment("username")
            .WithTimeout(10)
            .SetQueryParam("address", address)
            .ConfigureRequest(c => c.JsonSerializer = camelCaseSerializer)
            .GetJsonAsync<PravdaResponce<string>>();

        return nicknameResp.Data;
    }
    catch (Exception ex)
    {
        throw new NetworkingException(NetworkingExceptionReason.ExploadApp, ex);
    }
}

Call a Pravda Program Method

dApp API

public static async Task<PravdaResponce<PravdaTransactionResult>> CallMethod(string address, string method, params object[] args)
{
    var call = new PravdaMethodCall()
    {
        Address = address,
        Method = method,
        Args = new List<object>(args)
    };

    try
    {
        var result = await dappUrl
            .AppendPathSegment("program")
            .AppendPathSegment("method")
            .WithTimeout(60)
            .ConfigureRequest(c => c.JsonSerializer = camelCaseSerializer)
            .PostJsonAsync(call)
            .ReceiveJson<PravdaResponce<PravdaTransactionResult>>();

        return result;
    }
    catch (Exception ex)
    {
        throw new NetworkingException(NetworkingExceptionReason.ExploadApp, ex);
    }
}

You can find the full source code here.

Tips and Tricks

  • Don't forget about permissions. You may wish to make certain functions in your Pravda programs gameserver-only or owner-only. This can be done using Require()
  • Don't overload the Pravda programs. Put as much logic as you can into the game server, as all the operations in the blockchain require XPlatinum.
  • All the costs related to XGold and Marketplace operations are borne by Expload.
  • An automatic Pravda program deploy/update pipeline might be a really good idea. Here is an example: link