Skip to main content

Haste Server SDK

Haste Server SDK️🪄

Introduction

Ready to list your game? Follow these straightforward steps to ensure a seamless integration with our API that gets you (and your users) paid faster.

  • Verify your game is compatible with Haste-SDK.
  • Install all Required Packages.
  • Register your game through the Haste Developer Portal and generate game access keys.
  • Review the Security standards for Haste and ensure your game follows the authoritative server model described there.
  • Ensure all required functions are implemented. If you'd like to reference our API documentation, you can do that here, but below you'll find a quick list of the functions required to list your game in Haste Arcade.

Table of Contents

Architecture

Haste Browser Architecture

Server-side Functions

The @hastearcade/server package is the primary entry point to the Haste ecosystem. The SDK is a wrapper for the Haste API and allows developers to HLP enable a game. The Haste ecosystem provides tools to handle most components of HLP; these functions are required to list your game with us, so make sure you have them somewhere in your code.

Initialize Haste using Haste.build()

To initialize the Haste SDK for use in your server, you need to perform the the code in InitializeHaste.tsx:

The client ID and secret are defined in the developer portal on your game page. See the image below for reference:

Game Server Keys

For the third parameter to build you can use nonproduction or production. Please use nonproduction when testing as it will not send payouts. When you are ready to test payouts and/or you are in your true production environment please change the third parameter to production. The best practice is to use an environment variable to manage this process. See Testing for more details.

InitializeHaste.tsx

import { Haste } from "@hastearcade/server";

// see Testing for more details
const environment = "nonproduction";
const haste = await Haste.build(
// Retrieve from Developer Portal
process.env.HASTE_SERVER_CLIENT_ID,
// Retrieve from Developer Portal
process.env.HASTE_SERVER_CLIENT_SECRET,
environment
);

/// Now do things with the haste object like submit a play or a score.

NOTE: It is recommended to create an abstraction (service, lib, etc) around the haste-sdk in your codebase. This will allow you to initialize one haste object.

Integrate with Haste Authentication and your Game Client

Every game listed in Haste Arcade must integrate with the Haste authentication system to allow players to receive payment for their skills. Users must be logged in to Haste Arcade to submit their score and later receive payment. The game client (using @hastearcade/web) will send the login token to the server with each request. The server can use the following code to validate the token:

IntegrateWithGameClient.tsx

import { Haste } from "@hastearcade/server";
/// this is custom code specific to your server to retrieve the token from the web request
/// for example if you send the token using the Authorization header, you can extract it from the request headers
const token = receiveTokenFromRequest();

try {
const playerId = await Haste.validatePlayerAccess(token);
console.log(`The player authenticated has an id of ${playerId}`);
} catch (err) {
console.error(`An error occurred while validating the player's token.`);
}

Note: the above code does not use the haste object created from build(). build() and validatePlayerAccess() are both static functions. All other functions (including get leaderboards, submit a score, etc. should utilize the haste object created from the build() function).

Get Leaderboard for Play Selection

In the Haste Arcade players can choose what level they wish to play at. They can risk small amounts or larger amounts based on their desire to earn. The Haste ecosystem currently has multiple leaderboards that can be played for every game. Each tier requires additional funds to play the game (i.e. paying a penny vs paying a "quarter"). Every game in the arcade must support this concept in game. Thus, most games will display a dropdown UI to allow the player to select what leaderboard they wish to participate in. In order to retrieve the list of leaderboards to show in your dropdown you can use

Note: if you wish your game to support Party Mode you will need to pass in a playerId to the leaderboards method.

In most cases you should be using the formattedName property of the leaderboard in your game client UI. The formatted name will create consistency across the arcade and will display the appropriate currency to the user.

GetLeaderboardsForPlaySelection.tsx

const haste = await Haste.build(
process.env.HASTE_SERVER_CLIENT_ID,
process.env.HASTE_SERVER_CLIENT_SECRET
);
const leaderBoardsWithOutParties = await haste.game.leaderboards();
const leaderBoardsWithParties = await haste.game.leaderboards(playerId);

console.log(leaderBoardsWithOutParties);
console.log(leaderBoardsWithParties); // will include any parties the player has accepted

/*
output:

[{
id: "guid", // The GUID id will be required for the play endpoint
name: "Beginner",
cost: 4, // cost to play in this leaderboard in USD.
currency: 'USD', // the current currency being utilized
formattedName: "Beginner - 4 USD", // the formatted name to be used in a dropdown
}]

*/

Create a function to submit a Play and Score

To play a game in a physical arcade, you have to first insert a quarter. The @hastearcade/server SDK requires a similar flow. Once a player has selected their Leaderboard, the developer will need to submit a "play" to the Haste API via the SDK. The following code shows a demonstration of this concept: The general flow of the scoring process should be:

  • The play call comes back with a good response, indicating the player can start the game.
  • The player plays the game.
  • When the game ends, the score function is called.

Play.ts

const haste = await Haste.build(process.env.HASTE_SERVER_CLIENT_ID, process.env.HASTE_SERVER_CLIENT_SECRET);

/// leaderboardId comes GetLeaderboardsForPlaySelection.tsx
const play = await haste.game.play(new Player(playerId), new Leaderboard(leaderboardId));
console.log(play);

/*
output:

{
id: "guid",
gameId: "your game guid",
playerId: "player guid",
leaderboard: {
id: "guid",
name: "Beginner",
cost: 4,
}
}

When creating your game, make sure to maintain the business logic and scoring logic server-side for security reasons. Do not keep score or make any important game state decisions on the client.

Upon hitting an end state for your game (i.e. the player gets hit by a bomb and dies), it is time to submit your score. To submit a score, you'll need the original play object. The play object can be maintained however you choose (memory, database, cache, etc). The score SDK method takes the current Play object, the appropriate Leaderboard, and the score.

Score.tsx

// the play object is the output from Play.tsx
// score is a number submitted from your game server through the SDK to the Haste API
await haste.game.score(play, score);

Get Leaders

In order to get a list of the current leaders for your game you can use the following function

GetLeaders.tsx

const haste = await Haste.build(process.env.HASTE_SERVER_CLIENT_ID, process.env.HASTE_SERVER_CLIENT_SECRET);
const leaders = await haste.game.leaders(new Leaderboard(leaderboardId));
console.log(leaders);

/*
output:

[
{
playerId: 'player guid',
name: 'player username',
score: 150,
avatar: 'https://www.gravatar.com/avatar/fb69ae3186660885da0fffa0f9f578e5.jpg'
}
]

Get top score

There are times when you will need to get a player's top score for a given leaderboard. For example, in certain games the Haste team shows the player's top score in the game client UI so the player knows their personal best.

GetTopScore.ts

const haste = await Haste.build(process.env.HASTE_SERVER_CLIENT_ID, process.env.HASTE_SERVER_CLIENT_SECRET);

/// leaderboardId comes GetLeaderboardsForPlaySelection.tsx
const topscore = await haste.game.topscore(new Player(playerId), new Leaderboard(leaderboardId));
console.log(topscore);

/*
output:

{
userId: "guid",
value: 0, // The best score of the player for the given leaderboard.
}

Get Play

There are times when you may prefer not to serialize the entire Play object and instead store it in a database or in memory. If you want to store the ID only, then you will need to retrieve the play object before calling the score. To retrieve the full Play object from the Haste API you may use the following:

GetPlay.tsx

const play = await haste.play.find(playId);
console.log(play);

Payment Transaction

When submitting a play, the Haste ecosystem is performing a payout on behalf of the player. The underlying system uses the wallet to perform the payout, and each payout has a transaction hash associated with it. If you need access to the transaction, you can use the following function call:

GetPaymentTransaction.tsx

const haste = await Haste.build(
process.env.HASTE_SERVER_CLIENT_ID,
process.env.HASTE_SERVER_CLIENT_SECRET
);
const play = await haste.game.play(
new Player(playerId),
new Leaderboard(leaderboardId)
);
const transaction = await haste.play.transaction(play); // takes id of play (string) as parameter
console.log(transaction);
/*
output:

{
id: "guid",
status: "COMPLETE",
tx: "transactionhash",
}
*/

NOTE: Payments are performed via asynchronous methods and thus, you may not receive the transaction hash if you call play.transaction() immediately after a play. The best practice is to poll play.transaction() until you receive a tx.

Get Player Details

If you require additional details about a player like their handcash profile id or user name, you can use the getPlayerDetails function.

GetPaymentTransaction.tsx

import { Haste } from "@hastearcade/server";
/// this is custom code specific to your server to retrieve the token from the web request
const token = receiveTokenFromRequest();

try {
const { playerId, userName, handcashProfileId } =
await Haste.getPlayerDetails(token);
console.log(`The player authenticated has an id of ${playerId}`);
} catch (err) {
console.error(`An error occurred while validating the player's token.`);
}

Get Player Payouts

In your game, you may wish to display what a player has earned while playing your game. The SDK provides these details for your game and a specific player - regardless of which level they play at. This will return all payouts they have earned while being a leader on one of game's leaderboards.

.payouts() retrieves all the payouts for a game for a player. The number of payout events can be potentially large, so the endpoint will use a cursor based pagination to optimize performance. There are two primary parameters used to paginate. For the first call you will likely only use the limit query parameter. Once you recieve the first response it will container a data field called ending_before. The second request to the endpoint should pass that ending_before value as the starting_after value. Repeating this operation will allow you to paginate through all the player's payouts. The events are sorted by most recent payouts descending

GetPayouts.tsx

const haste = await Haste.build(
process.env.HASTE_SERVER_CLIENT_ID,
process.env.HASTE_SERVER_CLIENT_SECRET
);

const player = new Player(playerId); // players UUID
const payouts = await haste.game.payouts(player);
// eslint-disable-next-line no-console
console.log(JSON.stringify(payouts, null, 2));

/*
{
"starting_after": "8a3e2337-a8af-4d6b-ab3a-c45bc4aecb6f",
"ending_before": "1feba4de-898e-4a1e-8c7a-fc93bf89cfde",
"events": [
{
"eventId": "a63e2337-a8af-ad6b-af3a-c45bc4aecb6f",
"details": {
"userId": "446d1959-a4ec-adcc-ccdd-d46c9425087d",
"createdAt": "2022-02-18T20:37:19.802Z",
"payeeHandle": "foundrium",
"payerHandle": "rallieon",
"paymentAmount": 200
}
}
]
}
*/

Party Mode

Party Mode enables players to play in smaller groups from the global leaderboard. Perhaps you want to just compete with your friends or some organization you are a part of. By default games have party mode disabled. If you wish players to enjoy party mode for your game, please go into the Developer Portal and enable it.

You will need to be on at least version 2.0.0 for @hastearcade/server to support Party Mode and have it enabled in the Developer Portal. Also please update the call to leaderboards to include the playerId. See Leaderboards for an example.