Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@substra-hooks/core",
"version": "0.0.34",
"version": "0.0.35",
"main": "dist/cjs/src/index.js",
"module": "dist/esm/src/index.js",
"types": "dist/esm/src/index.d.ts",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './get-asset-balance';
export * from './fetch-system-properties';
export * from './format-price';
export * from './get-encoded-address';
export * from './noop';
1 change: 1 addition & 0 deletions packages/core/src/helpers/noop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const noop = () => null;
1 change: 1 addition & 0 deletions packages/core/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './use-polkadot-extension';
export * from './use-asset-balance';
export * from './use-encoded-address';
export * from './use-api-provider';
export * from './use-errors';
6 changes: 3 additions & 3 deletions packages/core/src/hooks/use-account-balance.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useContext, useEffect, useState } from 'react';
import { useContext, useEffect } from 'react';
import { useSystemProperties } from './use-system-properties';
import { useIsMountedRef } from '../helpers/use-is-mounted-ref';
import { BalanceReturnType, getAccountBalance } from '../helpers/get-account-balance';
import { useApiProvider } from './use-api-provider';
import { SubstraHooksContext, useSubstraHooksState } from '../providers';
import { BalanceTypes } from '../providers/substrahooks-provider/reducer';
import { BalanceTypes } from '../state/balances';

export const useAccountBalance = (
account: string,
Expand All @@ -31,7 +31,7 @@ export const useAccountBalance = (
locked,
reserved,
total,
available
available,
},
},
});
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/hooks/use-asset-balance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { BalanceReturnType } from '../helpers/get-account-balance';
import { getAssetBalance } from '../helpers/get-asset-balance';
import { useApiProvider } from './use-api-provider';
import { SubstraHooksContext, useSubstraHooksState } from '../providers';
import { BalanceTypes } from '../providers/substrahooks-provider/reducer';
import { BalanceTypes } from '../state/balances';

export const useAssetBalance = (
account: string,
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/hooks/use-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useContext } from 'react';
import { SubstraHooksContext, useSubstraHooksState } from '../providers';

export const useBlockSyncError = (apiProviderId?: string): Error | null => {
const defaultId = useContext(SubstraHooksContext).defaultApiProviderId;
const { errorsState } = useSubstraHooksState();

const networkId = apiProviderId || defaultId;

return errorsState.blockSyncErrors[networkId] || null;
};
25 changes: 16 additions & 9 deletions packages/core/src/providers/substrahooks-provider/context.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
import { createContext, Dispatch, useContext } from 'react';
import { ApiPromise } from '@polkadot/api';
import { ApiPromise, WsProvider } from '@polkadot/api';
import { ISystemProperties } from '../../types/system-properties';
import { BalanceReturnType } from '../../helpers';
import { BalancesActions } from './reducer';
import { BalancesActions, BalancesState } from '../../state/balances';
import { ErrorsActions, ErrorsState } from '../../state/errors';

export type ApiProvider = { apiProvider: ApiPromise | null; systemProperties: ISystemProperties };
export type ApiProvider = {
apiProvider: ApiPromise | null;
systemProperties: ISystemProperties;
wsProvider?: WsProvider;
};
export type ApiProviders = Record<string, ApiProvider>;

export interface BalancesState {
balances: Record<string, BalanceReturnType>;
assets: Record<string, Record<string, BalanceReturnType>>;
}
export const initialErrorsState: ErrorsState = {
blockSyncErrors: {},
};

export const initialBalancesState: BalancesState = {
balances: {},
assets: {}
assets: {},
};

export const SubstraHooksContext = createContext<{
apiProviders: ApiProviders;
defaultApiProviderId: string;
balancesState: BalancesState;
balancesDispatch: Dispatch<BalancesActions>;
errorsState: ErrorsState;
errorsDispatch: Dispatch<ErrorsActions>;
}>({
apiProviders: {},
defaultApiProviderId: '',
errorsState: initialErrorsState,
errorsDispatch: () => null,
balancesState: initialBalancesState,
balancesDispatch: () => null,
});
Expand Down
46 changes: 43 additions & 3 deletions packages/core/src/providers/substrahooks-provider/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import {
import { ExtensionProvider } from '../extension';
import { useIsMountedRef } from '../../helpers/use-is-mounted-ref';
import { RegistryTypes } from '@polkadot/types/types';
import { balancesReducer } from './reducer';
import { balancesReducer, BalanceTypes } from '../../state/balances';
import { ErrorActionTypes, errorsReducer } from '../../state/errors';
import { initialErrorsState } from '.';
import { noop } from '../..';

const _apiProviders: ApiProviders = {};

Expand All @@ -34,18 +37,24 @@ export const initPolkadotPromise = async (
let systemProperties = systemPropertiesDefaults;
try {
const wsProvider = new WsProvider(wsProviderUrl);
polkadotApi = await ApiPromise.create({ provider: wsProvider, types: types, throwOnConnect: true });
polkadotApi = await ApiPromise.create({
provider: wsProvider,
types: types,
throwOnConnect: true,
});
await polkadotApi.isReady;
systemProperties = await fetchSystemProperties(polkadotApi);
_apiProviders[id] = {
systemProperties,
apiProvider: polkadotApi,
wsProvider,
};
} catch (error: any) {
console.warn(`RPC ${wsProviderUrl} has failed with an error`, error);
}

_apiProviders[id] = {
..._apiProviders[id],
systemProperties,
apiProvider: polkadotApi,
};
Expand All @@ -72,6 +81,7 @@ export const SubstraHooksProvider = ({
autoInitialiseExtension,
}: ISubstraHooksProviderProps) => {
const [apiProviders, setApiProviders] = useState<ApiProviders>({});
const [errorsState, errorsDispatch] = useReducer(errorsReducer, initialErrorsState);
const [balancesState, balancesDispatch] = useReducer(balancesReducer, initialBalancesState);
const isMountedRef = useIsMountedRef();

Expand All @@ -81,13 +91,43 @@ export const SubstraHooksProvider = ({
if (isMountedRef.current) {
setApiProviders(apiProviders);
}
Object.keys(apiProviders).map((apiProviderId) => {
const wsProvider = apiProviders[apiProviderId].wsProvider;
const errorHandler = (error: Error | string) => {
errorsDispatch({
type: ErrorActionTypes.BLOCK_SYNC_ERROR,
payload: {
network: apiProviderId,
error: typeof error === 'string' ? new Error(error) : error,
},
});
};
const connectedHandler = () => {
errorsDispatch({
type: ErrorActionTypes.BLOCK_SYNC_ERROR,
payload: {
network: apiProviderId,
error: undefined,
},
});
};
wsProvider?.on('error', errorHandler);
wsProvider?.on('connected', connectedHandler);
});
});
}
}, [JSON.stringify(apiProviderConfig), isMountedRef]);

return (
<SubstraHooksContext.Provider
value={{ apiProviders, defaultApiProviderId, balancesState, balancesDispatch }}>
value={{
apiProviders,
defaultApiProviderId,
errorsState,
errorsDispatch,
balancesState,
balancesDispatch,
}}>
<ExtensionProvider autoInitialiseExtension={autoInitialiseExtension}>
{children}
</ExtensionProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { merge } from 'ramda';
import { BalanceReturnType } from '../../helpers';
import { ActionMap } from '../../types/reducer';
import { BalancesState } from './context';
import { BalanceReturnType } from '../helpers';
import { ActionMap } from '../types/reducer';

export interface BalancesState {
balances: Record<string, BalanceReturnType>;
assets: Record<string, Record<string, BalanceReturnType>>;
}

export enum BalanceTypes {
SET_BALANCE = 'SET_BALANCE',
Expand Down
35 changes: 35 additions & 0 deletions packages/core/src/state/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { merge } from 'ramda';
import { ActionMap } from '../types/reducer';

export interface ErrorsState {
blockSyncErrors: {
[network: string]: Error | undefined;
};
}

export enum ErrorActionTypes {
BLOCK_SYNC_ERROR = 'BLOCK_SYNC_ERROR',
}

type ErrorsPayload = {
[ErrorActionTypes.BLOCK_SYNC_ERROR]: {
network: string;
error?: Error;
};
};

export type ErrorsActions = ActionMap<ErrorsPayload>[keyof ActionMap<ErrorsPayload>];

export const errorsReducer = (state: ErrorsState, action: ErrorsActions) => {
switch (action.type) {
case ErrorActionTypes.BLOCK_SYNC_ERROR:
return merge(state, {
blockSyncErrors: merge(state.blockSyncErrors, {
[action.payload.network]: action.payload.error,
}),
});

default:
return state;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ import { ApiProviderConfig, SubstraHooksProvider } from '@substra-hooks/core';
interface ISubstraHooksProviderProps {
apiProviderConfig: ApiProviderConfig;
children: ReactNode;
defaultApiProviderId?: string;
}

const SubstraHooksProviderSSR = ({ apiProviderConfig, children }: ISubstraHooksProviderProps) => {
const SubstraHooksProviderSSR = ({
apiProviderConfig,
children,
defaultApiProviderId,
}: ISubstraHooksProviderProps) => {
return (
<SubstraHooksProvider
apiProviderConfig={apiProviderConfig}
defaultApiProviderId={'kusama'}
defaultApiProviderId={defaultApiProviderId || 'kusama'}
autoInitialiseExtension>
{children}
</SubstraHooksProvider>
Expand Down
2 changes: 0 additions & 2 deletions packages/example-nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
"lint": "next lint"
},
"dependencies": {
"@substra-hooks/core": "^0.0.28",
"next": "12.0.3",
"react": "17.0.2",
"react-dom": "17.0.2"
},
"devDependencies": {
"@substra-hooks/core": "*",
"@types/node": "16.11.6",
"@types/react": "17.0.34",
"eslint": "7",
Expand Down
5 changes: 5 additions & 0 deletions packages/example-nextjs/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const SubstraHooksProviderSSR = dynamic(() => import('../components/app/substra-
function MyApp({ Component, pageProps }: AppProps) {
return (
<SubstraHooksProviderSSR
defaultApiProviderId="development"
apiProviderConfig={{
kusama: {
id: 'kusama',
Expand All @@ -17,6 +18,10 @@ function MyApp({ Component, pageProps }: AppProps) {
id: 'statemine',
wsProviderUrl: 'wss://statemine-rpc.polkadot.io',
},
development: {
id: 'development',
wsProviderUrl: 'ws://127.0.0.1:9944',
},
}}>
<Component {...pageProps} />
</SubstraHooksProviderSSR>
Expand Down
10 changes: 10 additions & 0 deletions packages/example-nextjs/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
useAssetBalance,
usePolkadotExtension,
useSystemProperties,
useBlockSyncError,
} from '@substra-hooks/core';
import { useEffect } from 'react';
import Link from 'next/link';
Expand All @@ -22,6 +23,8 @@ const Home: NextPage = () => {
);
const systemProperties = useSystemProperties();

const blockSyncError = useBlockSyncError('development');

console.log('systemProperties', systemProperties);

useEffect(() => {
Expand All @@ -43,6 +46,13 @@ const Home: NextPage = () => {
</Head>

<main className={styles.main}>
{blockSyncError && (
<div style={{ color: 'red' }}>
<div>Block sync error:</div>
<div>{JSON.stringify(blockSyncError, null, 2)}</div>
<br />
</div>
)}
<div>Balance: {balancePayload?.balance.formatted}</div>
<div>Locked Balance: {balancePayload && balancePayload?.locked?.formatted}</div>
<div>Reserved Balance: {balancePayload?.reserved?.formatted}</div>
Expand Down
Loading