Fixes for Solana value encoding and searches (#140)

Tested with a new test Hasura instance
pull/142/head
J M Rossy 2 weeks ago committed by GitHub
parent b7e8e1dcd3
commit d7da83d3a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      src/features/messages/pi-queries/usePiChainMessageQuery.ts
  2. 4
      src/features/messages/queries/build.ts
  3. 38
      src/features/messages/queries/encoding.ts
  4. 6
      src/features/messages/queries/parse.ts
  5. 17
      src/features/messages/queries/useMessageQuery.ts
  6. 2
      src/utils/string.ts

@ -46,7 +46,7 @@ export function usePiChainMessageSearchQuery({
],
queryFn: async () => {
const hasInput = !!sanitizedInput;
const isValidInput = isValidSearchQuery(sanitizedInput, true);
const isValidInput = isValidSearchQuery(sanitizedInput);
if (pause || !multiProvider || !hasInput || !isValidInput) return [];
logger.debug('Starting PI Chain message search for:', sanitizedInput);
// TODO handle time-based filters here

@ -71,14 +71,12 @@ export function buildMessageSearchQuery(
limit: number,
useStub = false,
) {
const hasInput = !!searchInput;
const originChains = originFilter ? originFilter.split(',') : undefined;
const destinationChains = destFilter ? destFilter.split(',') : undefined;
const startTime = startTimeFilter ? adjustToUtcTime(startTimeFilter) : undefined;
const endTime = endTimeFilter ? adjustToUtcTime(endTimeFilter) : undefined;
const variables = {
search: hasInput ? searchValueToPostgresBytea(searchInput) : undefined,
search: searchValueToPostgresBytea(searchInput),
originChains,
destinationChains,
startTime,

@ -1,10 +1,16 @@
import { ChainMetadata } from '@hyperlane-xyz/sdk';
import {
addressToByteHexString,
base58ToBuffer,
bufferToBase58,
bytesToProtocolAddress,
ensure0x,
isAddress,
isAddressEvm,
isValidTransactionHashCosmos,
isValidTransactionHashEvm,
isValidTransactionHashSealevel,
ProtocolType,
strip0x,
} from '@hyperlane-xyz/utils';
@ -34,7 +40,33 @@ export function postgresByteaToAddress(
return bytesToProtocolAddress(addressBytes, chainMetadata.protocol, chainMetadata.bech32Prefix);
}
export function searchValueToPostgresBytea(input: string): string {
if (isAddress(input)) return addressToPostgresBytea(input);
else return stringToPostgresBytea(input);
export function postgresByteaToTxHash(
byteString: string,
chainMetadata: ChainMetadata | null | undefined,
): string {
const hexString = postgresByteaToString(byteString);
// Return hex string for protocols other than Sealevel
if (chainMetadata?.protocol !== ProtocolType.Sealevel) return hexString;
const bytes = Buffer.from(strip0x(hexString), 'hex');
return bufferToBase58(bytes);
}
export function searchValueToPostgresBytea(input: string): string | undefined {
if (!input) return undefined;
try {
if (isAddress(input)) {
return addressToPostgresBytea(input);
}
if (isValidTransactionHashEvm(input) || isValidTransactionHashCosmos(input)) {
return stringToPostgresBytea(input);
}
if (isValidTransactionHashSealevel(input)) {
const bytes = base58ToBuffer(input);
return stringToPostgresBytea(bytes.toString('hex'));
}
return undefined;
} catch (error) {
// Search input couldn't be decoded and recoded properly
return undefined;
}
}

@ -6,7 +6,7 @@ import { tryUtf8DecodeBytes } from '../../../utils/string';
import { DomainsEntry } from '../../chains/queries/fragments';
import { isPiChain } from '../../chains/utils';
import { postgresByteaToAddress, postgresByteaToString } from './encoding';
import { postgresByteaToAddress, postgresByteaToString, postgresByteaToTxHash } from './encoding';
import {
MessageEntry,
MessageStubEntry,
@ -79,13 +79,13 @@ function parseMessageStub(
destinationDomainId: m.destination_domain_id,
origin: {
timestamp: parseTimestampString(m.send_occurred_at),
hash: postgresByteaToString(m.origin_tx_hash),
hash: postgresByteaToTxHash(m.origin_tx_hash, originMetadata),
from: postgresByteaToAddress(m.origin_tx_sender, originMetadata),
},
destination: m.is_delivered
? {
timestamp: parseTimestampString(m.delivery_occurred_at!),
hash: postgresByteaToString(m.destination_tx_hash!),
hash: postgresByteaToTxHash(m.destination_tx_hash!, destinationMetadata),
from: postgresByteaToAddress(m.destination_tx_sender!, destinationMetadata),
}
: undefined,

@ -1,18 +1,13 @@
import { useCallback, useMemo } from 'react';
import { useQuery } from 'urql';
import {
isAddress,
isValidTransactionHashCosmos,
isValidTransactionHashEvm,
} from '@hyperlane-xyz/utils';
import { useMultiProvider } from '../../../store';
import { MessageStatus } from '../../../types';
import { useInterval } from '../../../utils/useInterval';
import { useScrapedDomains } from '../../chains/queries/useScrapedChains';
import { MessageIdentifierType, buildMessageQuery, buildMessageSearchQuery } from './build';
import { searchValueToPostgresBytea } from './encoding';
import { MessagesQueryResult, MessagesStubQueryResult } from './fragments';
import { parseMessageQueryResult, parseMessageStubResult } from './parse';
@ -21,13 +16,9 @@ const MSG_AUTO_REFRESH_DELAY = 10_000; // 10s
const LATEST_QUERY_LIMIT = 100;
const SEARCH_QUERY_LIMIT = 50;
export function isValidSearchQuery(input: string, allowAddress?: boolean) {
export function isValidSearchQuery(input: string) {
if (!input) return false;
return !!(
isValidTransactionHashEvm(input) ||
isValidTransactionHashCosmos(input) ||
(allowAddress && isAddress(input))
);
return !!searchValueToPostgresBytea(input);
}
export function useMessageSearchQuery(
@ -40,7 +31,7 @@ export function useMessageSearchQuery(
const { scrapedDomains: scrapedChains } = useScrapedDomains();
const hasInput = !!sanitizedInput;
const isValidInput = hasInput ? isValidSearchQuery(sanitizedInput, true) : true;
const isValidInput = !hasInput || isValidSearchQuery(sanitizedInput);
// Assemble GraphQL query
const { query, variables } = buildMessageSearchQuery(

@ -5,7 +5,7 @@ import { strip0x } from '@hyperlane-xyz/utils';
const alphanumericRgex = /[^a-zA-Z0-9]/gi;
export function sanitizeString(str: string) {
if (!str || typeof str !== 'string') return '';
return str.replaceAll(alphanumericRgex, '').toLowerCase();
return str.replaceAll(alphanumericRgex, '');
}
export function tryUtf8DecodeBytes(value: string, fatal = true) {

Loading…
Cancel
Save