Experience development
- How an experience works
- Telling the casino that the experience is ready
- Authenticating a player
- Subscribing to player balance updates
An experience is a game frontend backed by a controller that talks to a hub server from an app iframed on the casino.
We recommend referencing our React experience template to see how these concepts work together in practice.
You are free to use any frontend technology you want (React, Vue, Svelte, etc.) to build your experience.
Here are some example experiences:
Experiences talk to a @moneypot/hub game server to authenticate MoneyPot users, manage player balances, and implement API endpoints specific to the game.
Experiences are also expected to implement PostMessage events to communicate with the casino.
How an experience works
Anyone can create an experience at moneypot.com/me/developer where you must provide two things:
- Controller ID: The underlying controller that uses the MoneyPot API to authenticate users, detect deposits, and send withdrawals.
- This cannot be changed.
- You can create one here: moneypot.com/me/developer/controllers
- A controller can be summarized as a “sub-user” that you can create: it holds a balance and has API keys to manage its balance. The hub server uses the controller’s API keys to make requests to MoneyPot.
- You generally own the controller and run your own hub server that uses its credentials, but that’s not required; You can also use someone else’s controllerID and point your experience at their hub server. This is the basis for creating “skins” for existing games.
- Iframe URL: URL to the game frontend.
- You can always change this later.
Once you create an experience, you can access it at https://moneypot.com/play/{username}/{experienceId}
. You can also set a permanent slug
for the experience to give it a prettier URL like /play/user1/my-game
.
Once you set an experience’s slug, you cannot change it without contacting support.
When a player visits that page, MoneyPot creates a userToken
(a JSON Web Token) for them and passes it to the experience through the iframe url:
<iframe src="https://my-game.example.com#userToken={userToken}" />
When the experience loads in the iframe, it parses the userToken
and it derives the casinoBaseUrl
(the url of the MoneyPot casino that embedded it).
This information is sufficient to know which MoneyPot player is playing the game.
Telling the casino that the experience is ready
The casino shows a loading screen on the /play/{username}/{experienceId}
page until the experience is ready.
The experience posts the status message to the casino when it’s ready to be revealed:
parent.postMessage({ type: "status", status: "ready" }, "*");
Or, if the experience hit an error that it can’t recover from (like if the hub server is down), then:
parent.postMessage({ type: "status", status: "fatal" }, "*");
More info: PostMessage API docs explain, the experience can tell the casino that it’s ready by posting a message to the parent.
Authenticating a player
Here’s a hub server in production that implements various MoneyPot first-party games: provably-fair-controller.moneypot.com.
If you add a new mutation, you can see that there’s a hubAuthenticate
mutation:
mutation Authenticate {
hubAuthenticate(
input: { casinoBaseUrl: "https://moneypot.com", userToken: "..." }
) {
success {
experienceId
sessionKey
uname
userId
}
}
}
The hub server verifies the userToken JWT, extracts the token, and exchanges it with the MoneyPot API to get the player’s info.
The hub server then ensures the player exists in its own database and creates its own session for the player.
Now we can store sessionKey
on the client to make authenticated requests to the hub server:
fetch("https://provably-fair-controller.moneypot.com/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `session:${sessionKey}`,
},
body: JSON.stringify({ query: "..." }),
});
(Our React template shows how you can set up graphql codegen and TanStack Query to work with a graphql API in a pleasant, type-safe way.)
Once the player is authenticated (and any time the player’s balance changes), the experience is required to post the player’s balances to the casino.
parent.postMessage(
{
type: "playerBalances",
balances: {
HOUSE: 100,
BTC: 123,
},
},
"*"
);
Subscribing to player balance updates
The hub server offers a graphql subscription that the experience can subscribe to for knowing when to fetch the player’s latest balances from the hub server:
subscription PlayerBalanceAlert {
hubBalanceAlert {
currencyKey
}
}
Notice that the alert doesn’t tell us the player’s balance, just that the balance has changed.
The experience is expected to fetch the latest balances from the hub server:
query PlayerBalances {
hubCurrentUser {
hubBalancesByUserId {
nodes {
id
currencyKey
amount
hubCurrencyByCurrencyKeyAndCasinoId {
key
displayUnitScale
displayUnitName
}
}
}
}
}
That will return something like:
{
"data": {
"hubCurrentUser": {
"hubBalancesByUserId": {
"nodes": [
{
"id": "0ffaece8-8d94-4592-ba8c-ce20afbd122a",
"amount": 123,
"hubCurrencyByCurrencyKeyAndCasinoId": {
"key": "BTC",
"displayUnitScale": 100,
"displayUnitName": "bits"
}
},
{
"id": "0ffaece8-8d94-4592-ba8c-ce20afbd122b",
"amount": 100,
"hubCurrencyByCurrencyKeyAndCasinoId": {
"key": "HOUSE",
"displayUnitScale": 1,
"displayUnitName": "tokens"
}
}
]
}
}
}
}