Skip to content

Commit

Permalink
Updated testnet chain id fallback logic
Browse files Browse the repository at this point in the history
  • Loading branch information
grod220 committed Sep 12, 2024
1 parent 000b796 commit e2082c5
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 32 deletions.
2 changes: 1 addition & 1 deletion npm/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

### Minor Changes

- c9bf54c: Update to latest cosmos registry
- c9bf54c: Updating testnet chain id fallback logic

## 11.1.0

Expand Down
16 changes: 13 additions & 3 deletions npm/src/bundled.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,20 @@ describe('BundledClient', () => {
expect(() => bundled.get('unknown')).toThrow('Registry not found for unknown');
});

it.skip('handles preview chain IDs by swapping them', () => {
const registry = bundled.get('penumbra-testnet-deimos-8-xf2dbce94');
it('returns a random suffix chain ID if available', () => {
const registry = bundled.get('penumbra-testnet-deimos-8-x6de97e39');
expect(registry).toBeInstanceOf(Registry);
expect(registry.chainId).toEqual('penumbra-testnet-deimos-8');
expect(registry.chainId).toEqual('penumbra-testnet-deimos-8-x6de97e39');
});

it('swaps a random suffix chain ID by swapping them if it is not present', () => {
const registry = bundled.get('penumbra-testnet-phobos-1-xf2dbce94');
expect(registry).toBeInstanceOf(Registry);
expect(registry.chainId).toEqual('penumbra-testnet-phobos-1');
});

it('fails if swapped random suffix chain ID is not present', () => {
expect(() => bundled.get('penumbra-testnet-jupiter-1-xf2dbce94')).toThrow();
});

it('returns staking asset global as expected', () => {
Expand Down
21 changes: 15 additions & 6 deletions npm/src/bundled.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,26 @@
import { Registry } from './registry';
import { allJsonRegistries } from './json';
import { swapIfPreviewChain } from './preview';
import * as GlobalsJson from '../../registry/globals.json';
import { RegistryGlobals } from './globals';
import { deriveTestnetChainIdFromPreview, isTestnetPreviewChainId } from './utils/testnet-parser';

export class BundledClient {
get(chainId: string): Registry {
const chainIdToIndex = swapIfPreviewChain(chainId);
const jsonRegistry = allJsonRegistries[chainIdToIndex];
if (!jsonRegistry) {
throw new Error(`Registry not found for ${chainIdToIndex}`);
const jsonRegistry = allJsonRegistries[chainId];
if (jsonRegistry) {
return new Registry(jsonRegistry);
}
return new Registry(jsonRegistry);

if (isTestnetPreviewChainId(chainId)) {
const fallbackChainId = deriveTestnetChainIdFromPreview(chainId);
console.warn(`Attempting to get fallback chain registry: ${fallbackChainId}`);
const fallbackRegistry = allJsonRegistries[fallbackChainId];
if (fallbackRegistry) {
return new Registry(fallbackRegistry);
}
}

throw new Error(`Registry not found for ${chainId}`);
}

globals(): RegistryGlobals {
Expand Down
2 changes: 1 addition & 1 deletion npm/src/json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ interface Image {
}

export const allJsonRegistries: Record<string, JsonRegistry> = {
'penumbra-testnet-deimos-8': Deimos8,
'penumbra-testnet-deimos-8-x6de97e39': Deimos8,
'penumbra-1': Penumbra1,
'penumbra-testnet-phobos-1': Phobos1,
};
9 changes: 4 additions & 5 deletions npm/src/registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,14 @@ describe('Registry', () => {
expect(getCubeMetadata).toThrow();
});

it.skip('gets all assets successfully', () => {
it('gets all assets successfully', () => {
const registry = new Registry(testRegistry);
const res = registry.getAllAssets();
expect(res.length).toEqual(20);
expect(res.length).toBeGreaterThan(0);
});

it.skip('versions correctly', async () => {
it('versions without throwing', async () => {
const registry = new Registry(testRegistry);
const version = await registry.version();
expect(version).toEqual('9eaf48c7cbf3248e6979830cfc982f2208eeec0fcc4c0e2802f0bd43c8bffad3');
await expect(registry.version()).resolves.not.toThrow();
});
});
70 changes: 57 additions & 13 deletions npm/src/remote.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fetchMock from 'fetch-mock';
import { RemoteClient } from './remote';
import { REGISTRY_BASE_URL } from './github';
import { ChainRegistryClient } from './client';
import * as Deimos8 from '../../registry/chains/penumbra-testnet-deimos-8-x6de97e39.json';
import * as Phobos1 from '../../registry/chains/penumbra-testnet-phobos-1.json';
import * as GlobalsJson from '../../registry/globals.json';

describe('RemoteClient', () => {
Expand All @@ -24,15 +24,15 @@ describe('RemoteClient', () => {
const endpoint = `${REGISTRY_BASE_URL}/chains/${chainId}.json`;
fetchMock.mock(endpoint, {
status: 200,
body: Deimos8,
body: Phobos1,
});

const registry = await rClient.get(chainId);

expect(fetchMock.called(endpoint)).toBe(true);
expect(registry.chainId).toEqual(Deimos8.chainId);
expect(registry.ibcConnections).toEqual(Deimos8.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Deimos8.assetById).length);
expect(registry.chainId).toEqual(Phobos1.chainId);
expect(registry.ibcConnections).toEqual(Phobos1.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Phobos1.assetById).length);
});

it('should throw if there is not a remote version', async () => {
Expand All @@ -59,25 +59,69 @@ describe('RemoteClient', () => {
expect(registry.rpcs).toEqual(GlobalsJson.rpcs);
});

describe('testnet preview', () => {
it('fetches falls back if available', async () => {
const testnetPreviewChainId = 'penumbra-testnet-phobos-1-x6de97e39';
const firstCall = `${REGISTRY_BASE_URL}/chains/${testnetPreviewChainId}.json`;
fetchMock.mock(firstCall, {
status: 404,
});
const fallbackChainId = 'penumbra-testnet-phobos-1';
const secondCall = `${REGISTRY_BASE_URL}/chains/${fallbackChainId}.json`;
fetchMock.mock(secondCall, {
status: 200,
body: Phobos1,
});

const registry = await rClient.get(testnetPreviewChainId);

expect(fetchMock.called(firstCall)).toBe(true);
expect(fetchMock.called(secondCall)).toBe(true);
expect(registry.chainId).toEqual(Phobos1.chainId);
expect(registry.ibcConnections).toEqual(Phobos1.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Phobos1.assetById).length);
});

it('throws if falls back not available', async () => {
const testnetPreviewChainId = 'penumbra-testnet-phobos-1-x6de97e39';
const firstCall = `${REGISTRY_BASE_URL}/chains/${testnetPreviewChainId}.json`;
fetchMock.mock(firstCall, {
status: 404,
});
const fallbackChainId = 'penumbra-testnet-phobos-1';
const secondCall = `${REGISTRY_BASE_URL}/chains/${fallbackChainId}.json`;
fetchMock.mock(secondCall, {
status: 404,
});

await expect(rClient.get(testnetPreviewChainId)).rejects.toThrow(
`Failed to fetch from: ${secondCall}`,
);

expect(fetchMock.called(firstCall)).toBe(true);
expect(fetchMock.called(secondCall)).toBe(true);
});
});

describe('getWithBundledBackup', () => {
it('fetches remote when available', async () => {
const chainId = 'test-chain-7';
const endpoint = `${REGISTRY_BASE_URL}/chains/${chainId}.json`;
fetchMock.mock(endpoint, {
status: 200,
body: Deimos8,
body: Phobos1,
});

const registry = await rClient.getWithBundledBackup(chainId);

expect(fetchMock.called(endpoint)).toBe(true);
expect(registry.chainId).toEqual(Deimos8.chainId);
expect(registry.ibcConnections).toEqual(Deimos8.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Deimos8.assetById).length);
expect(registry.chainId).toEqual(Phobos1.chainId);
expect(registry.ibcConnections).toEqual(Phobos1.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Phobos1.assetById).length);
});

it('fetches bundled when available', async () => {
const chainId = 'penumbra-testnet-deimos-8';
const chainId = 'penumbra-testnet-phobos-1';
const endpoint = `${REGISTRY_BASE_URL}/chains/${chainId}.json`;
fetchMock.mock(endpoint, {
status: 404,
Expand All @@ -86,9 +130,9 @@ describe('RemoteClient', () => {
const registry = await rClient.getWithBundledBackup(chainId);

expect(fetchMock.called(endpoint)).toBe(true);
expect(registry.chainId).toEqual(Deimos8.chainId);
expect(registry.ibcConnections).toEqual(Deimos8.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Deimos8.assetById).length);
expect(registry.chainId).toEqual(Phobos1.chainId);
expect(registry.ibcConnections).toEqual(Phobos1.ibcConnections);
expect(registry.getAllAssets().length).toEqual(Object.keys(Phobos1.assetById).length);
});
});
});
14 changes: 11 additions & 3 deletions npm/src/remote.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import { Registry } from './registry';
import { GithubFetcher } from './github';
import { swapIfPreviewChain } from './preview';
import { RegistryGlobals } from './globals';
import { BundledClient } from './bundled';
import { deriveTestnetChainIdFromPreview, isTestnetPreviewChainId } from './utils/testnet-parser';

export class RemoteClient {
private readonly github = new GithubFetcher();

constructor(private readonly bundled: BundledClient) {}

async get(chainId: string): Promise<Registry> {
const chainIdToQuery = swapIfPreviewChain(chainId);
return this.github.fetchRegistry(chainIdToQuery);
try {
return await this.github.fetchRegistry(chainId);
} catch (e) {
if (isTestnetPreviewChainId(chainId)) {
const fallbackChainId = deriveTestnetChainIdFromPreview(chainId);
console.warn(`Attempting to fetch fallback chain registry: ${fallbackChainId}`);
return await this.github.fetchRegistry(fallbackChainId);
}
throw e;
}
}

// If remote fails, fall back to bundled registry for chain
Expand Down
1 change: 1 addition & 0 deletions npm/src/utils/testnet-parser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ describe('testnet-preview helper', () => {
expect(deriveTestnetChainIdFromPreview('penumbra-testnet-tethys12-b4d8f9a0')).toEqual(
'penumbra-testnet-tethys12',
);
expect(deriveTestnetChainIdFromPreview('penumbra-testnet-deimos-8')).toEqual('');
});
});

0 comments on commit e2082c5

Please sign in to comment.