ipns
Version:
IPNS record definitions
56 lines (46 loc) • 1.8 kB
text/typescript
import NanoDate from 'timestamp-nano'
import { IpnsEntry } from './pb/ipns.ts'
import { unmarshalIPNSRecord } from './utils.ts'
/**
* Selects the latest valid IPNS record from an array of marshalled IPNS records.
*
* Records are sorted by:
* 1. Sequence number (higher takes precedence)
* 2. Validity time for EOL records with same sequence number (longer lived record takes precedence)
*
* @param key - The routing key for the IPNS record
* @param data - Array of marshalled IPNS records to select from
* @returns The index of the most valid record from the input array
*/
export function ipnsSelector (key: Uint8Array, data: Uint8Array[]): number {
const entries = data.map((buf, index) => ({
record: unmarshalIPNSRecord(buf),
index
}))
entries.sort((a, b) => {
// Before we'd sort based on the signature version. Unmarshal now fails if
// a record does not have SignatureV2, so that is no longer needed. V1-only
// records haven't been issues in a long time.
const aSeq = a.record.sequence
const bSeq = b.record.sequence
// choose later sequence number
if (aSeq > bSeq) {
return -1
} else if (aSeq < bSeq) {
return 1
}
if (a.record.validityType === IpnsEntry.ValidityType.EOL && b.record.validityType === IpnsEntry.ValidityType.EOL) {
// choose longer lived record if sequence numbers the same
const recordAValidityDate = NanoDate.fromString(a.record.validity).toDate()
const recordBValidityDate = NanoDate.fromString(b.record.validity).toDate()
if (recordAValidityDate.getTime() > recordBValidityDate.getTime()) {
return -1
}
if (recordAValidityDate.getTime() < recordBValidityDate.getTime()) {
return 1
}
}
return 0
})
return entries[0].index
}