Skip to content

Commit

Permalink
feat: gnokey logs in console.info (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
thehowl authored Sep 25, 2023
1 parent 4c3da92 commit 2318c73
Showing 1 changed file with 99 additions and 52 deletions.
151 changes: 99 additions & 52 deletions web/assets/js/actions.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
import {saveToLocalStorage} from './utils/localstorage';
import { saveToLocalStorage } from './utils/localstorage';
import {
defaultFaucetTokenKey,
defaultMnemonicKey,
drawRequestTimer,
Game,
type GameoverType,
type GameSettings,
GameState,
GameTime,
Player,
Promotion
defaultFaucetTokenKey,
defaultMnemonicKey,
drawRequestTimer,
Game,
type GameoverType,
type GameSettings,
GameState,
GameTime,
Player,
Promotion
} from './types/types';
import {defaultTxFee, GnoJSONRPCProvider, GnoWallet} from '@gnolang/gno-js-client';
import {BroadcastTxCommitResult, TM2Error, TransactionEndpoint} from '@gnolang/tm2-js-client';
import {generateMnemonic} from './utils/crypto.ts';
import {
defaultTxFee,
GnoJSONRPCProvider,
GnoWallet
} from '@gnolang/gno-js-client';
import {
BroadcastTxCommitResult,
TM2Error,
TransactionEndpoint
} from '@gnolang/tm2-js-client';
import { generateMnemonic } from './utils/crypto.ts';
import Long from 'long';
import Config from './config.ts';
import {constructFaucetError} from './utils/errors.ts';
import {AlreadyInLobbyError, ErrorTransform} from './errors.ts';
import {preparePromotion} from './utils/moves.ts';
import { constructFaucetError } from './utils/errors.ts';
import { AlreadyInLobbyError, ErrorTransform } from './errors.ts';
import { preparePromotion } from './utils/moves.ts';

// ENV values //
// const wsURL: string = Config.GNO_WS_URL; TODO temporarily disabled
Expand All @@ -33,6 +41,14 @@ const cleanUpRealmReturn = (ret: string) => {
const decodeRealmResponse = (resp: string) => {
return cleanUpRealmReturn(atob(resp));
};
const parsedJSONOrRaw = (data: string, nob64 = false) => {
const decoded = nob64 ? cleanUpRealmReturn(data) : decodeRealmResponse(data);
try {
return JSON.parse(decoded);
} finally {
return decoded;
}
};

/**
* Actions is a singleton logic bundler
Expand Down Expand Up @@ -123,19 +139,32 @@ class Actions {
return this.faucetToken || localStorage.getItem(defaultFaucetTokenKey);
}

private gkLog(): Boolean {
const wnd = window as { gnokeyLog?: Boolean };
return typeof wnd.gnokeyLog !== 'undefined' && wnd.gnokeyLog;
}

/**
* Performs a transaction, handling common error cases and transforming them
* into known error types.
*/
public async callMethod(
path: string,
method: string,
args: string[] | null,
gasWanted: Long = defaultGasWanted
): Promise<BroadcastTxCommitResult> {
const gkLog = this.gkLog();
try {
return (await this.wallet?.callMethod(
path,
if (gkLog) {
const gkArgs = args?.map((arg) => '-args ' + arg).join(' ') ?? '';
console.info(
`$ gnokey maketx call -broadcast ` +
`-pkgpath ${chessRealm} -gas-wanted ${gasWanted} -gas-fee ${defaultTxFee} ` +
`-func ${method} ${gkArgs} test1`
);
}
const resp = (await this.wallet?.callMethod(
chessRealm,
method,
args,
TransactionEndpoint.BROADCAST_TX_COMMIT,
Expand All @@ -145,19 +174,52 @@ class Actions {
gasWanted: gasWanted
}
)) as BroadcastTxCommitResult;
if (gkLog) {
console.info('response:', resp);
const respData = resp.deliver_tx.ResponseBase.Data;
if (respData !== null) {
console.info('response (parsed):', parsedJSONOrRaw(respData));
}
}
return resp;
} catch (e) {
const ex = e as { log?: string; message?: string } | undefined;
if (
typeof ex?.log !== 'undefined' &&
typeof ex?.message !== 'undefined' &&
ex.message.includes('abci.StringError')
) {
throw ErrorTransform(e as TM2Error);
e = ErrorTransform(e as TM2Error);
}
if (gkLog) {
console.info('error:', e);
}
throw e;
}
}

public async evaluateExpression(expr: string): Promise<string> {
const gkLog = this.gkLog();
if (gkLog) {
const quotesEscaped = expr.replace(/'/g, `'\\''`);
console.info(
`$ gnokey query vm/qeval --data '${chessRealm}'$'\\n''${quotesEscaped}'`
);
}

const resp = (await this.provider?.evaluateExpression(
chessRealm,
expr
)) as string;

if (gkLog) {
console.info('response:', parsedJSONOrRaw(resp, true));
}

// Parse the response
return resp;
}

/****************
* GAME ENGINE
****************/
Expand All @@ -171,7 +233,7 @@ class Actions {
const seconds = time.time * 60;
// Join the waiting lobby
try {
await this.callMethod(chessRealm, 'LobbyJoin', [
await this.callMethod('LobbyJoin', [
seconds.toString(),
time.increment.toString()
]);
Expand All @@ -188,7 +250,7 @@ class Actions {
return await this.waitForGame();
} catch (e) {
// Unable to find the game, cancel the search
await this.callMethod(chessRealm, 'LobbyQuit', null);
await this.callMethod('LobbyQuit', null);
this.quitLobby();
// Propagate the error
throw new Error('unable to find game');
Expand All @@ -210,7 +272,6 @@ class Actions {
private async lookForGame(): Promise<BroadcastTxCommitResult> {
if (!this.isInTheLobby) throw new Error('Left the lobby');
return (await this.callMethod(
chessRealm,
'LobbyGameFound',
null
)) as BroadcastTxCommitResult;
Expand Down Expand Up @@ -283,8 +344,7 @@ class Actions {
* @param gameID the ID of the running game
*/
public async getGame(gameID: string): Promise<Game> {
const gameResponse: string = (await this.provider?.evaluateExpression(
chessRealm,
const gameResponse: string = (await this.evaluateExpression(
`GetGame("${gameID}")`
)) as string;

Expand All @@ -306,7 +366,7 @@ class Actions {
promotion: Promotion = Promotion.NO_PROMOTION
): Promise<Game> {
// Make the move
const moveResponse = await this.callMethod(chessRealm, 'MakeMove', [
const moveResponse = await this.callMethod('MakeMove', [
gameID,
from,
to,
Expand Down Expand Up @@ -344,9 +404,7 @@ class Actions {
*/
async requestDraw(gameID: string, timeout?: number): Promise<Game> {
// Make the request
const drawResponse = await this.callMethod(chessRealm, 'DrawOffer', [
gameID
]);
const drawResponse = await this.callMethod('DrawOffer', [gameID]);

// Parse the response from the node
const drawResponseRaw: string | null =
Expand Down Expand Up @@ -383,9 +441,7 @@ class Actions {

async claimTimeout(gameID: string): Promise<Game> {
// Make the request
const response = await this.callMethod(chessRealm, 'ClaimTimeout', [
gameID
]);
const response = await this.callMethod('ClaimTimeout', [gameID]);

// Parse the response from the node
const claimTimeoutRaw: string | null =
Expand All @@ -411,11 +467,9 @@ class Actions {
const fetchInterval = setInterval(async () => {
try {
// Get the game
const getGameResponse: string =
(await this.provider?.evaluateExpression(
chessRealm,
`GetGame(${gameID})`
)) as string;
const getGameResponse: string = (await this.evaluateExpression(
`GetGame(${gameID})`
)) as string;

// Parse the response
const game: Game = JSON.parse(cleanUpRealmReturn(getGameResponse));
Expand Down Expand Up @@ -461,9 +515,7 @@ class Actions {
*/
async requestResign(gameID: string): Promise<Game> {
// Make the request
const resignResponse = await this.callMethod(chessRealm, 'Resign', [
gameID
]);
const resignResponse = await this.callMethod('Resign', [gameID]);

// Parse the response from the node
const resignResponseRaw: string | null =
Expand All @@ -482,9 +534,7 @@ class Actions {
*/
async declineDraw(gameID: string): Promise<Game> {
// Make the request
const declineResponse = await this.callMethod(chessRealm, 'DrawRefuse', [
gameID
]);
const declineResponse = await this.callMethod('DrawRefuse', [gameID]);

// Parse the response from the node
const declineResponseRaw: string | null =
Expand All @@ -503,7 +553,7 @@ class Actions {
*/
async acceptDraw(gameID: string): Promise<Game> {
// Make the request
const acceptResponse = await this.callMethod(chessRealm, 'Draw', [gameID]);
const acceptResponse = await this.callMethod('Draw', [gameID]);

// Parse the response from the node
const acceptResponseRaw: string | null =
Expand Down Expand Up @@ -536,11 +586,9 @@ class Actions {
* ordered by their position in the leaderboard
*/
async getLeaderboard(): Promise<Player[]> {
const leaderboardResponse: string =
(await this.provider?.evaluateExpression(
chessRealm,
'Leaderboard()'
)) as string;
const leaderboardResponse: string = (await this.evaluateExpression(
'Leaderboard()'
)) as string;

// Parse the response
return JSON.parse(cleanUpRealmReturn(leaderboardResponse));
Expand All @@ -551,8 +599,7 @@ class Actions {
* @param playerID the ID of the player (can be address or @username)
*/
async getPlayer(playerID: string): Promise<Player> {
const playerResponse: string = (await this.provider?.evaluateExpression(
chessRealm,
const playerResponse: string = (await this.evaluateExpression(
`GetPlayer("${playerID}")`
)) as string;

Expand Down

0 comments on commit 2318c73

Please sign in to comment.