Skip to content

Commit

Permalink
Battleship-zk: fix signless (#446)
Browse files Browse the repository at this point in the history
  • Loading branch information
vraja-nayaka authored Sep 5, 2024
1 parent 1245527 commit ab75078
Show file tree
Hide file tree
Showing 13 changed files with 74 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
display: flex;
flex-direction: column;
gap: 16px;
margin-top: 24px;
}

.input label {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { Button } from '@gear-js/vara-ui';
import { useAccount, useApi, useBalanceFormat } from '@gear-js/react-hooks';
import { useAccount, useAlert, useApi, useBalanceFormat } from '@gear-js/react-hooks';
import { TextField } from '@/components/layout/text-field';
import { isNotEmpty, useForm } from '@mantine/form';
import { Heading } from '@/components/ui/heading';
import { Text } from '@/components/ui/text';
import { EzTransactionsSwitch } from '@dapps-frontend/ez-transactions';
import { SIGNLESS_ALLOWED_ACTIONS } from '@/app/consts';
import { GameDetails } from '@/components/layout/game-details';
import { VaraIcon } from '@/components/layout/vara-svg';
import { usePending } from '@/features/game/hooks';
import { useMultiplayerGame } from '../../hooks';
Expand All @@ -29,6 +28,7 @@ type Props = {
function CreateGameForm({ onCancel }: Props) {
const { account } = useAccount();
const { api } = useApi();
const alert = useAlert();
const { getFormattedBalanceValue } = useBalanceFormat();
const { createGameMessage } = useCreateGameMessage();
const { triggerGame } = useMultiplayerGame();
Expand Down Expand Up @@ -60,13 +60,15 @@ function CreateGameForm({ onCancel }: Props) {
try {
setPending(true);

const transaction = await createGameMessage(values.name);
const withFee = await transaction.withValue(BigInt(getChainBalanceValue(values.fee).toFixed()));
const { response } = await withFee.signAndSend();
const transaction = await createGameMessage(values.name, BigInt(getChainBalanceValue(values.fee).toFixed()));
const { response } = await transaction.signAndSend();

await response();
await triggerGame();
} catch (err) {
const { message, docs } = err as Error & { docs: string };
const errorText = message || docs || 'Create game error';
alert.error(errorText);
console.log(err);
} finally {
setPending(false);
Expand All @@ -83,7 +85,7 @@ function CreateGameForm({ onCancel }: Props) {
</Text>
</div>
</div>
<form className={styles.form} onSubmit={onCreateSubmit(handleCreateSession)}>
<form className={styles.form} id="create_game_form" onSubmit={onCreateSubmit(handleCreateSession)}>
<div className={styles.input}>
<TextField
label="Specify entry fee"
Expand All @@ -106,19 +108,18 @@ function CreateGameForm({ onCancel }: Props) {
/>
<span className={styles.fieldError}>{createErrors.name}</span>
</div>
<EzTransactionsSwitch allowedActions={SIGNLESS_ALLOWED_ACTIONS} />
<div className={styles.buttons}>
<Button type="submit" text="Create game" isLoading={pending} className={styles.button} />
<Button
type="submit"
text="Cancel"
color="grey"
isLoading={pending}
className={styles.button}
onClick={onCancel}
/>
</div>
</form>
<EzTransactionsSwitch allowedActions={SIGNLESS_ALLOWED_ACTIONS} />
<div className={styles.buttons}>
<Button
type="submit"
form="create_game_form"
text="Create game"
isLoading={pending}
className={styles.button}
/>
<Button text="Cancel" color="grey" isLoading={pending} className={styles.button} onClick={onCancel} />
</div>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { Button } from '@gear-js/vara-ui';
import { decodeAddress } from '@gear-js/api';
import { useAccount, useBalanceFormat, withoutCommas } from '@gear-js/react-hooks';
import { useAccount, useAlert, useBalanceFormat, withoutCommas } from '@gear-js/react-hooks';
import { TextField } from '@/components/layout/text-field';
import { isNotEmpty, useForm } from '@mantine/form';
import { HexString } from '@gear-js/api';
Expand Down Expand Up @@ -33,6 +33,7 @@ function JoinGameForm({ onCancel }: Props) {
const { getFormattedBalanceValue } = useBalanceFormat();
const { triggerGame } = useMultiplayerGame();
const { joinGameMessage } = useJoinGameMessage();
const alert = useAlert();
const gameQuery = useMultiGameQuery();
const [foundState, setFoundState] = useState<MultipleGameState | null>(null);
const { pending, setPending } = usePending();
Expand Down Expand Up @@ -83,14 +84,16 @@ function JoinGameForm({ onCancel }: Props) {
setPending(true);

try {
const transaction = await joinGameMessage(foundGame, values.name);
const withFee = await transaction.withValue(BigInt(foundState.bid));
const { response } = await withFee.signAndSend();
const transaction = await joinGameMessage(foundGame, values.name, BigInt(foundState.bid));
const { response } = await transaction.signAndSend();

await response();
await triggerGame();
} catch (err) {
console.log(err);
const { message, docs } = err as Error & { docs: string };
const errorText = message || docs || 'Create game error';
alert.error(errorText);
} finally {
setPending(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export const useCreateGameMessage = () => {
});
const { prepareEzTransactionParams } = usePrepareEzTransactionParams();

const createGameMessage = async (name: string) => {
const createGameMessage = async (name: string, value: bigint) => {
const { sessionForAccount, ...params } = await prepareEzTransactionParams(true);
const { transaction } = await prepareTransactionAsync({
args: [name, sessionForAccount],
...params,
value,
});
return transaction;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ export const useJoinGameMessage = () => {
});
const { prepareEzTransactionParams } = usePrepareEzTransactionParams();

const joinGameMessage = async (game_id: string, name: string) => {
const { sessionForAccount, ...params } = await prepareEzTransactionParams();
const joinGameMessage = async (game_id: string, name: string, value: bigint) => {
const { sessionForAccount, ...params } = await prepareEzTransactionParams(true);
const { transaction } = await prepareTransactionAsync({
args: [game_id, name, sessionForAccount],
...params,
value,
});
return transaction;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { usePrepareProgramTransaction } from '@gear-js/react-hooks';
import { usePrepareEzTransactionParams } from '@dapps-frontend/ez-transactions';
import { useProgram } from '@/app/utils/sails';
import { useConfigurationQuery, useProgram } from '@/app/utils/sails';
import { ProofBytes, PublicStartInput } from '@/app/utils/sails/lib/lib';

export const useVerifyPlacementMessage = () => {
Expand All @@ -11,13 +11,22 @@ export const useVerifyPlacementMessage = () => {
functionName: 'verifyPlacement',
});
const { prepareEzTransactionParams } = usePrepareEzTransactionParams();
const { data: config } = useConfigurationQuery();

const verifyPlacementMessage = async (proof: ProofBytes, public_input: PublicStartInput, game_id: string) => {
const { sessionForAccount, ...params } = await prepareEzTransactionParams();
const { transaction } = await prepareTransactionAsync({
args: [proof, public_input, sessionForAccount, game_id],
...params,
});
const calculatedGas = BigInt(transaction.extrinsic.args[2].toString());

// When calculating gas for two players simultaneously,
// make sure to account for the gas_for_check_time allocated in the contract for a delayed message,
// which will be deducted from the last signing player.
const requiredGas = calculatedGas + BigInt(config?.gas_for_check_time || 0);

await transaction.withGas(requiredGas);
return transaction;
};

Expand Down
3 changes: 2 additions & 1 deletion frontend/packages/ez-transactions/src/context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ function EzTransactionsProvider({ children }: Props) {

const signlessContext = useSignlessTransactions();

const onSessionCreate = async (signlessAccountAddress: string) => gasless.requestVoucher(signlessAccountAddress);
const onSessionCreate = async (signlessAccountAddress: string) =>
gasless.requestVoucher(signlessAccountAddress, false);

const signless = {
...signlessContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const usePrepareEzTransactionParams = () => {
const sessionForAccount = sendFromPair ? account.decodedAddress : null;

let voucherId = sendFromPair ? voucher?.id : gasless.voucherId;
if (account && gasless.isEnabled && !gasless.voucherId && !signless.isActive) {
if (account && gasless.isEnabled && !gasless.voucherId && (sendFromBaseAccount || !signless.isActive)) {
voucherId = await gasless.requestVoucher(account.address);
}

Expand Down
8 changes: 5 additions & 3 deletions frontend/packages/gasless-transactions/src/context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ function GaslessTransactionsProvider({ backendAddress, programId, voucherLimit,
[voucherId, voucherStatus],
);

const requestVoucher = async (_accountAddress: string) =>
const requestVoucher = async (_accountAddress: string, isSaveContext = true) =>
withLoading(
getVoucherId(backendAddress, _accountAddress, programId).then((result) => {
setAccountAddress(_accountAddress);
setVoucherId(result);
if (isSaveContext) {
setAccountAddress(_accountAddress);
setVoucherId(result);
}

return result;
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type GaslessContext = {
isActive: boolean;
voucherStatus: VoucherStatus | null;
expireTimestamp: number | null;
requestVoucher: (accountAddress: string) => Promise<`0x${string}`>;
requestVoucher: (accountAddress: string, isSaveContext?: boolean) => Promise<`0x${string}`>;
setIsEnabled: (value: boolean) => void;
};

Expand Down
22 changes: 20 additions & 2 deletions frontend/packages/signless-transactions/src/context/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
getTypedEntries,
useAccount,
useBalance,
useProgramEvent,
useProgramQuery,
useReadFullState,
useVouchers,
Expand Down Expand Up @@ -31,12 +32,29 @@ function useMetadataSession(programId: HexString, metadata: ProgramMetadata | un

function useSailsSession(program: BaseProgram) {
const { account } = useAccount();
const { data: responseSession } = useProgramQuery({
const { data: responseSession, refetch } = useProgramQuery({
program,
serviceName: 'session',
functionName: 'sessionForTheAccount',
args: [account?.decodedAddress || ''],
watch: true,
});

useProgramEvent({
program,
serviceName: 'session',
functionName: 'subscribeToSessionCreatedEvent',
onData: () => {
refetch();
},
});

useProgramEvent({
program,
serviceName: 'session',
functionName: 'subscribeToSessionDeletedEvent',
onData: () => {
refetch();
},
});

const isSessionReady = responseSession !== undefined;
Expand Down
2 changes: 2 additions & 0 deletions frontend/packages/signless-transactions/src/context/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ type BaseProgram =
sessionForTheAccount: (account: ActorId, ...arg2: BaseProgramQueryProps) => Promise<ProgramSession | null>;
createSession: (signatureData: SignatureData, signature: `0x${string}` | null) => TransactionBuilder<null>;
deleteSessionFromAccount: () => TransactionBuilder<null>;
subscribeToSessionCreatedEvent: (callback: (data: null) => void | Promise<void>) => Promise<() => void>;
subscribeToSessionDeletedEvent: (callback: (data: null) => void | Promise<void>) => Promise<() => void>;
};
registry: TypeRegistry;
}
Expand Down
12 changes: 1 addition & 11 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2611,16 +2611,6 @@ __metadata:
languageName: node
linkType: hard

"@gear-js/vara-ui@npm:0.0.10":
version: 0.0.10
resolution: "@gear-js/vara-ui@npm:0.0.10"
peerDependencies:
react: ^18.2.0
react-dom: ^18.2.0
checksum: 10c0/f8cb7cbf1e6183085386752d86d3e4ad067d308545bfed0c27e22944e11cd74cc469c57e16a288f69b9c18077285825b25c899c630028caf408662bb366b5900
languageName: node
linkType: hard

"@gear-js/vara-ui@npm:0.0.6":
version: 0.0.6
resolution: "@gear-js/vara-ui@npm:0.0.6"
Expand Down Expand Up @@ -23916,7 +23906,7 @@ __metadata:
"@gear-js/api": "npm:0.38.1"
"@gear-js/react-hooks": "npm:0.12.1"
"@gear-js/ui": "npm:0.5.26"
"@gear-js/vara-ui": "npm:0.0.10"
"@gear-js/vara-ui": "npm:0.0.6"
"@headlessui/react": "npm:1.7.13"
"@mantine/form": "npm:6.0.19"
"@polkadot/api": "npm:11.0.2"
Expand Down

0 comments on commit ab75078

Please sign in to comment.