Skip to content

Commit d647529

Browse files
jtsmedleydependabot[bot]semantic-release-botachingbrain2color
authored
feat: change default TTL and add support for custom TTL (#1) (#308)
- Changes the Default TTL to the suggested default of 1 hour per the ipns-record [spec](https://specs.ipfs.tech/ipns/ipns-record/#ttl-uint64) - Allows for a custom TTL to be passed Fixes #310 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: semantic-release-bot <semantic-release-bot@martynus.net> Co-authored-by: Alex Potsides <alex@achingbrain.net> Co-authored-by: Daniel Norman <1992255+2color@users.noreply.github.com>
1 parent e933496 commit d647529

File tree

2 files changed

+50
-11
lines changed

2 files changed

+50
-11
lines changed

src/index.ts

+7-7
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type { CID } from 'multiformats/cid'
1616

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

2021
export const namespace = '/ipns/'
2122
export const namespaceLength = namespace.length
@@ -128,6 +129,7 @@ export interface IDKeys {
128129
}
129130

130131
export interface CreateOptions {
132+
ttlNs?: number | bigint
131133
v1Compatible?: boolean
132134
}
133135

@@ -140,7 +142,8 @@ export interface CreateV2Options {
140142
}
141143

142144
const defaultCreateOptions: CreateOptions = {
143-
v1Compatible: true
145+
v1Compatible: true,
146+
ttlNs: DEFAULT_TTL_NS
144147
}
145148

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

173-
return _create(peerId, value, seq, validityType, expirationDate.toString(), lifetimeNs, options)
175+
return _create(peerId, value, seq, validityType, expirationDate.toString(), ttlNs, options)
174176
}
175177

176178
/**
@@ -195,9 +197,7 @@ export async function createWithExpiration (peerId: PeerId, value: CID | PeerId
195197
export async function createWithExpiration (peerId: PeerId, value: CID | PeerId | string, seq: number | bigint, expiration: string, options: CreateOptions = defaultCreateOptions): Promise<IPNSRecord> {
196198
const expirationDate = NanoDate.fromString(expiration)
197199
const validityType = IpnsEntry.ValidityType.EOL
198-
199-
const ttlMs = expirationDate.toDate().getTime() - Date.now()
200-
const ttlNs = (BigInt(ttlMs) * BigInt(100000)) + BigInt(expirationDate.getNano())
200+
const ttlNs = BigInt(options.ttlNs != null ? options.ttlNs : DEFAULT_TTL_NS)
201201

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

test/index.spec.ts

+43-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ describe('ipns', function () {
3232

3333
it('should create an ipns record (V1+V2) correctly', async () => {
3434
const sequence = 0
35+
const ttl = BigInt(60 * 60 * 1e+9)
3536
const validity = 1000000
3637

3738
const record = await ipns.create(peerId, contentPath, sequence, validity)
@@ -40,7 +41,7 @@ describe('ipns', function () {
4041
expect(record.validityType).to.equal(IpnsEntry.ValidityType.EOL)
4142
expect(record.validity).to.exist()
4243
expect(record.sequence).to.equal(BigInt(0))
43-
expect(record.ttl).to.equal(BigInt(validity * 100000))
44+
expect(record.ttl).to.equal(ttl)
4445
expect(record.signatureV1).to.exist()
4546
expect(record.signatureV2).to.exist()
4647
expect(record.data).to.exist()
@@ -51,7 +52,7 @@ describe('ipns', function () {
5152
expect(pb.validityType).to.equal(IpnsEntry.ValidityType.EOL)
5253
expect(pb.validity).to.exist()
5354
expect(pb.sequence).to.equal(BigInt(sequence))
54-
expect(pb.ttl).to.equal(BigInt(validity * 100000))
55+
expect(pb.ttl).to.equal(ttl)
5556
expect(pb.signatureV1).to.exist()
5657
expect(pb.signatureV2).to.exist()
5758
expect(pb.data).to.exist()
@@ -67,6 +68,7 @@ describe('ipns', function () {
6768

6869
it('should create an ipns record (V2) correctly', async () => {
6970
const sequence = 0
71+
const ttl = BigInt(60 * 60 * 1e+9)
7072
const validity = 1000000
7173

7274
const record = await ipns.create(peerId, contentPath, sequence, validity, { v1Compatible: false })
@@ -75,7 +77,7 @@ describe('ipns', function () {
7577
expect(record.validityType).to.equal(IpnsEntry.ValidityType.EOL)
7678
expect(record.validity).to.exist()
7779
expect(record.sequence).to.equal(BigInt(0))
78-
expect(record.ttl).to.equal(BigInt(validity * 100000))
80+
expect(record.ttl).to.equal(ttl)
7981
expect(record.signatureV2).to.exist()
8082
expect(record).to.not.have.property('signatureV1')
8183
expect(record.data).to.exist()
@@ -97,7 +99,7 @@ describe('ipns', function () {
9799
expect(data.ValidityType).to.equal(IpnsEntry.ValidityType.EOL)
98100
expect(data.Validity).to.exist()
99101
expect(data.Sequence).to.equal(BigInt(sequence))
100-
expect(data.TTL).to.equal(BigInt(validity * 100000))
102+
expect(data.TTL).to.equal(ttl)
101103
})
102104

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

135+
it('should be able to create a record (V1+V2) with a fixed ttl', async () => {
136+
const sequence = 0
137+
const ttl = BigInt(0.6e+12)
138+
const validity = 1000000
139+
140+
const record = await ipns.create(peerId, contentPath, sequence, validity, {
141+
ttlNs: ttl
142+
})
143+
const marshalledRecord = ipns.marshal(record)
144+
145+
await ipnsValidator(peerIdToRoutingKey(peerId), marshalledRecord)
146+
147+
const pb = IpnsEntry.decode(marshalledRecord)
148+
const data = parseCborData(pb.data ?? new Uint8Array(0))
149+
expect(data.TTL).to.equal(ttl)
150+
})
151+
152+
it('should be able to create a record (V2) with a fixed ttl', async () => {
153+
const sequence = 0
154+
const ttl = BigInt(1.6e+12)
155+
const validity = 1000000
156+
157+
const record = await ipns.create(peerId, contentPath, sequence, validity, {
158+
ttlNs: ttl,
159+
v1Compatible: false
160+
})
161+
const marshalledRecord = ipns.marshal(record)
162+
163+
await ipnsValidator(peerIdToRoutingKey(peerId), marshalledRecord)
164+
165+
const pb = IpnsEntry.decode(marshalledRecord)
166+
expect(pb).to.not.have.property('ttl')
167+
168+
const data = parseCborData(pb.data ?? new Uint8Array(0))
169+
expect(data.TTL).to.equal(ttl)
170+
})
171+
133172
it('should create an ipns record (V1+V2) and validate it correctly', async () => {
134173
const sequence = 0
135174
const validity = 1000000

0 commit comments

Comments
 (0)