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
4 changes: 2 additions & 2 deletions examples/demo-multi-clients/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import { usePolkadotClient, useTypink } from 'typink';

function App() {
const { networks } = useTypink();
const [relay, assethub, people] = networks;
const { status: relayStatus } = usePolkadotClient(relay?.id);
const [assethub, people] = networks;
const { status: relayStatus } = usePolkadotClient();
const { status: assetHubStatus } = usePolkadotClient(assethub?.id);
const { status: peopleStatus } = usePolkadotClient(people?.id);

Expand Down
2 changes: 1 addition & 1 deletion packages/create-typink/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-typink",
"version": "0.4.0",
"version": "0.4.1",
"author": "Tung Vu <tung@dedot.dev>",
"homepage": "https://typink.dev",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/typink/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typink",
"version": "0.4.0",
"version": "0.4.1",
"description": "Fully-typed react hooks to interact with ink! smart contract powered by Dedot!",
"author": "Thang X. Vu <thang@dedot.dev>",
"homepage": "https://typink.dev",
Expand Down
4 changes: 2 additions & 2 deletions packages/typink/src/hooks/usePolkadotClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export function usePolkadotClient<ChainApi extends VersionedGenericSubstrateApi
}, [getClient, networkId]);

const status = useMemo(() => {
return connectionStatus.get(networkId || '') || ClientConnectionStatus.NotConnected;
}, [connectionStatus, networkId]);
return connectionStatus.get(network.id || '') || ClientConnectionStatus.NotConnected;
}, [connectionStatus, network]);

return { client, network, status };
}
4 changes: 0 additions & 4 deletions packages/typink/src/networks/mainnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ export const polkadot: NetworkInfo = {
logo: `${CHAIN_ASSETS_BASE_URL}/assets/chains/polkadot.png`,
providers: [
'wss://polkadot-rpc.dwellir.com',
'wss://polkadot.public.curie.radiumblock.co/ws',
'wss://dot-rpc.stakeworld.io',
'wss://rpc-polkadot.luckyfriday.io',
'wss://polkadot-rpc-tn.dwellir.com',
Expand Down Expand Up @@ -96,7 +95,6 @@ export const polkadotPeople: NetworkInfo = {
providers: [
'wss://polkadot-people-rpc.polkadot.io',
'wss://rpc-people-polkadot.luckyfriday.io',
'wss://people-polkadot.public.curie.radiumblock.co/ws',
'wss://sys.ibp.network/people-polkadot',
'wss://sys.dotters.network/people-polkadot',
'wss://people-polkadot.dotters.network',
Expand All @@ -116,7 +114,6 @@ export const kusama: NetworkInfo = {
name: 'Kusama',
logo: `${CHAIN_ASSETS_BASE_URL}/assets/chains/kusama.png`,
providers: [
'wss://kusama.public.curie.radiumblock.co/ws',
'wss://kusama-rpc-tn.dwellir.com',
'wss://rpc-kusama.luckyfriday.io',
'wss://ksm-rpc.stakeworld.io',
Expand Down Expand Up @@ -148,7 +145,6 @@ export const kusamaAssetHub: NetworkInfo = {
'wss://rpc-asset-hub-kusama.luckyfriday.io',
'wss://assethub-kusama.api.onfinality.io/public-ws',
'wss://kusama-asset-hub-rpc.polkadot.io',
'wss://statemine.public.curie.radiumblock.co/ws',
'wss://ksm-rpc.stakeworld.io/assethub',
],
symbol: 'KSM',
Expand Down
8 changes: 5 additions & 3 deletions packages/typink/src/providers/ClientProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,16 +157,18 @@ export function ClientProvider({
const [networkConnections, setNetworkConnections] = useAtom(networkConnectionsAtom);

// Initialize network connections and default network ID properly
useEffect(() => {
useMemo(() => {
if (supportedNetworks.length === 0) return;

// Check if we have stored connections from localStorage
if (networkConnections.length === 0 && initialConnections.length > 0) {
setNetworkConnections(initialConnections);
} else if (networkConnections.length > 0) {
// Check if all existing connections are in the supported networks list
// Check if all existing connections are in the supported networks or default networks list
const hasInvalidNetwork = networkConnections.some(
(conn) => !supportedNetworks.find((n) => n.id === conn.networkId),
(conn) =>
!supportedNetworks.find((n) => n.id === conn.networkId) ||
!initialConnections.find((n) => n.networkId === conn.networkId),
);

if (hasInvalidNetwork) {
Expand Down
70 changes: 52 additions & 18 deletions packages/typink/src/providers/__tests__/ClientProvider.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,16 +106,33 @@ describe('ClientProvider localStorage validation', () => {
});

describe('Valid persisted connections', () => {
it('should preserve valid networkConnections from localStorage', () => {
const wrapper = createWrapper(['polkadot'], validConnections);
it('should preserve valid networkConnections from localStorage when they match defaults', () => {
// Use connections that match the default networks
const matchingConnections: NetworkConnection[] = [
{ networkId: 'polkadot' },
{ networkId: 'kusama', provider: 'wss://custom.kusama.provider' },
];
const wrapper = createWrapper(['polkadot', 'kusama'], matchingConnections);

const { result } = renderHook(() => useClient(), { wrapper });

// Should keep the persisted connections since they're all valid
expect(result.current.networkConnections).toEqual(validConnections);
// Should keep the persisted connections since they match defaults
expect(result.current.networkConnections).toEqual(matchingConnections);
expect(consoleWarnSpy).not.toHaveBeenCalled();
});

it('should reset when persisted connections don\'t match defaults', () => {
const wrapper = createWrapper(['polkadot'], validConnections);

const { result } = renderHook(() => useClient(), { wrapper });

// Should reset to default because kusama is not in defaultNetworkIds
expect(result.current.networkConnections).toEqual([{ networkId: 'polkadot' }]);
expect(consoleWarnSpy).toHaveBeenCalledWith(
'Some persisted network connections are not in the supported networks list. Resetting to default networks.'
);
});

it('should preserve connections when all networks exist in supportedNetworks', () => {
const persistedConnections: NetworkConnection[] = [
{ networkId: 'kusama', provider: 'wss://kusama.example' },
Expand All @@ -126,8 +143,11 @@ describe('ClientProvider localStorage validation', () => {

const { result } = renderHook(() => useClient(), { wrapper });

expect(result.current.networkConnections).toEqual(persistedConnections);
expect(consoleWarnSpy).not.toHaveBeenCalled();
// Should reset because kusama and westend are not in defaultNetworkIds
expect(result.current.networkConnections).toEqual([{ networkId: 'polkadot' }]);
expect(consoleWarnSpy).toHaveBeenCalledWith(
'Some persisted network connections are not in the supported networks list. Resetting to default networks.'
);
});

it('should preserve empty array if that is what was persisted', () => {
Expand Down Expand Up @@ -294,10 +314,16 @@ describe('ClientProvider localStorage validation', () => {
});

it('should not warn when no invalid networks exist', () => {
const wrapper = createWrapper(['polkadot'], validConnections);
// Use connections that match defaults
const matchingConnections: NetworkConnection[] = [
{ networkId: 'polkadot' },
{ networkId: 'kusama' },
];
const wrapper = createWrapper(['polkadot', 'kusama'], matchingConnections);

renderHook(() => useClient(), { wrapper });

// Should not warn when connections match defaults
expect(consoleWarnSpy).not.toHaveBeenCalled();
});

Expand Down Expand Up @@ -336,9 +362,14 @@ describe('ClientProvider localStorage validation', () => {

const { result } = renderHook(() => useClient(), { wrapper });

// Should keep localStorage since kusama is valid, even though it's different from defaults
expect(result.current.networkConnections).toEqual(subsetConnections);
expect(consoleWarnSpy).not.toHaveBeenCalled();
// Should reset because kusama is not in defaultNetworks
expect(result.current.networkConnections).toEqual([
{ networkId: 'polkadot' },
{ networkId: 'westend' },
]);
expect(consoleWarnSpy).toHaveBeenCalledWith(
'Some persisted network connections are not in the supported networks list. Resetting to default networks.'
);
});
});

Expand All @@ -361,15 +392,17 @@ describe('ClientProvider localStorage validation', () => {

it('should follow correct branching: populated localStorage with valid networks -> preserve', () => {
const defaultNetworks = ['polkadot']; // Different from what's in localStorage

// Start with valid connections in localStorage
const wrapper = createWrapper(defaultNetworks, validConnections);

const { result } = renderHook(() => useClient(), { wrapper });

// Should enter second branch: networkConnections.length > 0, but hasInvalidNetwork = false
expect(result.current.networkConnections).toEqual(validConnections);
expect(consoleWarnSpy).not.toHaveBeenCalled();
// Should reset because kusama is not in defaultNetworks
expect(result.current.networkConnections).toEqual([{ networkId: 'polkadot' }]);
expect(consoleWarnSpy).toHaveBeenCalledWith(
'Some persisted network connections are not in the supported networks list. Resetting to default networks.'
);
});

it('should follow correct branching: populated localStorage with invalid networks -> reset', () => {
Expand Down Expand Up @@ -491,11 +524,12 @@ describe('ClientProvider localStorage validation', () => {

const { result } = renderHook(() => useClient(), { wrapper });

expect(result.current.networkConnections).toEqual(validConnections);

// The atom should retain the original valid connections
// Should reset because kusama is not in defaultNetworks
expect(result.current.networkConnections).toEqual([{ networkId: 'polkadot' }]);

// The atom should be updated with the reset value
const currentStoredValue = store.get(networkConnectionsAtom);
expect(currentStoredValue).toEqual(validConnections);
expect(currentStoredValue).toEqual([{ networkId: 'polkadot' }]);
});
});
});