Skip to content

Commit

Permalink
feat(cip-1694): integrate fetch receipt
Browse files Browse the repository at this point in the history
  • Loading branch information
vetalcore committed Jul 26, 2023
1 parent 0f66c2c commit 6978744
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 76 deletions.
1 change: 1 addition & 0 deletions ui/cip-1694/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ REACT_APP_CATEGORY_ID=CIP-1694_Pre_Ratification_4619

REACT_APP_EVENT_BY_ID_REFERENCE_URL=${REACT_APP_SERVER_URL}/api/reference/event
REACT_APP_CAST_VOTE_URL=${REACT_APP_SERVER_URL}/api/vote/cast
REACT_APP_VOTE_RECEIPT_URL=${REACT_APP_SERVER_URL}/api/vote/receipt
REACT_APP_BLOCKCHAIN_TIP_URL=${REACT_APP_SERVER_URL}/api/blockchain/tip
REACT_APP_VOTING_POWER_URL=${REACT_APP_SERVER_URL}/api/account

Expand Down
45 changes: 29 additions & 16 deletions ui/cip-1694/src/common/api/voteService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,51 @@ import { DEFAULT_CONTENT_TYPE_HEADERS, doRequest, HttpMethods } from '../handler
import {
EVENT_BY_ID_REFERENCE_URL,
CAST_VOTE_URL,
VOTE_RECEIPT_URL,
BLOCKCHAIN_TIP_URL,
VOTING_POWER_URL,
} from '../constants/appConstants';
import { Problem, SignedWeb3Request, Vote, Event, ChainTip, Account } from '../../types/backend-services-types';
import {
Problem,
SignedWeb3Request,
Vote,
Event,
ChainTip,
Account,
VoteReceipt,
} from '../../types/backend-services-types';

const getEventById = async (eventId: Event['id']) =>
export const getEventById = async (eventId: Event['id']) =>
await doRequest<Vote>(HttpMethods.GET, `${EVENT_BY_ID_REFERENCE_URL}/${eventId}`, {
...DEFAULT_CONTENT_TYPE_HEADERS,
});

const castAVoteWithDigitalSignature = async (jsonRequest: SignedWeb3Request) =>
export const castAVoteWithDigitalSignature = async (jsonRequest: SignedWeb3Request) =>
await doRequest<Problem | Vote>(
HttpMethods.POST,
`${CAST_VOTE_URL}`,
{ ...DEFAULT_CONTENT_TYPE_HEADERS },
CAST_VOTE_URL,
DEFAULT_CONTENT_TYPE_HEADERS,
JSON.stringify(jsonRequest),
false
);

const getSlotNumber = async () => {
return await doRequest<ChainTip>(HttpMethods.GET, `${BLOCKCHAIN_TIP_URL}`, { ...DEFAULT_CONTENT_TYPE_HEADERS });
export const getSlotNumber = async () => {
return await doRequest<ChainTip>(HttpMethods.GET, BLOCKCHAIN_TIP_URL, DEFAULT_CONTENT_TYPE_HEADERS);
};

const getVotingPower = async (eventId: Event['id'], stakeAddress: string) => {
return await doRequest<Account>(HttpMethods.GET, `${VOTING_POWER_URL}/${eventId}/${stakeAddress}`, {
...DEFAULT_CONTENT_TYPE_HEADERS,
});
export const getVoteReceipt = async (jsonRequest: SignedWeb3Request) => {
return await doRequest<Problem | VoteReceipt>(
HttpMethods.POST,
VOTE_RECEIPT_URL,
DEFAULT_CONTENT_TYPE_HEADERS,
JSON.stringify(jsonRequest)
);
};

export const voteService = {
getEventById: getEventById,
castAVoteWithDigitalSignature: castAVoteWithDigitalSignature,
getSlotNumber: getSlotNumber,
getVotingPower: getVotingPower,
export const getVotingPower = async (eventId: Event['id'], stakeAddress: string) => {
return await doRequest<Account>(
HttpMethods.POST,
`${VOTING_POWER_URL}/${eventId}/${stakeAddress}`,
DEFAULT_CONTENT_TYPE_HEADERS
);
};
1 change: 1 addition & 0 deletions ui/cip-1694/src/common/constants/appConstants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Services URLs
export const EVENT_BY_ID_REFERENCE_URL = process.env.EVENT_BY_ID_REFERENCE_URL;
export const CAST_VOTE_URL = process.env.REACT_APP_CAST_VOTE_URL;
export const VOTE_RECEIPT_URL = process.env.REACT_APP_VOTE_RECEIPT_URL;
export const BLOCKCHAIN_TIP_URL = process.env.REACT_APP_BLOCKCHAIN_TIP_URL;
export const VOTING_POWER_URL = process.env.REACT_APP_VOTING_POWER_URL;

Expand Down
25 changes: 16 additions & 9 deletions ui/cip-1694/src/common/handlers/httpHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,10 @@ type AnuthorizedResponse = {
fault?: { faultstring?: string };
message?: string;
Error?: string | Error;
title?: string;
} & Response;
async function getErrorMessage(response: AnuthorizedResponse): Promise<string> {

const getErrorMessage = (response: AnuthorizedResponse): string => {
if (response.error) {
return response.error_description ? response.error_description : response.error;
} else if (response.errors && response.errors.length > 0) {
Expand All @@ -68,6 +70,8 @@ async function getErrorMessage(response: AnuthorizedResponse): Promise<string> {
return messages.toString();
} else if (response.fault && response.fault.faultstring) {
return response.fault.faultstring;
} else if (response.title) {
return response.title;
} else if (response.message) {
try {
const errors = JSON.parse(response.message);
Expand All @@ -84,7 +88,7 @@ async function getErrorMessage(response: AnuthorizedResponse): Promise<string> {
} else {
return '' + response;
}
}
};

export function responseErrorsHandler() {
return {
Expand All @@ -108,20 +112,23 @@ export function responseHandlerDelegate<T>() {

return {
async parse(response: Response | AnuthorizedResponse): Promise<T | never> {
let json!: T & Errors;
let parsedResponse!: T & Errors;

const contentType = response.headers.get(Headers.CONTENT_TYPE.toLowerCase());
const isJson = contentType && contentType.indexOf(MediaTypes.APPLICATION_JSON) !== -1;
try {
json = await response.json();
} catch (err) {
parsedResponse = await response[isJson ? 'json' : 'text']();
if (response.status !== 200) {
throw new HttpError(401, response.url, await getErrorMessage(response));
throw new HttpError(401, response.url, getErrorMessage(parsedResponse));
}
} catch (error) {
throw new Error(error);
}

if (typeof json === 'object' && 'errors' in json && json.errors.length >= 1) {
throw new HttpError(400, response.url, errorsHandler.parse(json.errors));
if (parsedResponse?.errors?.length >= 1) {
throw new HttpError(400, response.url, errorsHandler.parse(parsedResponse.errors));
} else {
return json;
return parsedResponse;
}
},
};
Expand Down
4 changes: 4 additions & 0 deletions ui/cip-1694/src/common/store/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { VoteReceipt } from 'types/backend-services-types';

export interface UserState {
isConnectWalletModalVisible: boolean;
isVoteSubmittedModalVisible: boolean;
connectedWallet: string;
isReceiptFetched: boolean;
receipt: VoteReceipt | null;
}

export interface State {
Expand Down
17 changes: 16 additions & 1 deletion ui/cip-1694/src/common/store/userSlice.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import { VoteReceipt } from 'types/backend-services-types';
import { UserState } from './types';

const initialState: UserState = {
isConnectWalletModalVisible: false,
isVoteSubmittedModalVisible: false,
connectedWallet: '',
isReceiptFetched: false,
receipt: null,
};

export const userSlice = createSlice({
Expand All @@ -21,8 +24,20 @@ export const userSlice = createSlice({
setConnectedWallet: (state, action: PayloadAction<{ wallet: string }>) => {
state.connectedWallet = action.payload.wallet;
},
setVoteReceipt: (state, action: PayloadAction<{ receipt: VoteReceipt }>) => {
state.receipt = action.payload.receipt;
},
setIsReceiptFetched: (state, action: PayloadAction<{ isFetched: boolean }>) => {
state.isReceiptFetched = action.payload.isFetched;
},
},
});

export const { setIsConnectWalletModalVisible, setIsVoteSubmittedModalVisible, setConnectedWallet } = userSlice.actions;
export const {
setIsConnectWalletModalVisible,
setIsVoteSubmittedModalVisible,
setConnectedWallet,
setVoteReceipt,
setIsReceiptFetched,
} = userSlice.actions;
export default userSlice.reducer;
3 changes: 2 additions & 1 deletion ui/cip-1694/src/components/OptionCard/OptionCard.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import DoneIcon from '@mui/icons-material/Done';
import CloseIcon from '@mui/icons-material/Close';
import DoDisturbIcon from '@mui/icons-material/DoDisturb';
import { OptionCard } from './OptionCard';
import { OptionItem } from './OptionCard.types';

const items = [
const items: OptionItem[] = [
{
label: 'Yes',
icon: <DoneIcon />,
Expand Down
2 changes: 1 addition & 1 deletion ui/cip-1694/src/components/OptionCard/OptionCard.types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';

interface OptionItem {
label: string;
label: 'Yes' | 'No' | 'Abstain';
icon: React.ReactElement | null;
}

Expand Down
Loading

0 comments on commit 6978744

Please sign in to comment.