Skip to content
Merged
14 changes: 7 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type { CID } from 'multiformats/cid'

const log = logger('ipns')
const ID_MULTIHASH_CODE = identity.code
const DEFAULT_TTL_NS = 60 * 60 * 1e+9 // 1 Hour or 3600 Seconds

export const namespace = '/ipns/'
export const namespaceLength = namespace.length
Expand Down Expand Up @@ -128,6 +129,7 @@ export interface IDKeys {
}

export interface CreateOptions {
ttlNs?: number | bigint
v1Compatible?: boolean
}

Expand All @@ -140,7 +142,8 @@ export interface CreateV2Options {
}

const defaultCreateOptions: CreateOptions = {
v1Compatible: true
v1Compatible: true,
ttlNs: DEFAULT_TTL_NS
}

/**
Expand All @@ -167,10 +170,9 @@ export async function create (peerId: PeerId, value: CID | PeerId | string, seq:
// Validity in ISOString with nanoseconds precision and validity type EOL
const expirationDate = new NanoDate(Date.now() + Number(lifetime))
const validityType = IpnsEntry.ValidityType.EOL
const [ms, ns] = lifetime.toString().split('.')
const lifetimeNs = (BigInt(ms) * BigInt(100000)) + BigInt(ns ?? '0')
const ttlNs = typeof options.ttlNs !== 'undefined' ? BigInt(options.ttlNs) : DEFAULT_TTL_NS

return _create(peerId, value, seq, validityType, expirationDate.toString(), lifetimeNs, options)
return _create(peerId, value, seq, validityType, expirationDate.toString(), ttlNs, options)
}

/**
Expand All @@ -195,9 +197,7 @@ export async function createWithExpiration (peerId: PeerId, value: CID | PeerId
export async function createWithExpiration (peerId: PeerId, value: CID | PeerId | string, seq: number | bigint, expiration: string, options: CreateOptions = defaultCreateOptions): Promise<IPNSRecord> {
const expirationDate = NanoDate.fromString(expiration)
const validityType = IpnsEntry.ValidityType.EOL

const ttlMs = expirationDate.toDate().getTime() - Date.now()
const ttlNs = (BigInt(ttlMs) * BigInt(100000)) + BigInt(expirationDate.getNano())
const ttlNs = typeof options.ttlNs !== 'undefined' ? BigInt(options.ttlNs) : DEFAULT_TTL_NS

return _create(peerId, value, seq, validityType, expirationDate.toString(), ttlNs, options)
}
Expand Down
47 changes: 43 additions & 4 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('ipns', function () {

it('should create an ipns record (V1+V2) correctly', async () => {
const sequence = 0
const ttl = 3.6e+12
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity)
Expand All @@ -40,7 +41,7 @@ describe('ipns', function () {
expect(record.validityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(record.validity).to.exist()
expect(record.sequence).to.equal(BigInt(0))
expect(record.ttl).to.equal(BigInt(validity * 100000))
expect(record.ttl).to.equal(ttl)
expect(record.signatureV1).to.exist()
expect(record.signatureV2).to.exist()
expect(record.data).to.exist()
Expand All @@ -51,7 +52,7 @@ describe('ipns', function () {
expect(pb.validityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(pb.validity).to.exist()
expect(pb.sequence).to.equal(BigInt(sequence))
expect(pb.ttl).to.equal(BigInt(validity * 100000))
expect(pb.ttl).to.equal(ttl)
expect(pb.signatureV1).to.exist()
expect(pb.signatureV2).to.exist()
expect(pb.data).to.exist()
Expand All @@ -67,6 +68,7 @@ describe('ipns', function () {

it('should create an ipns record (V2) correctly', async () => {
const sequence = 0
const ttl = 3.6e+12
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity, { v1Compatible: false })
Expand All @@ -75,7 +77,7 @@ describe('ipns', function () {
expect(record.validityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(record.validity).to.exist()
expect(record.sequence).to.equal(BigInt(0))
expect(record.ttl).to.equal(BigInt(validity * 100000))
expect(record.ttl).to.equal(ttl)
expect(record.signatureV2).to.exist()
expect(record).to.not.have.property('signatureV1')
expect(record.data).to.exist()
Expand All @@ -97,7 +99,7 @@ describe('ipns', function () {
expect(data.ValidityType).to.equal(IpnsEntry.ValidityType.EOL)
expect(data.Validity).to.exist()
expect(data.Sequence).to.equal(BigInt(sequence))
expect(data.TTL).to.equal(BigInt(validity * 100000))
expect(data.TTL).to.equal(ttl)
})

it('should be able to create a record (V1+V2) with a fixed expiration', async () => {
Expand Down Expand Up @@ -130,6 +132,43 @@ describe('ipns', function () {
expect(data.Validity).to.equalBytes(uint8ArrayFromString(expiration))
})

it('should be able to create a record (V1+V2) with a fixed ttl', async () => {
const sequence = 0
const ttl = 0.6e+12
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity, {
ttlNs: ttl
})
const marshalledRecord = ipns.marshal(record)

await ipnsValidator(peerIdToRoutingKey(peerId), marshalledRecord)

const pb = IpnsEntry.decode(marshalledRecord)
const data = parseCborData(pb.data ?? new Uint8Array(0))
expect(data.TTL).to.equal(ttl)
})

it('should be able to create a record (V2) with a fixed ttl', async () => {
const sequence = 0
const ttl = BigInt(1.6e+12)
const validity = 1000000

const record = await ipns.create(peerId, contentPath, sequence, validity, {
ttlNs: ttl,
v1Compatible: false
})
const marshalledRecord = ipns.marshal(record)

await ipnsValidator(peerIdToRoutingKey(peerId), marshalledRecord)

const pb = IpnsEntry.decode(marshalledRecord)
expect(pb).to.not.have.property('ttl')

const data = parseCborData(pb.data ?? new Uint8Array(0))
expect(data.TTL).to.equal(ttl)
})

it('should create an ipns record (V1+V2) and validate it correctly', async () => {
const sequence = 0
const validity = 1000000
Expand Down