Skip to content

Commit

Permalink
feat: integrated cosmosJS and bank slice (#840)
Browse files Browse the repository at this point in the history
  • Loading branch information
charymalloju authored Nov 6, 2023
2 parents a97ea60 + d84702d commit 9c22a5f
Show file tree
Hide file tree
Showing 22 changed files with 1,657 additions and 3,462 deletions.
10 changes: 7 additions & 3 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
"lint": "next lint --no-cache"
},
"dependencies": {
"@cosmjs/amino": "^0.31.3",
"@cosmjs/proto-signing": "^0.31.3",
"@cosmjs/stargate": "^0.31.3",
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.1",
"@emotion/server": "^11.11.0",
Expand All @@ -25,10 +28,11 @@
"cosmjs-types": "^0.9.0",
"eslint": "8.50.0",
"eslint-config-next": "13.5.2",
"next": "14.0.1",
"mathjs": "^12.0.0",
"next": "^14.0.1",
"postcss": "8.4.30",
"react": "18.2.0",
"react-dom": "18.2.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.47.0",
"react-redux": "^8.1.3",
"tailwindcss": "3.3.3",
Expand Down
33 changes: 12 additions & 21 deletions frontend/src/components/ConnectWalletButton.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client';
import React, { useEffect, useState } from 'react';
import { networks } from '../utils/chainsInfo';
import Image from 'next/image';
import Walletpage from './popups/WalletPage';
import { getWalletName, isConnected } from '../utils/localStorage';
import { useDispatch, useSelector } from 'react-redux';
import { connectWalletV1 } from '../store/features/wallet/walletSlice';
import { AppDispatch, RootState } from '../store/store';
"use client";
import React, { useEffect, useState } from "react";
import { networks } from "../utils/chainsInfo";
import Image from "next/image";
import Walletpage from "./popups/WalletPage";
import { getWalletName, isConnected } from "../utils/localStorage";
import { useDispatch, useSelector } from "react-redux";
import { establishWalletConnection } from "../store/features/wallet/walletSlice";
import { AppDispatch, RootState } from "../store/store";

export const ConnectWalletButton = ({
children,
Expand All @@ -24,30 +24,21 @@ export const ConnectWalletButton = ({
};

const selectWallet = (walletName: string) => {
dispatch(
connectWalletV1({
walletName,
mainnets: networks,
testnets: [],
})
);
tryConnectWallet(walletName)
handleClose();
};

const tryConnectWallet = (walletName: string) => {
dispatch(
connectWalletV1({
establishWalletConnection({
walletName,
mainnets: networks,
testnets: [],
networks: networks,
})
);
};

useEffect(() => {
const walletName = getWalletName();
console.log(walletName);

if (isConnected()) {
tryConnectWallet(walletName);
}
Expand Down
14 changes: 0 additions & 14 deletions frontend/src/components/TestClientComponent.tsx

This file was deleted.

38 changes: 38 additions & 0 deletions frontend/src/store/features/bank/bankService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import Axios, { AxiosResponse } from 'axios';
import { convertPaginationToParams, cleanURL } from '../../../utils/util';
import { KeyLimitPagination } from '../../../types/types';

const balancesURL = '/cosmos/bank/v1beta1/balances/';
const balanceURL = (address: string, denom: string) =>
`/cosmos/bank/v1beta1/balances/${address}/by_denom?denom=${denom}`;

const fetchBalances = (
baseURL: string,
address: string,
pagination: KeyLimitPagination
): Promise<AxiosResponse> => {
let uri = `${cleanURL(baseURL)}${balancesURL}${address}`;
const parsed = convertPaginationToParams(pagination);
if (parsed !== '') {
uri += `?${parsed}`;
}

return Axios.get(uri);
};

const fetchBalance = (
baseURL: string,
address: string,
denom: string
): Promise<AxiosResponse> => {
const uri = `${cleanURL(baseURL)}${balanceURL(address, denom)}`;

return Axios.get(uri);
};

const result = {
balances: fetchBalances,
balance: fetchBalance,
};

export default result;
183 changes: 183 additions & 0 deletions frontend/src/store/features/bank/bankSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { SendMsg } from '../../../txns/bank';
import bankService from './bankService';
import { signAndBroadcast } from '../../../utils/signing';
import { Coin } from 'cosmjs-types/cosmos/base/v1beta1/coin';
import { KeyLimitPagination } from '../../../types/types';
import { TxStatus } from '../../../types/store';
import { GAS_FEE } from 'staking/utils/constants';
import { MultiTxnsInputs, TxSendInputs } from 'staking/types/bank';

interface Balance {
list: Coin[];
status: TxStatus;
errMsg: string;
}
interface BankState {
balances: Record<string, Balance>;
tx: {
status: TxStatus;
};
multiSendTx: {
status: TxStatus;
};
}

const initialState: BankState = {
balances: {},
tx: {
status: TxStatus.INIT,
},
multiSendTx: { status: TxStatus.INIT },
};

export const getBalances = createAsyncThunk(
'bank/balances',
async (data: {
baseURL: string;
address: string;
chainID: string;
pagination: KeyLimitPagination;
}) => {
const response = await bankService.balances(
data.baseURL,
data.address,
data.pagination
);
return {
chainID: data.chainID,
data: response.data,
};
}
);


export const multiTxns = createAsyncThunk(
'bank/multi-txs',
async (
data: MultiTxnsInputs,
{ rejectWithValue, fulfillWithValue }
) => {
try {
const result = await signAndBroadcast(
data.basicChainInfo.chainID,
data.basicChainInfo.aminoConfig,
data.prefix,
data.msgs,
GAS_FEE,
data.memo,
`${data.feeAmount}${data.denom}`,
data.basicChainInfo.rest,
data.feegranter?.length > 0 ? data.feegranter : undefined
);
if (result?.code === 0) {
return fulfillWithValue({ txHash: result?.transactionHash });
} else {
return rejectWithValue(result?.rawLog);
}
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
} catch (error: any) {
return rejectWithValue(error.message);
}
}
);

export const txBankSend = createAsyncThunk(
'bank/tx-bank-send',
async (
data: TxSendInputs,
{ rejectWithValue, fulfillWithValue }
) => {
try {
const msg = SendMsg(data.from, data.to, data.amount, data.denom);
const result = await signAndBroadcast(
data.basicChainInfo.chainID,
data.basicChainInfo.aminoConfig,
data.prefix,
[msg],
GAS_FEE,
data.memo,
`${data.feeAmount}${data.denom}`,
data.basicChainInfo.rest,
data.feegranter?.length > 0 ? data.feegranter : undefined
);
if (result?.code === 0) {
return fulfillWithValue({ txHash: result?.transactionHash });
} else {
return rejectWithValue(result?.rawLog);
}
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
} catch (error: any) {
return rejectWithValue(error.message);
}
}
);

export const bankSlice = createSlice({
name: 'bank',
initialState,
reducers: {
claimRewardInBank: (state: BankState, action) => {
const { chainID, totalRewards, minimalDenom } = action.payload;
for (let i = 0; i < state?.balances?.[chainID]?.list?.length; i++) {
if (state.balances[chainID]?.list?.[i]?.denom === minimalDenom) {
state.balances[chainID].list[i].amount =
+state.balances[chainID].list[i].amount + totalRewards;
}
}
},
resetMultiSendTxRes: (state) => {
state.multiSendTx = { status: TxStatus.INIT };
},
},

extraReducers: (builder) => {
builder
.addCase(getBalances.pending, (state: BankState, action) => {
const chainID = action.meta.arg.chainID;
state.balances[chainID].status = TxStatus.PENDING;
})
.addCase(getBalances.fulfilled, (state, action) => {
const chainID = action.payload.chainID;
const result = {
list: action.payload.data?.balances,
status: TxStatus.IDLE,
errMsg: '',
};
state.balances[chainID] = result;
})
.addCase(getBalances.rejected, (state: BankState, action) => {
const chainID = action.meta.arg.chainID;
state.balances[chainID] = {
status: TxStatus.REJECTED,
errMsg:
action?.error?.message || 'requested rejected for unknown reason',
list: [],
};
})
.addCase(txBankSend.pending, (state) => {
state.tx.status = TxStatus.PENDING;
})
.addCase(txBankSend.fulfilled, (state) => {
state.tx.status = TxStatus.IDLE;
})
.addCase(txBankSend.rejected, (state) => {
state.tx.status = TxStatus.REJECTED;
})
.addCase(multiTxns.pending, (state) => {
state.tx.status = TxStatus.PENDING;
state.multiSendTx.status = TxStatus.PENDING;
})
.addCase(multiTxns.fulfilled, (state) => {
state.tx.status = TxStatus.IDLE;
state.multiSendTx.status = TxStatus.IDLE;
})
.addCase(multiTxns.rejected, (state) => {
state.tx.status = TxStatus.REJECTED;
state.multiSendTx.status = TxStatus.REJECTED;
});
},
});

export const { claimRewardInBank, resetMultiSendTxRes } = bankSlice.actions;
export default bankSlice.reducer;
Loading

0 comments on commit 9c22a5f

Please sign in to comment.