refactor: rename SolaceScanScout to Solace and update related configurations

- Updated branding from "SolaceScanScout" to "Solace" across various files including deployment scripts, API responses, and documentation.
- Changed default base URL for Playwright tests and updated security headers to reflect the new branding.
- Enhanced README and API documentation to include new authentication endpoints and product access details.

This refactor aligns the project branding and improves clarity in the API documentation.
This commit is contained in:
defiQUG
2026-04-10 12:52:17 -07:00
parent bdae5a9f6e
commit f46bd213ba
160 changed files with 13274 additions and 1061 deletions

View File

@@ -1,7 +1,12 @@
import { resolveExplorerApiBase } from '@/libs/frontend-api-client/api-base'
import type { Block } from './blocks'
import type { Transaction } from './transactions'
import type { TransactionSummary } from './addresses'
import type {
AddressInfo,
AddressTokenBalance,
AddressTokenTransfer,
TransactionSummary,
} from './addresses'
export function getExplorerApiBase() {
return resolveExplorerApiBase()
@@ -16,18 +21,94 @@ export async function fetchBlockscoutJson<T>(path: string): Promise<T> {
}
type HashLike = string | { hash?: string | null } | null | undefined
type StringLike = string | number | null | undefined
export function extractHash(value: HashLike): string {
if (!value) return ''
return typeof value === 'string' ? value : value.hash || ''
}
export function extractLabel(value: unknown): string {
if (!value || typeof value !== 'object') return ''
const candidate = value as {
name?: string | null
label?: string | null
display_name?: string | null
symbol?: string | null
}
return candidate.name || candidate.label || candidate.display_name || candidate.symbol || ''
}
function toNumber(value: unknown): number {
if (typeof value === 'number') return value
if (typeof value === 'string' && value.trim() !== '') return Number(value)
return 0
}
function toNullableNumber(value: unknown): number | undefined {
if (value == null) return undefined
const numeric = toNumber(value)
return Number.isFinite(numeric) ? numeric : undefined
}
export interface BlockscoutAddressRef {
hash?: string | null
name?: string | null
label?: string | null
is_contract?: boolean
is_verified?: boolean
}
export interface BlockscoutTokenRef {
address?: string | null
name?: string | null
symbol?: string | null
decimals?: StringLike
type?: string | null
total_supply?: string | null
holders?: StringLike
}
export interface BlockscoutTokenTransfer {
block_hash?: string
block_number?: StringLike
from?: BlockscoutAddressRef | null
to?: BlockscoutAddressRef | null
log_index?: StringLike
method?: string | null
timestamp?: string | null
token?: BlockscoutTokenRef | null
total?: {
decimals?: StringLike
value?: string | null
} | null
transaction_hash?: string
type?: string | null
}
export interface BlockscoutDecodedInput {
method_call?: string | null
method_id?: string | null
parameters?: Array<{
name?: string | null
type?: string | null
value?: unknown
}>
}
export interface BlockscoutInternalTransaction {
from?: BlockscoutAddressRef | null
to?: BlockscoutAddressRef | null
created_contract?: BlockscoutAddressRef | null
success?: boolean | null
error?: string | null
result?: string | null
timestamp?: string | null
transaction_hash?: string | null
type?: string | null
value?: string | null
}
interface BlockscoutBlock {
hash: string
height: number | string
@@ -54,6 +135,13 @@ interface BlockscoutTransaction {
raw_input?: string | null
timestamp: string
created_contract?: HashLike
fee?: { value?: string | null } | string | null
method?: string | null
revert_reason?: string | null
transaction_tag?: string | null
decoded_input?: BlockscoutDecodedInput | null
token_transfers?: BlockscoutTokenTransfer[] | null
actions?: unknown[] | null
}
function normalizeStatus(raw: BlockscoutTransaction): number {
@@ -95,6 +183,39 @@ export function normalizeTransaction(raw: BlockscoutTransaction, chainId: number
input_data: raw.raw_input || undefined,
contract_address: extractHash(raw.created_contract) || undefined,
created_at: raw.timestamp,
fee: typeof raw.fee === 'string' ? raw.fee : raw.fee?.value || undefined,
method: raw.method || undefined,
revert_reason: raw.revert_reason || undefined,
transaction_tag: raw.transaction_tag || undefined,
decoded_input: raw.decoded_input
? {
method_call: raw.decoded_input.method_call || undefined,
method_id: raw.decoded_input.method_id || undefined,
parameters: Array.isArray(raw.decoded_input.parameters)
? raw.decoded_input.parameters.map((parameter) => ({
name: parameter.name || undefined,
type: parameter.type || undefined,
value: parameter.value,
}))
: [],
}
: undefined,
token_transfers: Array.isArray(raw.token_transfers)
? raw.token_transfers.map((transfer) => ({
block_number: toNullableNumber(transfer.block_number),
from_address: extractHash(transfer.from),
from_label: extractLabel(transfer.from),
to_address: extractHash(transfer.to),
to_label: extractLabel(transfer.to),
token_address: transfer.token?.address || '',
token_name: transfer.token?.name || undefined,
token_symbol: transfer.token?.symbol || undefined,
token_decimals: toNullableNumber(transfer.token?.decimals) ?? toNullableNumber(transfer.total?.decimals) ?? 18,
amount: transfer.total?.value || '0',
type: transfer.type || undefined,
timestamp: transfer.timestamp || undefined,
}))
: [],
}
}
@@ -108,3 +229,104 @@ export function normalizeTransactionSummary(raw: BlockscoutTransaction): Transac
status: normalizeStatus(raw),
}
}
interface BlockscoutAddress {
hash: string
coin_balance?: string | null
is_contract?: boolean
is_verified?: boolean
name?: string | null
public_tags?: Array<{ label?: string; display_name?: string; name?: string } | string>
private_tags?: Array<{ label?: string; display_name?: string; name?: string } | string>
watchlist_names?: string[]
has_token_transfers?: boolean
has_tokens?: boolean
creation_transaction_hash?: string | null
token?: BlockscoutTokenRef | null
}
export function normalizeAddressInfo(
raw: BlockscoutAddress,
counters: {
transactions_count?: number | string
token_balances_count?: number | string
token_transfers_count?: number | string
internal_transactions_count?: number | string
logs_count?: number | string
},
chainId: number,
): AddressInfo {
const tags = [
...(raw.public_tags || []),
...(raw.private_tags || []),
...(raw.watchlist_names || []),
]
.map((tag) => {
if (typeof tag === 'string') return tag
return tag.display_name || tag.label || tag.name || ''
})
.filter(Boolean)
return {
address: raw.hash,
chain_id: chainId,
transaction_count: Number(counters.transactions_count || 0),
token_count: Number(counters.token_balances_count || 0),
token_transfer_count: Number(counters.token_transfers_count || 0),
internal_transaction_count: Number(counters.internal_transactions_count || 0),
logs_count: Number(counters.logs_count || 0),
is_contract: !!raw.is_contract,
is_verified: !!raw.is_verified,
has_token_transfers: !!raw.has_token_transfers,
has_tokens: !!raw.has_tokens,
balance: raw.coin_balance || undefined,
creation_transaction_hash: raw.creation_transaction_hash || undefined,
label: raw.name || raw.token?.symbol || undefined,
tags,
token_contract: raw.token?.address
? {
address: raw.token.address,
symbol: raw.token.symbol || undefined,
name: raw.token.name || undefined,
decimals: toNullableNumber(raw.token.decimals),
type: raw.token.type || undefined,
total_supply: raw.token.total_supply || undefined,
holders: toNullableNumber(raw.token.holders),
}
: undefined,
}
}
export function normalizeAddressTokenBalance(raw: {
token?: BlockscoutTokenRef | null
value?: string | null
}): AddressTokenBalance {
return {
token_address: raw.token?.address || '',
token_name: raw.token?.name || undefined,
token_symbol: raw.token?.symbol || undefined,
token_type: raw.token?.type || undefined,
token_decimals: toNullableNumber(raw.token?.decimals) ?? 18,
value: raw.value || '0',
holder_count: raw.token?.holders != null ? toNumber(raw.token.holders) : undefined,
total_supply: raw.token?.total_supply || undefined,
}
}
export function normalizeAddressTokenTransfer(raw: BlockscoutTokenTransfer): AddressTokenTransfer {
return {
transaction_hash: raw.transaction_hash || '',
block_number: toNullableNumber(raw.block_number) ?? 0,
timestamp: raw.timestamp || undefined,
from_address: extractHash(raw.from),
from_label: extractLabel(raw.from),
to_address: extractHash(raw.to),
to_label: extractLabel(raw.to),
token_address: raw.token?.address || '',
token_name: raw.token?.name || undefined,
token_symbol: raw.token?.symbol || undefined,
token_decimals: toNullableNumber(raw.token?.decimals) ?? toNullableNumber(raw.total?.decimals) ?? 18,
value: raw.total?.value || '0',
type: raw.type || undefined,
}
}