Skip to content
Draft
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,6 @@ yalc.lock
/public/workbox-*.js
/public/workbox-*.js.map
/public/fallback*
/public/*.js.LICENSE.txt
/public/*.js.LICENSE.txt

public/tx-decoder-tmp
222 changes: 222 additions & 0 deletions grab_split_db.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
#!/bin/bash

# Config
EXPORT_URL="https://api.openchain.xyz/signature-database/v1/export"
TEMP_EXPORT_FILE="/tmp/db_export_downloaded"
OUTPUT_DIR="public/tx-decoder-tmp"
LINES_PER_CHUNK=65000 # Adjust as needed to get desired file sizes
TYPESCRIPT_FILE="hash-lookup.ts"

# Ensure output directory exists
mkdir -p "$OUTPUT_DIR"
mkdir -p "/tmp/db_export" # Create temp directory for download

# Step 0: Download the export file
echo "Downloading export file from $EXPORT_URL..."
wget -O "$TEMP_EXPORT_FILE" "$EXPORT_URL"

if [ $? -ne 0 ]; then
echo "Failed to download the export file. Exiting."
exit 1
fi

echo "Download complete."

# Count total lines in the file
echo "Counting total lines in file..."
TOTAL_LINES=$(wc -l < "$TEMP_EXPORT_FILE")
echo "Total lines: $TOTAL_LINES"

# Calculate number of chunks needed
CHUNK_COUNT=$(( (TOTAL_LINES + LINES_PER_CHUNK - 1) / LINES_PER_CHUNK ))
echo "Will create $CHUNK_COUNT chunks with approximately $LINES_PER_CHUNK lines each"

echo "Step 1: Splitting the file into chunks by line boundaries..."
# Use split to create chunks with a specified number of lines
split -l "$LINES_PER_CHUNK" "$TEMP_EXPORT_FILE" "$OUTPUT_DIR/chunk_"

# Rename chunks to have .raw extension for clarity
for chunk in "$OUTPUT_DIR"/chunk_*; do
if [[ ! "$chunk" == *.raw ]]; then
mv "$chunk" "$chunk.raw"
fi
done

echo "Step 2: Getting the first and last lines from each chunk for hash ranges..."
# Start writing the TypeScript file with the header
cat > "$TYPESCRIPT_FILE" << 'EOF'
/**
* Hash range lookup for transaction signatures
*
* This file is automatically generated from export file chunks
* Each chunk contains function signatures with their corresponding hashes
* Format: 0xHASH,functionSignature(param1,param2)
*/

/**
* Interface representing a hash range within a specific file
*/
interface HashRange {
/** Filename containing the hash range */
file: string;
/** First hash in the file */
firstHash: string;
/** First function signature in the file */
firstSig: string;
/** Last hash in the file */
lastHash: string;
/** Last function signature in the file */
lastSig: string;
}

/**
* Array of hash ranges, with first and last hash/signature from each file
*/
const FILE_RANGES: HashRange[] = [
EOF

# Process each raw chunk to extract its first and last lines
count=0
for chunk in "$OUTPUT_DIR"/chunk_*.raw; do
# Extract chunk number from filename to create sequential numbered output files
chunk_basename=$(basename "$chunk")
chunk_suffix=${chunk_basename#chunk_}
chunk_number=${chunk_suffix%.raw}

# Convert to padded decimal number
# First, convert from base 36 to decimal (macOS split uses a-z after 0-9)
decimal_value=0
for (( i=0; i<${#chunk_number}; i++ )); do
char=${chunk_number:$i:1}
if [[ $char =~ [0-9] ]]; then
value=$char
else
# Convert a-z to 10-35
value=$(( $(printf "%d" "'$char") - $(printf "%d" "'a") + 10 ))
fi
decimal_value=$(( decimal_value * 36 + value ))
done

# Format with padding
padded_number=$(printf "%02d" $((decimal_value + 1)))
export_chunk_filename="export_chunk_$padded_number"

echo "Processing chunk: $chunk_basename to $export_chunk_filename"

# Extract first and last lines
first_line=$(head -n 1 "$chunk")
last_line=$(tail -n 1 "$chunk")

# Validate first line format (must start with 0x)
if [[ ! "$first_line" =~ ^0x[0-9a-fA-F]+ ]]; then
echo "Warning: First line in $chunk_basename doesn't match expected format: $first_line"
continue
fi

# Validate last line format (must start with 0x)
if [[ ! "$last_line" =~ ^0x[0-9a-fA-F]+ ]]; then
echo "Warning: Last line in $chunk_basename doesn't match expected format: $last_line"
continue
fi

# Parse hash and signature from first line
first_hash=$(echo "$first_line" | cut -d',' -f1)
first_sig=$(echo "$first_line" | cut -d',' -f2-)

# Parse hash and signature from last line
last_hash=$(echo "$last_line" | cut -d',' -f1)
last_sig=$(echo "$last_line" | cut -d',' -f2-)

# Add comma if not the first entry
if [ $count -gt 0 ]; then
echo "," >> "$TYPESCRIPT_FILE"
fi

# Properly escape quotes for JavaScript
first_sig=$(echo "$first_sig" | sed 's/"/\\"/g')
last_sig=$(echo "$last_sig" | sed 's/"/\\"/g')

# Write this file's range to the TypeScript file
cat >> "$TYPESCRIPT_FILE" << EOF
{
file: "$export_chunk_filename",
firstHash: "$first_hash",
firstSig: "$first_sig",
lastHash: "$last_hash",
lastSig: "$last_sig"
}
EOF

echo " Extracted range from $chunk_basename: $first_hash to $last_hash"
count=$((count + 1))
done

# Close the array and add the lookup function
cat >> "$TYPESCRIPT_FILE" << 'EOF'
];

/**
* Finds the file that contains the given hash
*
* @param hash - The function hash to look up (format: '0x...')
* @returns The filename containing the hash, or null if not found
*/
export function findFileForHash(hash: string): string | null {
// Convert hash to numeric value for comparison
const hashValue = parseInt(hash, 16);

for (const range of FILE_RANGES) {
// Convert first and last hashes to numeric values
const firstValue = parseInt(range.firstHash, 16);
const lastValue = parseInt(range.lastHash, 16);

// Check if the hash falls within this file's range
if (hashValue >= firstValue && hashValue <= lastValue) {
return range.file;
}
}

// If no range matched, return null
return null;
}
EOF

echo "Step 3: Compressing each chunk with zstd..."
# Now compress each raw chunk
for chunk in "$OUTPUT_DIR"/chunk_*.raw; do
# Extract chunk number from filename to create sequential numbered output files
chunk_basename=$(basename "$chunk")
chunk_suffix=${chunk_basename#chunk_}
chunk_number=${chunk_suffix%.raw}

# Convert to padded decimal number
# First, convert from base 36 to decimal (macOS split uses a-z after 0-9)
decimal_value=0
for (( i=0; i<${#chunk_number}; i++ )); do
char=${chunk_number:$i:1}
if [[ $char =~ [0-9] ]]; then
value=$char
else
# Convert a-z to 10-35
value=$(( $(printf "%d" "'$char") - $(printf "%d" "'a") + 10 ))
fi
decimal_value=$(( decimal_value * 36 + value ))
done

# Format with padding
padded_number=$(printf "%02d" $((decimal_value + 1)))
export_chunk_filename="export_chunk_$padded_number"
output_file="$OUTPUT_DIR/$export_chunk_filename"

echo " Compressing $chunk_basename to $export_chunk_filename..."
zstd -19 "$chunk" -o "$output_file"
done

echo "Step 4: Cleaning up temporary raw chunks and downloaded file..."
# Clean up the raw chunks and downloaded file
rm "$OUTPUT_DIR"/chunk_*.raw
rm "$TEMP_EXPORT_FILE"

echo "Done! Created $count compressed chunks and TypeScript lookup file."
echo "TypeScript file: $TYPESCRIPT_FILE"
echo "Compressed files are in: $OUTPUT_DIR"
17 changes: 10 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,13 @@
},
"resolutions": {
"@solana/web3.js": "^1.87.7",
"@walletconnect/core": "^2.10.6",
"@walletconnect/ethereum-provider": "^2.10.6",
"@walletconnect/utils": "^2.10.6",
"@web3-onboard/common": "^2.4.1",
"@web3-onboard/trezor/**/protobufjs": "^7.2.4",
"crypto-es": "^2.1.0",
"crypto-js": "^4.2.0"
},
"dependencies": {
"@bokuweb/zstd-wasm": "^0.0.27",
"@ducanh2912/next-pwa": "^9.7.1",
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.0",
Expand All @@ -47,7 +46,10 @@
"@mui/icons-material": "^5.14.20",
"@mui/material": "^5.14.20",
"@mui/x-date-pickers": "^5.0.20",
"@oneidentity/zstd-js": "^1.0.3",
"@openchainxyz/abi-guesser": "^1.0.2",
"@reduxjs/toolkit": "^1.9.5",
"@reown/walletkit": "^1.2.1",
"@safe-global/protocol-kit": "1.3.0",
"@safe-global/safe-apps-sdk": "^9.0.0-next.1",
"@safe-global/safe-deployments": "1.37.30",
Expand All @@ -58,10 +60,11 @@
"@tkey-mpc/common-types": "^8.2.2",
"@truffle/hdwallet-provider": "^2.1.4",
"@uniswap/token-lists": "1.0.0-beta.33",
"@walletconnect/utils": "^2.10.6",
"@walletconnect/core": "^2.19.0",
"@walletconnect/utils": "^2.19.0",
"@walletconnect/web3wallet": "^1.9.5",
"@web3-onboard/coinbase": "^2.2.6",
"@web3-onboard/core": "^2.21.2",
"@web3-onboard/core": "^2.24.0",
"@web3-onboard/injected-wallets": "^2.10.7",
"@web3-onboard/keystone": "^2.3.7",
"@web3-onboard/ledger": "2.3.2",
Expand All @@ -71,7 +74,7 @@
"bn.js": "^5.2.1",
"classnames": "^2.3.1",
"date-fns": "^2.30.0",
"ethers": "5.7.2",
"ethers": "5.8.0",
"ethers-multicall-provider": "3.1.2",
"exponential-backoff": "^3.1.0",
"framer-motion": "^10.13.1",
Expand Down Expand Up @@ -127,7 +130,7 @@
"prettier": "^2.7.0",
"ts-prune": "^0.10.3",
"typechain": "^8.0.0",
"typescript": "4.9.4",
"typescript": "5.8.2",
"typescript-plugin-css-modules": "^4.2.2",
"webpack": "^5.88.2"
},
Expand Down
5 changes: 5 additions & 0 deletions src/components/common/Header/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import classnames from 'classnames'
import css from './styles.module.css'
import ConnectWallet from '@/components/common/ConnectWallet'
import NetworkSelector from '@/components/common/NetworkSelector'
import WalletConnectButton from '@/components/common/WalletConnectButton'
import { AppRoutes } from '@/config/routes'
import Link from 'next/link'

Expand Down Expand Up @@ -46,6 +47,10 @@ const Header = ({ onMenuToggle }: HeaderProps): ReactElement => {
<ConnectWallet />
</div>

<div className={classnames(css.element, css.walletConnectButton)}>
<WalletConnectButton />
</div>

<div className={classnames(css.element, css.networkSelector)}>
<NetworkSelector />
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/components/common/Header/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@
border-right: none;
}

.connectWallet {
.connectWallet,
.walletConnectButton {
flex-shrink: 0;
}

Expand Down
62 changes: 62 additions & 0 deletions src/components/common/WalletConnectButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useState, useRef } from 'react'
import { IconButton, Tooltip, SvgIcon, Badge } from '@mui/material'
import WalletConnectIcon from '@/public/images/common/walletconnect.svg'
import WalletConnectPairingModal from '@/components/common/WalletConnectPairingModal'
import { useWalletConnectContext } from '@/components/common/WalletConnectProvider'
import css from './styles.module.css'

const WalletConnectButton = () => {
const [isModalOpen, setIsModalOpen] = useState(false)
const { sessions, pendingProposal, pendingRequest } = useWalletConnectContext()
const buttonRef = useRef<HTMLButtonElement>(null)

const handleOpenModal = () => {
setIsModalOpen(true)
}

const handleCloseModal = () => {
setIsModalOpen(false)
}

const hasPendingProposals = !!pendingProposal
const hasPendingRequests = !!pendingRequest
const hasActiveSessions = sessions.length > 0
const showBadge = hasPendingProposals || hasPendingRequests || hasActiveSessions

return (
<>
<Tooltip
title={
hasPendingRequests
? 'WalletConnect: Pending transaction request'
: hasPendingProposals
? 'WalletConnect: Pending connection proposal'
: hasActiveSessions
? `WalletConnect: ${sessions.length} active connection${sessions.length > 1 ? 's' : ''}`
: 'WalletConnect Pairing'
}
arrow
>
<Badge
color={hasPendingRequests || hasPendingProposals ? 'error' : 'primary'}
variant="dot"
invisible={!showBadge}
>
<IconButton
ref={buttonRef}
onClick={handleOpenModal}
size="small"
color="primary"
className={css.walletConnectButton}
aria-label="WalletConnect Pairing"
>
<SvgIcon component={WalletConnectIcon} inheritViewBox fontSize="small" />
</IconButton>
</Badge>
</Tooltip>
<WalletConnectPairingModal open={isModalOpen} onClose={handleCloseModal} anchorEl={buttonRef.current} />
</>
)
}

export default WalletConnectButton
4 changes: 4 additions & 0 deletions src/components/common/WalletConnectButton/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.walletConnectButton {
padding: var(--space-1);
margin: 0 var(--space-1);
}
Loading
Loading