Skip to content

Commit

Permalink
Get smart-contract bytecode from websocket (#1851)
Browse files Browse the repository at this point in the history
* Get smart-contract bytecode from websocket

Fixes #1769

* fix test

* i am stupid 😓

* Update values.yaml.gotmpl

---------

Co-authored-by: Yan Vaskov <72267126+yvaskov@users.noreply.github.com>
  • Loading branch information
tom2drum and yvaskov authored May 6, 2024
1 parent 8b42923 commit 7884356
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 7 deletions.
8 changes: 4 additions & 4 deletions deploy/values/review/values.yaml.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ frontend:
NEXT_PUBLIC_APP_ENV: development
NEXT_PUBLIC_APP_INSTANCE: review
NEXT_PUBLIC_NETWORK_VERIFICATION_TYPE: validation
NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-goerli.json
NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/goerli.svg
NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/goerli.svg
NEXT_PUBLIC_API_HOST: eth-sepolia.blockscout.com
NEXT_PUBLIC_FEATURED_NETWORKS: https://raw.githubusercontent.com/blockscout/frontend-configs/dev/configs/featured-networks/eth-sepolia.json
NEXT_PUBLIC_NETWORK_LOGO: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-logos/sepolia.svg
NEXT_PUBLIC_NETWORK_ICON: https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/network-icons/sepolia.png
NEXT_PUBLIC_API_HOST: eth-sepolia.k8s-dev.blockscout.com
NEXT_PUBLIC_STATS_API_HOST: https://stats-goerli.k8s-dev.blockscout.com/
NEXT_PUBLIC_VISUALIZE_API_HOST: http://visualizer-svc.visualizer-testing.svc.cluster.local/
NEXT_PUBLIC_CONTRACT_INFO_API_HOST: https://contracts-info-test.k8s-dev.blockscout.com
Expand Down
2 changes: 2 additions & 0 deletions lib/socket/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ SocketMessage.AddressTxs |
SocketMessage.AddressTxsPending |
SocketMessage.AddressTokenTransfer |
SocketMessage.AddressChangedBytecode |
SocketMessage.AddressFetchedBytecode |
SocketMessage.SmartContractWasVerified |
SocketMessage.TokenTransfers |
SocketMessage.TokenTotalSupply |
Expand Down Expand Up @@ -64,6 +65,7 @@ export namespace SocketMessage {
export type AddressTxsPending = SocketMessageParamsGeneric<'pending_transaction', { transactions: Array<Transaction> }>;
export type AddressTokenTransfer = SocketMessageParamsGeneric<'token_transfer', { token_transfers: Array<TokenTransfer> }>;
export type AddressChangedBytecode = SocketMessageParamsGeneric<'changed_bytecode', Record<string, never>>;
export type AddressFetchedBytecode = SocketMessageParamsGeneric<'fetched_bytecode', { fetched_bytecode: string }>;
export type SmartContractWasVerified = SocketMessageParamsGeneric<'smart_contract_was_verified', Record<string, never>>;
export type TokenTransfers = SocketMessageParamsGeneric<'token_transfer', {token_transfer: number }>;
export type TokenTotalSupply = SocketMessageParamsGeneric<'total_supply', {total_supply: number }>;
Expand Down
11 changes: 11 additions & 0 deletions mocks/address/tabCounters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { AddressTabsCounters } from 'types/api/address';

export const base: AddressTabsCounters = {
internal_txs_count: 13,
logs_count: 51,
token_balances_count: 3,
token_transfers_count: 3,
transactions_count: 51,
validations_count: 42,
withdrawals_count: 11,
};
1 change: 1 addition & 0 deletions playwright/fixtures/socketServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export function sendMessage(socket: WebSocket, channel: Channel, msg: 'new_block
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'verification_result', payload: SmartContractVerificationResponse): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'total_supply', payload: { total_supply: number}): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'changed_bytecode', payload: Record<string, never>): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'fetched_bytecode', payload: { fetched_bytecode: string }): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'smart_contract_was_verified', payload: Record<string, never>): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: 'token_transfer', payload: { token_transfers: Array<TokenTransfer> }): void;
export function sendMessage(socket: WebSocket, channel: Channel, msg: string, payload: unknown): void {
Expand Down
33 changes: 33 additions & 0 deletions ui/pages/Address.pw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';

import * as addressMock from 'mocks/address/address';
import * as addressCountersMock from 'mocks/address/counters';
import * as addressTabCountersMock from 'mocks/address/tabCounters';
import * as socketServer from 'playwright/fixtures/socketServer';
import { test, expect } from 'playwright/lib';

import Address from './Address';

const hooksConfig = {
router: {
query: { hash: addressMock.hash },
},
};

test.describe('fetched bytecode', () => {
test('should refetch address query', async({ render, mockApiResponse, createSocket, page }) => {
const addressApiUrl = await mockApiResponse('address', addressMock.validator, { pathParams: { hash: addressMock.hash } });
await mockApiResponse('address_counters', addressCountersMock.forValidator, { pathParams: { hash: addressMock.hash } });
await mockApiResponse('address_tabs_counters', addressTabCountersMock.base, { pathParams: { hash: addressMock.hash } });
await mockApiResponse('address_txs', { items: [], next_page_params: null }, { pathParams: { hash: addressMock.hash } });
await render(<Address/>, { hooksConfig }, { withSocket: true });

const socket = await createSocket();
const channel = await socketServer.joinChannel(socket, `addresses:${ addressMock.hash.toLowerCase() }`);
socketServer.sendMessage(socket, channel, 'fetched_bytecode', { fetched_bytecode: '0x0123' });

const request = await page.waitForRequest(addressApiUrl);

expect(request).toBeTruthy();
});
});
22 changes: 19 additions & 3 deletions ui/pages/Address.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { useAppContext } from 'lib/contexts/app';
import useContractTabs from 'lib/hooks/useContractTabs';
import useIsSafeAddress from 'lib/hooks/useIsSafeAddress';
import getQueryParamString from 'lib/router/getQueryParamString';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
import { ADDRESS_TABS_COUNTERS } from 'stubs/address';
import { USER_OPS_ACCOUNT } from 'stubs/userOps';
import AddressAccountHistory from 'ui/address/AddressAccountHistory';
Expand Down Expand Up @@ -69,14 +71,28 @@ const AddressPageContent = () => {
},
});

const isLoading = addressQuery.isPlaceholderData || (config.features.userOps.isEnabled && userOpsAccountQuery.isPlaceholderData);
const isTabsLoading = isLoading || addressTabsCountersQuery.isPlaceholderData;

const handleFetchedBytecodeMessage = React.useCallback(() => {
addressQuery.refetch();
}, [ addressQuery ]);

const channel = useSocketChannel({
topic: `addresses:${ hash?.toLowerCase() }`,
isDisabled: isTabsLoading || addressQuery.isDegradedData || Boolean(addressQuery.data?.is_contract),
});
useSocketMessage({
channel,
event: 'fetched_bytecode',
handler: handleFetchedBytecodeMessage,
});

const isSafeAddress = useIsSafeAddress(!addressQuery.isPlaceholderData && addressQuery.data?.is_contract ? hash : undefined);
const safeIconColor = useColorModeValue('black', 'white');

const contractTabs = useContractTabs(addressQuery.data, addressQuery.isPlaceholderData);

const isLoading = addressQuery.isPlaceholderData || (config.features.userOps.isEnabled && userOpsAccountQuery.isPlaceholderData);
const isTabsLoading = isLoading || addressTabsCountersQuery.isPlaceholderData;

const tabs: Array<RoutedTab> = React.useMemo(() => {
return [
{
Expand Down

0 comments on commit 7884356

Please sign in to comment.