filecoin-pin
Version:
Bridge IPFS content to Filecoin Onchain Cloud using familiar tools
76 lines (60 loc) • 2.38 kB
text/typescript
export const ERC8004_TYPES = ['registration', 'validationrequest', 'validationresponse', 'feedback'] as const
export type ERC8004Type = (typeof ERC8004_TYPES)[number]
export interface MetadataConfigInput {
pieceMetadata?: Record<string, string> | undefined
dataSetMetadata?: Record<string, string> | undefined
erc8004Type?: ERC8004Type
erc8004Agent?: string
}
export interface MetadataConfigResult {
pieceMetadata?: Record<string, string> | undefined
dataSetMetadata?: Record<string, string> | undefined
}
export function normalizeMetadataConfig(input: MetadataConfigInput): MetadataConfigResult {
const pieceMetadata = sanitizeRecord(input.pieceMetadata)
const dataSetMetadata = sanitizeRecord(input.dataSetMetadata)
if ((input.erc8004Type && !input.erc8004Agent) || (!input.erc8004Type && input.erc8004Agent)) {
throw new Error('Both erc8004Type and erc8004Agent must be provided together')
}
if (input.erc8004Type && input.erc8004Agent) {
const key = `8004${input.erc8004Type}`
mergeRecord(pieceMetadata, key, input.erc8004Agent, 'ERC-8004 metadata', 'metadata')
mergeRecord(dataSetMetadata, 'erc8004Files', '', 'ERC-8004 metadata', 'data set metadata')
}
return {
pieceMetadata: Object.keys(pieceMetadata).length > 0 ? pieceMetadata : undefined,
dataSetMetadata: Object.keys(dataSetMetadata).length > 0 ? dataSetMetadata : undefined,
}
}
function sanitizeRecord(record: Record<string, string> | undefined): Record<string, string> {
if (record == null) {
return {}
}
const sanitized: Record<string, string> = {}
for (const [rawKey, rawValue] of Object.entries(record)) {
const key = rawKey.trim()
if (key === '') {
throw new Error('Metadata keys must be non-empty strings')
}
if (typeof rawValue !== 'string') {
throw new Error(`Metadata value for "${key}" must be a string`)
}
sanitized[key] = rawValue
}
return sanitized
}
function mergeRecord(
record: Record<string, string>,
key: string,
value: string,
sourceLabel: string,
conflictLabel: string
): void {
const existingValue = record[key]
if (existingValue != null && existingValue !== value) {
throw new Error(
`Conflicting metadata for "${key}": ${sourceLabel} tried to set "${value}" but ${conflictLabel} already set "${existingValue}".`
)
}
record[key] = value
}