Expose full verified contract source payloads

This commit is contained in:
defiQUG
2026-04-29 06:21:36 -07:00
parent f5eb874210
commit 1f5167aded

View File

@@ -18,6 +18,11 @@ export interface ContractMethodExecutionResult {
value: string
}
export interface ContractSourceFile {
path: string
content: string
}
export interface ContractProfile {
has_custom_methods_read: boolean
has_custom_methods_write: boolean
@@ -36,7 +41,10 @@ export interface ContractProfile {
license_type?: string
constructor_arguments?: string
abi?: string
abi_full?: string
source_code_full?: string
source_code_preview?: string
source_files: ContractSourceFile[]
source_status_text?: string
read_methods: ContractMethod[]
write_methods: ContractMethod[]
@@ -63,6 +71,7 @@ interface ContractCompatibilityAbiResponse {
interface ContractCompatibilitySourceRecord {
Address?: string
ContractName?: string
FileName?: string
CompilerVersion?: string
OptimizationUsed?: string | number
Runs?: string | number
@@ -111,6 +120,47 @@ function normalizeNumber(value: string | number | null | undefined): number | un
return undefined
}
function displaySourcePath(record: ContractCompatibilitySourceRecord | undefined): string {
const fileName = record?.FileName?.trim()
if (fileName) return fileName
const contractName = record?.ContractName?.trim()
if (contractName) return contractName.endsWith('.sol') ? contractName : `${contractName}.sol`
return 'Contract.sol'
}
function parseSourceFiles(sourceCode: string | undefined, record?: ContractCompatibilitySourceRecord): ContractSourceFile[] {
const trimmed = sourceCode?.trim()
if (!trimmed) return []
const candidates = [trimmed]
if (trimmed.startsWith('{{') && trimmed.endsWith('}}')) {
candidates.push(trimmed.slice(1, -1))
}
for (const candidate of candidates) {
try {
const parsed = JSON.parse(candidate) as {
sources?: Record<string, { content?: string } | string>
}
if (parsed && typeof parsed === 'object' && parsed.sources && typeof parsed.sources === 'object') {
return Object.entries(parsed.sources)
.map(([path, value]) => ({
path,
content: typeof value === 'string' ? value : value?.content || '',
}))
.filter((file) => file.content.trim().length > 0)
}
} catch {}
}
return [
{
path: displaySourcePath(record),
content: trimmed,
},
]
}
function parseABI(abiString?: string): ContractMethod[] {
if (!abiString) return []
try {
@@ -359,6 +409,7 @@ export const contractsApi = {
? sourceRecord.ABI
: undefined
const sourceCode = sourceRecord?.SourceCode
const sourceFiles = parseSourceFiles(sourceCode, sourceRecord)
const parsedMethods = parseABI(abiString)
const sourceVerified = Boolean(
abiString ||
@@ -391,7 +442,10 @@ export const contractsApi = {
license_type: sourceRecord?.LicenseType || undefined,
constructor_arguments: truncateHex(sourceRecord?.ConstructorArguments, 90),
abi: truncateText(abiString, 1200),
abi_full: abiString,
source_code_full: sourceCode,
source_code_preview: truncateText(sourceCode, 1200),
source_files: sourceFiles,
source_status_text: sourceStatusText || undefined,
read_methods: parsedMethods.filter(isReadMethod),
write_methods: parsedMethods.filter((method) => !isReadMethod(method)),