Skip to content

Commit aa20dba

Browse files
committed
feat: add Time module for slot operations
1 parent 0a2e863 commit aa20dba

File tree

8 files changed

+302
-103
lines changed

8 files changed

+302
-103
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Slot number in the Cardano blockchain.
3+
* Represents a discrete time unit in the blockchain.
4+
* Each slot is typically 1 second (1000ms) on mainnet.
5+
*
6+
* @category Time
7+
* @since 2.0.0
8+
*/
9+
export type Slot = bigint
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import type * as Network from "../Network.js"
2+
3+
/**
4+
* Slot configuration for a Cardano network.
5+
* Defines the relationship between slots and Unix time.
6+
*
7+
* @category Time
8+
* @since 2.0.0
9+
*/
10+
export interface SlotConfig {
11+
/**
12+
* Unix timestamp (in milliseconds) of the network start (Shelley era).
13+
*/
14+
readonly zeroTime: bigint
15+
16+
/**
17+
* First slot number of the Shelley era.
18+
*/
19+
readonly zeroSlot: bigint
20+
21+
/**
22+
* Duration of each slot in milliseconds (typically 1000ms = 1 second).
23+
*/
24+
readonly slotLength: number
25+
}
26+
27+
/**
28+
* Network-specific slot configurations for all Cardano networks.
29+
*
30+
* - **Mainnet**: Production network starting at Shelley era
31+
* - **Preview**: Preview testnet for protocol updates
32+
* - **Preprod**: Pre-production testnet
33+
* - **Custom**: Customizable for emulator/devnet (initialized with zeros)
34+
*
35+
* @category Time
36+
* @since 2.0.0
37+
*/
38+
export const SLOT_CONFIG_NETWORK: Record<Network.Network, SlotConfig> = {
39+
Mainnet: {
40+
zeroTime: 1596059091000n, // Shelley era start
41+
zeroSlot: 4492800n,
42+
slotLength: 1000,
43+
},
44+
Preview: {
45+
zeroTime: 1666656000000n,
46+
zeroSlot: 0n,
47+
slotLength: 1000,
48+
},
49+
Preprod: {
50+
zeroTime: 1654041600000n + 1728000000n, // 1655769600000n
51+
zeroSlot: 86400n,
52+
slotLength: 1000,
53+
},
54+
Custom: {
55+
zeroTime: 0n,
56+
zeroSlot: 0n,
57+
slotLength: 0,
58+
},
59+
}
60+
61+
/**
62+
* Get slot configuration for a network.
63+
*
64+
* @param network - The network to get configuration for
65+
* @returns Slot configuration for the network
66+
*
67+
* @category Time
68+
* @since 2.0.0
69+
*/
70+
export const getSlotConfig = (network: Network.Network): SlotConfig => SLOT_CONFIG_NETWORK[network]
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/**
2+
* Unix time in milliseconds since epoch (January 1, 1970 00:00:00 UTC).
3+
* Used for JavaScript Date interop and general time operations.
4+
*
5+
* @category Time
6+
* @since 2.0.0
7+
*/
8+
export type UnixTime = bigint
9+
10+
/**
11+
* Convert UnixTime (milliseconds) to seconds.
12+
*
13+
* @param unixTime - Unix time in milliseconds
14+
* @returns Unix time in seconds
15+
*
16+
* @category Time
17+
* @since 2.0.0
18+
*/
19+
export const toSeconds = (unixTime: UnixTime): bigint => unixTime / 1000n
20+
21+
/**
22+
* Convert seconds to UnixTime (milliseconds).
23+
*
24+
* @param seconds - Time in seconds
25+
* @returns Unix time in milliseconds
26+
*
27+
* @category Time
28+
* @since 2.0.0
29+
*/
30+
export const fromSeconds = (seconds: bigint): UnixTime => seconds * 1000n
31+
32+
/**
33+
* Get current UnixTime.
34+
*
35+
* @returns Current Unix time in milliseconds
36+
*
37+
* @category Time
38+
* @since 2.0.0
39+
*/
40+
export const now = (): UnixTime => BigInt(Date.now())
41+
42+
/**
43+
* Convert JavaScript Date to UnixTime.
44+
*
45+
* @param date - JavaScript Date object
46+
* @returns Unix time in milliseconds
47+
*
48+
* @category Time
49+
* @since 2.0.0
50+
*/
51+
export const fromDate = (date: Date): UnixTime => BigInt(date.getTime())
52+
53+
/**
54+
* Convert UnixTime to JavaScript Date.
55+
*
56+
* @param unixTime - Unix time in milliseconds
57+
* @returns JavaScript Date object
58+
*
59+
* @category Time
60+
* @since 2.0.0
61+
*/
62+
export const toDate = (unixTime: UnixTime): Date => new Date(Number(unixTime))
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/**
2+
* Time utilities for Cardano blockchain time operations.
3+
* Provides type-safe conversions between slots and Unix time.
4+
*
5+
* @module Time
6+
* @since 2.0.0
7+
*/
8+
9+
import type * as Network from "../Network.js"
10+
import type * as Slot from "./Slot.js"
11+
import * as SlotConfig from "./SlotConfig.js"
12+
import * as UnixTime from "./UnixTime.js"
13+
14+
export * as Slot from "./Slot.js"
15+
export * as SlotConfig from "./SlotConfig.js"
16+
export * as UnixTime from "./UnixTime.js"
17+
18+
/**
19+
* Convert a slot number to Unix time (in milliseconds).
20+
*
21+
* @param slot - The slot number to convert
22+
* @param slotConfig - The network's slot configuration
23+
* @returns Unix timestamp in milliseconds
24+
*
25+
* @category Conversion
26+
* @since 2.0.0
27+
*
28+
* @example
29+
* ```typescript
30+
* import * as Time from "@evolution-sdk/core/Time"
31+
*
32+
* const slot = 12345678n
33+
* const config = Time.SlotConfig.SLOT_CONFIG_NETWORK.Mainnet
34+
* const unixTime = Time.slotToUnixTime(slot, config)
35+
* console.log(unixTime) // Unix time in milliseconds
36+
* ```
37+
*/
38+
export const slotToUnixTime = (slot: Slot.Slot, slotConfig: SlotConfig.SlotConfig): UnixTime.UnixTime => {
39+
const msAfterBegin = (slot - slotConfig.zeroSlot) * BigInt(slotConfig.slotLength)
40+
return slotConfig.zeroTime + msAfterBegin
41+
}
42+
43+
/**
44+
* Convert Unix time (in milliseconds) to the enclosing slot number.
45+
* Uses floor division to find the slot that contains the given time.
46+
*
47+
* @param unixTime - Unix timestamp in milliseconds
48+
* @param slotConfig - The network's slot configuration
49+
* @returns The slot number that contains this Unix time
50+
*
51+
* @category Conversion
52+
* @since 2.0.0
53+
*
54+
* @example
55+
* ```typescript
56+
* import * as Time from "@evolution-sdk/core/Time"
57+
*
58+
* const unixTime = 1596059091000n // Mainnet Shelley start
59+
* const config = Time.SlotConfig.SLOT_CONFIG_NETWORK.Mainnet
60+
* const slot = Time.unixTimeToSlot(unixTime, config)
61+
* console.log(slot) // 4492800n
62+
* ```
63+
*/
64+
export const unixTimeToSlot = (unixTime: UnixTime.UnixTime, slotConfig: SlotConfig.SlotConfig): Slot.Slot => {
65+
const timePassed = unixTime - slotConfig.zeroTime
66+
const slotsPassed = timePassed / BigInt(slotConfig.slotLength)
67+
return slotsPassed + slotConfig.zeroSlot
68+
}
69+
70+
/**
71+
* Get the current slot number for a network.
72+
*
73+
* @param network - The network to get current slot for
74+
* @returns Current slot number
75+
*
76+
* @category Utility
77+
* @since 2.0.0
78+
*
79+
* @example
80+
* ```typescript
81+
* import * as Time from "@evolution-sdk/core/Time"
82+
*
83+
* const currentSlot = Time.getCurrentSlot("Mainnet")
84+
* console.log(currentSlot) // Current mainnet slot
85+
* ```
86+
*/
87+
export const getCurrentSlot = (network: Network.Network): Slot.Slot => {
88+
const config = SlotConfig.SLOT_CONFIG_NETWORK[network]
89+
const now = UnixTime.now()
90+
return unixTimeToSlot(now, config)
91+
}
92+
93+
/**
94+
* Check if a slot is in the future relative to current time.
95+
*
96+
* @param slot - The slot to check
97+
* @param slotConfig - The network's slot configuration
98+
* @returns True if the slot is in the future
99+
*
100+
* @category Utility
101+
* @since 2.0.0
102+
*/
103+
export const isSlotInFuture = (slot: Slot.Slot, slotConfig: SlotConfig.SlotConfig): boolean => {
104+
const now = UnixTime.now()
105+
const slotTime = slotToUnixTime(slot, slotConfig)
106+
return slotTime > now
107+
}
108+
109+
/**
110+
* Check if a slot is in the past relative to current time.
111+
*
112+
* @param slot - The slot to check
113+
* @param slotConfig - The network's slot configuration
114+
* @returns True if the slot is in the past
115+
*
116+
* @category Utility
117+
* @since 2.0.0
118+
*/
119+
export const isSlotInPast = (slot: Slot.Slot, slotConfig: SlotConfig.SlotConfig): boolean => {
120+
const now = UnixTime.now()
121+
const slotTime = slotToUnixTime(slot, slotConfig)
122+
return slotTime < now
123+
}
124+
125+
/**
126+
* Get the slot at a specific offset from now (in milliseconds).
127+
*
128+
* @param offsetMs - Offset in milliseconds (positive for future, negative for past)
129+
* @param network - The network
130+
* @returns Slot number at the offset time
131+
*
132+
* @category Utility
133+
* @since 2.0.0
134+
*
135+
* @example
136+
* ```typescript
137+
* import * as Time from "@evolution-sdk/core/Time"
138+
*
139+
* // Get slot 5 minutes from now
140+
* const futureSlot = Time.getSlotAt(5 * 60 * 1000, "Mainnet")
141+
*
142+
* // Get slot 10 minutes ago
143+
* const pastSlot = Time.getSlotAt(-10 * 60 * 1000, "Mainnet")
144+
* ```
145+
*/
146+
export const getSlotAt = (offsetMs: number, network: Network.Network): Slot.Slot => {
147+
const config = SlotConfig.SLOT_CONFIG_NETWORK[network]
148+
const targetTime = UnixTime.now() + BigInt(offsetMs)
149+
return unixTimeToSlot(targetTime, config)
150+
}

packages/evolution/src/core/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export * as SingleHostName from "./SingleHostName.js"
9595
export * as StakeReference from "./StakeReference.js"
9696
export * as Text from "./Text.js"
9797
export * as Text128 from "./Text128.js"
98+
export * as Time from "./Time/index.js"
9899
export * as Transaction from "./Transaction.js"
99100
export * as TransactionBody from "./TransactionBody.js"
100101
export * as TransactionHash from "./TransactionHash.js"

0 commit comments

Comments
 (0)