diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,8 @@
 # CHANGELOG
 
+## 3.0.1.0 — 20-05-2025
+* Support latest versions of `text`, `text-display` and `sel`
+
 ## 3.0.0.0 — 13-04-2024
 
 * The library has been transferred to the Haskell Cryptography Group's stewardship;
diff --git a/one-time-password.cabal b/one-time-password.cabal
--- a/one-time-password.cabal
+++ b/one-time-password.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.4
 name:               one-time-password
-version:            3.0.0.0
+version:            3.0.1.0
 synopsis:           HMAC-Based and Time-Based One-Time Passwords
 description:
   Implements HMAC-Based One-Time Password Algorithm as
@@ -20,11 +20,13 @@
 build-type:         Simple
 extra-source-files: README.md
 extra-doc-files:    CHANGELOG.md
-tested-with:        GHC ==9.4.8 || ==9.6.4 || ==9.8.2
+tested-with:
+  GHC ==9.4.8 || ==9.6.4 || ==9.6.7 || ==9.8.2 || ==9.8.4 || ==9.10.2
 
 source-repository head
   type:     git
-  location: git://github.com/haskell-cryptography/one-time-password.git
+  location:
+    https://github.com/haskell-cryptography/one-time-password.git
 
 common ghc-options
   ghc-options:
@@ -48,15 +50,16 @@
     OTP.TOTP
 
   build-depends:
-    , base             >=4.17   && <5
-    , bytestring       ^>=0.11
-    , cereal           ^>=0.5
-    , chronos          ^>=1.1.6
-    , cryptohash-sha1  ^>=0.11
-    , network-uri      ^>=2.6
-    , sel              ^>=0.0
-    , text             ^>=2.1
-    , text-display     ^>=0.0
+    , base                 >=4.17   && <5
+    , bytestring           ^>=0.12
+    , cereal               ^>=0.5
+    , chronos              ^>=1.1.6
+    , cryptohash-sha1      ^>=0.11
+    , network-uri          ^>=2.6
+    , sel                  ^>=0.1
+    , text                 >=2.0
+    , text-builder-linear  >=0.1
+    , text-display         ^>=1.0
 
   ghc-options:     -Wall
 
@@ -76,7 +79,7 @@
   build-depends:
     , base               >=4.17 && <5
     , base16
-    , base32             ^>=0.4
+    , base32             >=0.4
     , bytestring
     , chronos
     , cryptonite
@@ -127,5 +130,5 @@
     , torsor                ^>=0.1
 
   other-modules:      Paths_one_time_password
-  autogen-modules:      Paths_one_time_password
+  autogen-modules:    Paths_one_time_password
   ghc-options:        -Wall
diff --git a/src/OTP/Commons.hs b/src/OTP/Commons.hs
--- a/src/OTP/Commons.hs
+++ b/src/OTP/Commons.hs
@@ -15,9 +15,8 @@
 
 import Chronos (Time (..), Timespan (..), asSeconds, sinceEpoch)
 import Data.Int (Int64)
+import Data.Text.Builder.Linear (Builder)
 import Data.Text.Display
-import Data.Text.Lazy.Builder (Builder)
-import Data.Text.Lazy.Builder qualified as Text
 import Data.Word
 import Text.Printf (printf)
 
@@ -77,7 +76,7 @@
   displayBuilder OTP{digits, code} = displayWord32AsOTP digits code
 
 displayWord32AsOTP :: Word32 -> Word32 -> Builder
-displayWord32AsOTP digits code = Text.fromString $ printf ("%0" <> show digits <> "u") code
+displayWord32AsOTP digits code = displayBuilder @String $ printf ("%0" <> show digits <> "u") code
 
 -- |
 --
diff --git a/src/OTP/HOTP.hs b/src/OTP/HOTP.hs
--- a/src/OTP/HOTP.hs
+++ b/src/OTP/HOTP.hs
@@ -101,13 +101,13 @@
   -- ^ Number of digits in a password. MUST be 6 digits at a minimum, and possibly 7 and 8 digits.
   -> OTP
   -- ^ HOTP
-hotpSHA256 key counter digits' = unsafePerformIO $ do
+hotpSHA256 key counter digits' =
   let digits = digitsToWord32 digits'
-  let msg = runPut $ putWord64be counter
-  hash <- SHA256.authenticationTagToBinary <$> SHA256.authenticate msg key
-  let code = truncateHash $ BS.unpack hash
-  let result = code `rem` (10 ^ digits)
-  pure $ OTP digits result
+      msg = runPut $ putWord64be counter
+      hash = SHA256.authenticationTagToBinary $ SHA256.authenticate msg key
+      code = truncateHash $ BS.unpack hash
+      result = code `rem` (10 ^ digits)
+   in OTP digits result
 
 -- | Check presented password against a valid range.
 --
@@ -150,13 +150,13 @@
   -- ^ Number of digits in a password
   -> OTP
   -- ^ HOTP
-hotpSHA512 key counter digits' = unsafePerformIO $ do
+hotpSHA512 key counter digits' =
   let digits = digitsToWord32 digits'
-  let msg = runPut $ putWord64be counter
-  hash <- SHA512.authenticationTagToBinary <$> SHA512.authenticate msg key
-  let code = truncateHash $ BS.unpack hash
-  let result = code `rem` (10 ^ digits)
-  pure $ OTP digits result
+      msg = runPut $ putWord64be counter
+      hash = SHA512.authenticationTagToBinary $ SHA512.authenticate msg key
+      code = truncateHash $ BS.unpack hash
+      result = code `rem` (10 ^ digits)
+   in OTP digits result
 
 -- |
 --
diff --git a/test/Test/Properties.hs b/test/Test/Properties.hs
--- a/test/Test/Properties.hs
+++ b/test/Test/Properties.hs
@@ -136,7 +136,8 @@
     let format = DatetimeFormat (Just '-') (Just ' ') (Just ':')
      in time
           & timeToDatetime
-          & builder_YmdHMS (SubsecondPrecisionFixed 0) format
+          & encode_YmdHMS (SubsecondPrecisionFixed 0) format
+          & displayBuilder
 
 instance Display Timespan where
   displayBuilder timespan = displayBuilder (asSeconds timespan) <> "s"
