Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

adr 006 changes and implementation #1648

Merged
merged 1 commit into from
Aug 9, 2024
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
5 changes: 0 additions & 5 deletions .changeset/hungry-jobs-teach.md

This file was deleted.

5 changes: 5 additions & 0 deletions .changeset/pretty-pants-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@penumbra-zone/client': major
---

adr006 implementation
13 changes: 13 additions & 0 deletions apps/minifront/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# minifront

## 6.17.0

### Minor Changes

- df2ac99: Use newer client package for minifront. Fix disconnect in transport-chrome

### Patch Changes

- Updated dependencies [e6f019e]
- Updated dependencies [ca3c325]
- @repo/[email protected]
- @penumbra-zone/[email protected]

## 6.16.0

### Minor Changes
Expand Down
2 changes: 1 addition & 1 deletion apps/minifront/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "minifront",
"version": "6.16.0",
"version": "6.17.0",
"private": true,
"license": "(MIT OR Apache-2.0)",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions apps/minifront/src/abort-loader.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isPraxConnected, throwIfPraxNotConnected, throwIfPraxNotInstalled } from './prax';
import { penumbra, throwIfPraxNotConnected, throwIfPraxNotInstalled } from './prax';

/**
* Retry test, resolving `true`, or resolving `false` if timeout reached.
Expand Down Expand Up @@ -30,7 +30,7 @@ const retry = async (fn: () => boolean, ms = 500, rate = Math.max(ms / 10, 50))
*/
export const abortLoader = async (): Promise<null> => {
await throwIfPraxNotInstalled();
await retry(() => isPraxConnected());
await retry(() => Boolean(penumbra.connected));
throwIfPraxNotConnected();

// Loaders are required to return a value, even if it's null. By returning
Expand Down
24 changes: 0 additions & 24 deletions apps/minifront/src/clients.ts

This file was deleted.

8 changes: 5 additions & 3 deletions apps/minifront/src/components/extension-not-connected.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { HeadTag } from './metadata/head-tag';

import { useState } from 'react';
import { PenumbraRequestFailure } from '@penumbra-zone/client';
import { requestPraxAccess } from '../prax';
import { penumbra } from '../prax';
import { useNavigate } from 'react-router-dom';

const handleErr = (e: unknown) => {
if (e instanceof Error && e.cause) {
Expand Down Expand Up @@ -34,11 +35,12 @@ const handleErr = (e: unknown) => {

const useExtConnector = () => {
const [result, setResult] = useState<boolean>();
const navigate = useNavigate();

const request = async () => {
try {
await requestPraxAccess();
location.reload();
await penumbra.connect();
navigate('/');
} catch (e) {
handleErr(e);
} finally {
Expand Down
4 changes: 2 additions & 2 deletions apps/minifront/src/components/extension-not-installed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ export const ExtensionNotInstalled = () => {
<HeadTag />
<SplashPage title='Welcome to Penumbra'>
<div className='flex items-center justify-between gap-[1em] text-lg'>
To get started, install the Penumbra Chrome extension.
To get started, install a Penumbra extension.
<Button asChild variant='gradient'>
<a
href={`https://chrome.google.com/webstore/detail/penumbra-wallet/${CHROME_EXTENSION_ID}`}
target='_blank'
rel='noreferrer'
>
Install
Install Prax
</a>
</Button>
</div>
Expand Down
66 changes: 15 additions & 51 deletions apps/minifront/src/components/header/menu/provider.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,21 @@
import { cn } from '@repo/ui/lib/utils';
import * as NavigationMenu from '@radix-ui/react-navigation-menu';
import { getChainId } from '../../../fetchers/chain-id';
import { useCallback, useEffect, useState } from 'react';
import { useEffect, useState } from 'react';
import { itemStyle, triggerStyle, dropdownStyle, linkStyle, viewportStyle } from './nav-style';
import { Link1Icon, LinkBreak1Icon } from '@radix-ui/react-icons';
import { getPraxManifest, getPraxOrigin } from '../../../prax';
import { PenumbraSymbol } from '@penumbra-zone/client';
import { LinkBreak1Icon } from '@radix-ui/react-icons';
import { penumbra } from '../../../prax';

export const ProviderMenu = () => {
const [chainId, setChainId] = useState<string | undefined>();
const [providerManifest, setProviderManifest] = useState<ProviderManifest>();
const [providerOrigin] = useState(getPraxOrigin());

const [manifestIconUnavailable, setManifestIconUnavailable] = useState<boolean>();

const disconnect = useCallback(() => {
void window[PenumbraSymbol]?.[providerOrigin]
?.disconnect()
.then(() => window.location.reload());
}, [providerOrigin]);
const disconnect = () => void penumbra.disconnect().then(() => window.location.reload());

useEffect(() => {
void getPraxManifest().then(m => setProviderManifest(m as ProviderManifest));
void getChainId().then(setChainId);
}, []);

if (!providerManifest) {
if (!penumbra.manifest) {
return null;
}

Expand All @@ -39,17 +29,12 @@ export const ProviderMenu = () => {
'h-[42px] flex flex-row gap-2 place-items-center justify-evenly whitespace-nowrap',
)}
>
{manifestIconUnavailable ? (
<Link1Icon className='text-teal-500' />
) : (
<img
id='provider-icon'
className={cn('w-[1.5em]', 'max-w-none', 'h-[1.5em]')}
src={String(new URL(providerManifest.icons['128'], providerOrigin))}
alt={`${providerManifest.name} Icon`}
onError={() => setManifestIconUnavailable(true)}
/>
)}
<img
id='provider-icon'
className={cn('w-[1.5em]', 'max-w-none', 'h-[1.5em]')}
src={URL.createObjectURL(penumbra.manifest.icons['128'])}
alt={`${penumbra.manifest['name']} Icon`}
/>
{chainId}
</NavigationMenu.Trigger>
<NavigationMenu.Content className={cn(...dropdownStyle, 'min-w-60 w-full')}>
Expand All @@ -58,20 +43,14 @@ export const ProviderMenu = () => {
<NavigationMenu.Link className={cn(...linkStyle, 'p-0', 'leading-normal')}>
<div className='ml-4 text-muted-foreground'>
<span className='font-headline text-muted'>
{providerManifest.name} {providerManifest.version}
{penumbra.manifest['name']} {penumbra.manifest['version']}
</span>
<p>{providerManifest.description}</p>
<p>{penumbra.manifest['description']}</p>
</div>
</NavigationMenu.Link>
</NavigationMenu.Item>
<NavigationMenu.Item
hidden={
// hide if injection does not contain disconnect
!window[PenumbraSymbol]?.[providerOrigin]?.disconnect
}
className={cn(...itemStyle)}
>
<NavigationMenu.Link className={cn(...linkStyle)} onSelect={disconnect}>
<NavigationMenu.Item className={cn(...itemStyle)}>
<NavigationMenu.Link className={cn(...linkStyle)} onSelect={() => disconnect()}>
<span>
<LinkBreak1Icon className={cn('size-[1em]', 'inline-block')} />
&nbsp;Disconnect
Expand All @@ -85,18 +64,3 @@ export const ProviderMenu = () => {
</NavigationMenu.Root>
);
};

interface ProviderManifest {
options_ui?: {
page: string;
};
options_page?: string;
homepage_url: string;
name: string;
id: string;
version: string;
description: string;
icons: {
['128']: string;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import {
getAmount,
getAssetIdFromBalancesResponseOptional,
} from '@penumbra-zone/getters/balances-response';
import { viewClient } from '../../clients.ts';
import { ViewService } from '@penumbra-zone/protobuf';
import { GasPrices } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/fee/v1/fee_pb';
import { getAssetId } from '@penumbra-zone/getters/metadata';
import { penumbra } from '../../prax';

const hasTokenBalance = ({
source,
Expand Down Expand Up @@ -64,7 +65,7 @@ const useGasPrices = () => {
const [prices, setPrices] = useState<GasPrices[]>([]);

const fetchGasPrices = useCallback(async () => {
const res = await viewClient.gasPrices({});
const res = await penumbra.service(ViewService).gasPrices({});
setPrices(res.altGasPrices);
}, []);

Expand Down
8 changes: 6 additions & 2 deletions apps/minifront/src/components/tx-details/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { asReceiverTransactionView } from '@penumbra-zone/perspective/translators/transaction-view';
import { viewClient } from '../../clients';
import { ViewService } from '@penumbra-zone/protobuf';
import { TransactionView } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/transaction/v1/transaction_pb.js';
import { TransactionInfo } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb.js';
import { penumbra } from '../../prax';

const fetchReceiverView = async (txInfo: TransactionInfo): Promise<TransactionView> => {
return await asReceiverTransactionView(txInfo.view, {
isControlledAddress: async address =>
viewClient.indexByAddress({ address }).then(({ addressIndex }) => Boolean(addressIndex)),
penumbra
.service(ViewService)
.indexByAddress({ address })
.then(({ addressIndex }) => Boolean(addressIndex)),
});
};

Expand Down
8 changes: 5 additions & 3 deletions apps/minifront/src/components/tx-details/tx-viewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import type { Jsonified } from '@penumbra-zone/types/jsonified';
import { useState } from 'react';
import { SegmentedPicker } from '@repo/ui/components/ui/segmented-picker';
import { asPublicTransactionView } from '@penumbra-zone/perspective/translators/transaction-view';
import { typeRegistry } from '@penumbra-zone/protobuf';
import { typeRegistry, ViewService } from '@penumbra-zone/protobuf';
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';
import { penumbra } from '../../prax';

export enum TxDetailsTab {
PUBLIC = 'public',
Expand All @@ -28,7 +28,9 @@ const OPTIONS = [
const getMetadata: MetadataFetchFn = async ({ assetId }) => {
const feeAssetId = assetId ? assetId : new ChainRegistryClient().bundled.globals().stakingAssetId;

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

Expand Down
11 changes: 8 additions & 3 deletions apps/minifront/src/fetchers/address.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Address } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/keys/v1/keys_pb.js';
import { viewClient } from '../clients';
import { ViewService } from '@penumbra-zone/protobuf';
import { bech32mAddress } from '@penumbra-zone/bech32m/penumbra';
import { penumbra } from '../prax';

type Index = number;
type Bech32Address = string;
Expand All @@ -25,15 +26,19 @@ export const getAddresses = async (accounts: (number | undefined)[]): Promise<In
};

export const getAddressByIndex = async (account = 0): Promise<Address> => {
const { address } = await viewClient.addressByIndex({ addressIndex: { account } });
const { address } = await penumbra
.service(ViewService)
.addressByIndex({ addressIndex: { account } });
if (!address) {
throw new Error('Address not in getAddressByIndex response');
}
return address;
};

export const getEphemeralAddress = async (account = 0): Promise<Address> => {
const { address } = await viewClient.ephemeralAddress({ addressIndex: { account } });
const { address } = await penumbra
.service(ViewService)
.ephemeralAddress({ addressIndex: { account } });
if (!address) {
throw new Error('Address not in getEphemeralAddress response');
}
Expand Down
7 changes: 4 additions & 3 deletions apps/minifront/src/fetchers/assets.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { AssetMetadataByIdRequest } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/view/v1/view_pb.js';
import { viewClient } from '../clients';
import { ViewService } from '@penumbra-zone/protobuf';
import {
AssetId,
Metadata,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb.js';
import { getDenomMetadata } from '@penumbra-zone/getters/assets-response';
import { penumbra } from '../prax';

export const getAllAssets = async (): Promise<Metadata[]> => {
const responses = await Array.fromAsync(viewClient.assets({}));
const responses = await Array.fromAsync(penumbra.service(ViewService).assets({}));
return responses.map(getDenomMetadata);
};

export const getAssetMetadataById = async (assetId: AssetId): Promise<Metadata | undefined> => {
const req = new AssetMetadataByIdRequest({ assetId });
const { denomMetadata } = await viewClient.assetMetadataById(req);
const { denomMetadata } = await penumbra.service(ViewService).assetMetadataById(req);
return denomMetadata;
};
11 changes: 7 additions & 4 deletions apps/minifront/src/fetchers/auction-infos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import {
AuctionId,
DutchAuction,
} from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/component/auction/v1/auction_pb.js';
import { viewClient } from '../clients';
import { ViewService } from '@penumbra-zone/protobuf';
import { Metadata } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/asset/v1/asset_pb.js';
import { getInputAssetId, getOutputAssetId } from '@penumbra-zone/getters/dutch-auction';
import { AddressIndex } from '@buf/penumbra-zone_penumbra.bufbuild_es/penumbra/core/keys/v1/keys_pb.js';
import { penumbra } from '../prax';

export interface AuctionInfo {
id: AuctionId;
Expand All @@ -21,7 +22,9 @@ export const getAuctionInfos = async function* ({
}: {
queryLatestState?: boolean;
} = {}): AsyncGenerator<AuctionInfo> {
for await (const response of viewClient.auctions({ queryLatestState, includeInactive: true })) {
for await (const response of penumbra
.service(ViewService)
.auctions({ queryLatestState, includeInactive: true })) {
if (!response.auction || !response.id || !response.noteRecord?.addressIndex) {
continue;
}
Expand All @@ -32,10 +35,10 @@ export const getAuctionInfos = async function* ({
const outputAssetId = getOutputAssetId.optional()(auction);

const inputMetadataPromise = inputAssetId
? viewClient.assetMetadataById({ assetId: inputAssetId })
? penumbra.service(ViewService).assetMetadataById({ assetId: inputAssetId })
: undefined;
const outputMetadataPromise = outputAssetId
? viewClient.assetMetadataById({ assetId: outputAssetId })
? penumbra.service(ViewService).assetMetadataById({ assetId: outputAssetId })
: undefined;

const [inputMetadata, outputMetadata] = await Promise.all([
Expand Down
Loading
Loading