Skip to content

Commit

Permalink
Use remote registry API (#1472)
Browse files Browse the repository at this point in the history
* Make registry async

* fix tests
  • Loading branch information
grod220 authored Jul 13, 2024
1 parent 83151cb commit 3b7a289
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 111 deletions.
7 changes: 7 additions & 0 deletions .changeset/tiny-wolves-cover.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@repo/ui': major
'@penumbra-zone/storage': minor
'minifront': minor
---

Utilize v10 remote registry methods
2 changes: 1 addition & 1 deletion apps/minifront/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"@cosmos-kit/core": "^2.12.0",
"@cosmos-kit/react": "^2.15.0",
"@interchain-ui/react": "^1.23.16",
"@penumbra-labs/registry": "9.4.0",
"@penumbra-labs/registry": "10.0.0",
"@penumbra-zone/bech32m": "workspace:*",
"@penumbra-zone/client": "workspace:*",
"@penumbra-zone/crypto-web": "workspace:*",
Expand Down
30 changes: 21 additions & 9 deletions apps/minifront/src/components/tx-details/tx-viewer.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { JsonViewer } from '@repo/ui/components/ui/json-viewer';
import { TransactionViewComponent } from '@repo/ui/components/ui/tx';
import { MetadataFetchFn, TransactionViewComponent } from '@repo/ui/components/ui/tx';
import { TransactionInfo } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb.js';
import type { Jsonified } from '@penumbra-zone/types/jsonified';
import { useState } from 'react';
Expand All @@ -10,19 +10,28 @@ import { useQuery } from '@tanstack/react-query';
import fetchReceiverView from './hooks';
import { classifyTransaction } from '@penumbra-zone/perspective/transaction/classify';
import { uint8ArrayToHex } from '@penumbra-zone/types/hex';
import { viewClient } from '../../clients';
import { ChainRegistryClient } from '@penumbra-labs/registry';

export enum TxDetailsTab {
PUBLIC = 'public',
PRIVATE = 'private',
RECIEVER = 'reciever',
RECEIVER = 'receiver',
}

const OPTIONS = [
{ label: 'Your View', value: TxDetailsTab.PRIVATE },
{ label: 'Public View', value: TxDetailsTab.PUBLIC },
{ label: 'Reciever View', value: TxDetailsTab.RECIEVER },
{ label: 'Receiver View', value: TxDetailsTab.RECEIVER },
];

const getMetadata: MetadataFetchFn = async ({ assetId }) => {
const feeAssetId = assetId ? assetId : new ChainRegistryClient().bundled.globals().stakingAssetId;

const { denomMetadata } = await viewClient.assetMetadataById({ assetId: feeAssetId });
return denomMetadata;
};

export const TxViewer = ({ txInfo }: { txInfo?: TransactionInfo }) => {
const [option, setOption] = useState(TxDetailsTab.PRIVATE);

Expand All @@ -33,14 +42,14 @@ export const TxViewer = ({ txInfo }: { txInfo?: TransactionInfo }) => {
const showReceiverTransactionView = transactionClassification === 'send';
const filteredOptions = showReceiverTransactionView
? OPTIONS
: OPTIONS.filter(option => option.value !== TxDetailsTab.RECIEVER);
: OPTIONS.filter(option => option.value !== TxDetailsTab.RECEIVER);

// use React-Query to invoke custom hooks that call async translators.
const { data: receiverView } = useQuery(
['receiverView', txInfo, option],
() => fetchReceiverView(txInfo!),
{
enabled: option === TxDetailsTab.RECIEVER && !!txInfo,
enabled: option === TxDetailsTab.RECEIVER && !!txInfo,
},
);

Expand All @@ -62,18 +71,21 @@ export const TxViewer = ({ txInfo }: { txInfo?: TransactionInfo }) => {
</div>
{option === TxDetailsTab.PRIVATE && txInfo && (
<>
<TransactionViewComponent txv={txInfo.view!} />
<TransactionViewComponent txv={txInfo.view!} metadataFetcher={getMetadata} />
<div className='mt-8'>
<div className='text-xl font-bold'>Raw JSON</div>
<JsonViewer jsonObj={txInfo.toJson({ typeRegistry }) as Jsonified<TransactionInfo>} />
</div>
</>
)}
{option === TxDetailsTab.RECIEVER && receiverView && showReceiverTransactionView && (
<TransactionViewComponent txv={receiverView} />
{option === TxDetailsTab.RECEIVER && receiverView && showReceiverTransactionView && (
<TransactionViewComponent txv={receiverView} metadataFetcher={getMetadata} />
)}
{option === TxDetailsTab.PUBLIC && txInfo && (
<TransactionViewComponent txv={asPublicTransactionView(txInfo.view)} />
<TransactionViewComponent
txv={asPublicTransactionView(txInfo.view)}
metadataFetcher={getMetadata}
/>
)}
</div>
);
Expand Down
6 changes: 3 additions & 3 deletions apps/minifront/src/fetchers/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const useRegistry = () => {
if (!chainId) {
throw new Error('No chain id in response');
}
return chainRegistryClient.get(chainId);
return chainRegistryClient.remote.get(chainId);
},
staleTime: Infinity,
});
Expand All @@ -25,7 +25,7 @@ export const getStakingTokenMetadata = async () => {
throw new Error('Could not fetch chain id');
}

const stakingAssetId = chainRegistryClient.globals().stakingAssetId;
const { stakingAssetId } = chainRegistryClient.bundled.globals();
const stakingAssetsMetadata = await getAssetMetadataById(stakingAssetId);

if (!stakingAssetsMetadata) {
Expand All @@ -40,6 +40,6 @@ export const getChains = async (): Promise<Chain[]> => {
throw new Error('Could not fetch chain id');
}

const { ibcConnections } = chainRegistryClient.get(chainId);
const { ibcConnections } = await chainRegistryClient.remote.get(chainId);
return ibcConnections;
};
8 changes: 4 additions & 4 deletions apps/minifront/src/state/ibc-in/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ async function execute(
const transferToken = fromDisplayAmount(assetMetadata, coin.displayDenom, amount);
const params: MsgTransfer = {
sourcePort: 'transfer',
sourceChannel: getCounterpartyChannelId(selectedChain, penumbraChainId),
sourceChannel: await getCounterpartyChannelId(selectedChain, penumbraChainId),
sender,
receiver: penumbraAddress,
token: transferToken,
Expand All @@ -234,11 +234,11 @@ async function execute(
return await client.broadcastTx(cosmos.tx.v1beta1.TxRaw.encode(signedTx).finish());
}

const getCounterpartyChannelId = (
const getCounterpartyChannelId = async (
counterpartyChain: ChainInfo,
penumbraChainId: string,
): string => {
const registry = chainRegistryClient.get(penumbraChainId);
): Promise<string> => {
const registry = await chainRegistryClient.remote.get(penumbraChainId);

const counterpartyChannelId = registry.ibcConnections.find(
c => c.chainId === counterpartyChain.chainId,
Expand Down
7 changes: 5 additions & 2 deletions packages/storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,17 +31,20 @@
"dependencies": {
"@buf/penumbra-zone_penumbra.bufbuild_es": "1.10.0-20240703080008-312294d02bf9.1",
"@bufbuild/protobuf": "^1.10.0",
"@penumbra-labs/registry": "9.4.0",
"@penumbra-labs/registry": "10.0.0",
"@penumbra-zone/bech32m": "workspace:*",
"@penumbra-zone/getters": "workspace:*",
"@penumbra-zone/types": "workspace:*",
"@penumbra-zone/wasm": "workspace:*",
"idb": "^8.0.0"
},
"devDependencies": {
"fetch-mock": "^10.0.7"
},
"peerDependencies": {
"@buf/penumbra-zone_penumbra.bufbuild_es": "1.10.0-20240703080008-312294d02bf9.1",
"@bufbuild/protobuf": "^1.10.0",
"@penumbra-labs/registry": "9.4.0",
"@penumbra-labs/registry": "10.0.0",
"@penumbra-zone/bech32m": "workspace:*",
"@penumbra-zone/getters": "workspace:*",
"@penumbra-zone/types": "workspace:*",
Expand Down
28 changes: 12 additions & 16 deletions packages/storage/src/indexed-db/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,8 @@ export class IndexedDb implements IndexedDbInterface {
tables: IDB_TABLES,
} satisfies IdbConstants;

const instance = new this(
db,
new IbdUpdater(db),
constants,
chainId,
registryClient.globals().stakingAssetId,
);
const { stakingAssetId } = registryClient.bundled.globals();
const instance = new this(db, new IbdUpdater(db), constants, chainId, stakingAssetId);
await instance.saveRegistryAssets(registryClient, chainId); // Pre-load asset metadata from registry

const existing0thEpoch = await instance.getEpochByHeight(0n);
Expand Down Expand Up @@ -282,19 +277,20 @@ export class IndexedDb implements IndexedDbInterface {

// creates a local copy of the asset list from registry (https://github.com/prax-wallet/registry)
async saveRegistryAssets(registryClient: ChainRegistryClient, chainId: string) {
const { commit } = registryClient.version();
const lastPosition = await this.db.get('REGISTRY_VERSION', 'commit');
try {
const registry = await registryClient.remote.get(chainId);
const remoteVersion = await registry.version();
const localVersion = await this.db.get('REGISTRY_VERSION', 'commit');

// Registry version already saved
if (lastPosition === commit) {
return;
}
// Registry version already saved
if (localVersion === remoteVersion) {
return;
}

try {
const assets = registryClient.get(chainId).getAllAssets();
const assets = registry.getAllAssets();
const saveLocalMetadata = assets.map(m => this.saveAssetsMetadata(m));
await Promise.all(saveLocalMetadata);
await this.u.update({ table: 'REGISTRY_VERSION', key: 'commit', value: commit });
await this.u.update({ table: 'REGISTRY_VERSION', key: 'commit', value: remoteVersion });
} catch (error) {
console.error('Failed pre-population of assets from the registry', error);
}
Expand Down
68 changes: 52 additions & 16 deletions packages/storage/src/indexed-db/indexed-db.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
SwapRecord,
TransactionInfo,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb.js';
import { beforeEach, describe, expect, it } from 'vitest';
import { afterAll, beforeEach, describe, expect, it } from 'vitest';
import { IndexedDb } from './index.js';
import {
delegationMetadataA,
Expand Down Expand Up @@ -54,18 +54,53 @@ import {
DutchAuctionDescription,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb.js';
import { StateCommitment } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/crypto/tct/v1/tct_pb.js';
import { ChainRegistryClient } from '@penumbra-labs/registry';
import { ChainRegistryClient, Registry } from '@penumbra-labs/registry';
import fetchMock from 'fetch-mock';
import { uint8ArrayToBase64 } from '@penumbra-zone/types/base64';
import { JsonValue } from '@bufbuild/protobuf';

const registryClient = new ChainRegistryClient();
const chainId = 'penumbra-testnet-deimos-8';

const jsonifyRegistry = (r: Registry) => {
const assetById = r.getAllAssets().reduce<Record<string, JsonValue>>((acc, m) => {
const assetIdStr = uint8ArrayToBase64(m.penumbraAssetId!.inner);
acc[assetIdStr] = m.toJson();
return acc;
}, {});

const numeraires = r.numeraires.map(n => uint8ArrayToBase64(n.inner));

return {
chainId: r.chainId,
ibcConnections: r.ibcConnections,
numeraires,
assetById,
};
};

// uses different wallet ids so no collisions take place
const generateInitialProps = () => ({
chainId,
walletId: new WalletId({
inner: Uint8Array.from({ length: 32 }, () => Math.floor(Math.random() * 256)),
}),
registryClient,
});

const registryEndpoint = 'https://raw.githubusercontent.com/prax-wallet/registry/main/registry';

describe('IndexedDb', () => {
// uses different wallet ids so no collisions take place
const registryClient = new ChainRegistryClient();
const chainId = 'penumbra-testnet-deimos-6';
const generateInitialProps = () => ({
chainId,
walletId: new WalletId({
inner: Uint8Array.from({ length: 32 }, () => Math.floor(Math.random() * 256)),
}),
registryClient,
beforeEach(() => {
fetchMock.reset();
fetchMock.mock(`${registryEndpoint}/chains/${chainId}.json`, {
status: 200,
body: jsonifyRegistry(registryClient.bundled.get(chainId)),
});
});

afterAll(() => {
fetchMock.restore();
});

describe('initializing', () => {
Expand All @@ -78,7 +113,7 @@ describe('IndexedDb', () => {
const testnetDb = await IndexedDb.initialize(generateInitialProps());
const mainnetDb = await IndexedDb.initialize({
...generateInitialProps(),
chainId: 'penumbra-testnet-deimos-7',
chainId,
});

await testnetDb.saveAssetsMetadata(metadataA);
Expand Down Expand Up @@ -151,7 +186,7 @@ describe('IndexedDb', () => {
for await (const asset of db.iterateAssetsMetadata()) {
assets.push(asset);
}
const registryLength = registryClient.get(chainId).getAllAssets().length;
const registryLength = registryClient.bundled.get(chainId).getAllAssets().length;
expect(assets.length).toBe(registryLength + 1);

await db.saveTransaction(transactionId, 1000n, transaction);
Expand Down Expand Up @@ -301,7 +336,8 @@ describe('IndexedDb', () => {
savedAssets.push(asset);
}

const registryLength = registryClient.get(chainId).getAllAssets().length;
const registry = await registryClient.remote.get(chainId);
const registryLength = registry.getAllAssets().length;
expect(savedAssets.length === registryLength).toBeTruthy();
});

Expand All @@ -325,8 +361,8 @@ describe('IndexedDb', () => {
for await (const asset of db.iterateAssetsMetadata()) {
savedAssets.push(asset);
}
const registryLength = registryClient.get(chainId).getAllAssets().length;
expect(savedAssets.length === registryLength + 3).toBeTruthy();
const registryLength = registryClient.bundled.get(chainId).getAllAssets().length;
expect(savedAssets.length).toBe(registryLength + 3);
});
});

Expand Down
Loading

0 comments on commit 3b7a289

Please sign in to comment.