2

I have information encoded in the TokenName of an asset. These token names represent integers.

According to the Plutus source code, the TokenName is of type BuiltinByteString. How can I parse it to type Integer in the on chain code ? In short I am looking for a Plutus-pendant of the Haskell read, but one that returns a Maybe Integer.

2 Answers 2

2

I had trouble with the same thing, just going the opposite direction, Slot -> TokenName (Slot is just an Integer under the hood). After a bunch of pain I ended up just coding my own parsing logic:

-- Simplified business code here:
{-# INLINEABLE dcForSlot #-}
tokenNameForSlot :: Slot -> TokenName
tokenNameForSlot slot = TokenName $ Builtins.encodeUtf8 $ intToString $ getSlot slot

{-# INLINEABLE intToString #-}
intToString :: Integer -> Builtins.String
intToString i = Prelude.foldr Builtins.appendString "" strings
  where
    ints = intToInts i
    strings = map (Builtins.charToString . intToChar) ints

{-# INLINEABLE intToInts #-}
intToInts :: Integer -> [Integer]
intToInts i
  | (Builtins.equalsInteger a 0) = [b]
  | otherwise = (intToInts a) ++ [b]
  where
    (a, b) = divMod i 10

{-# INLINEABLE intToChar #-}
intToChar :: Integer -> Haskell.Char
intToChar i
  | (Builtins.equalsInteger i 0) = '0'
  | (Builtins.equalsInteger i 1) = '1'
  | (Builtins.equalsInteger i 2) = '2'
  | (Builtins.equalsInteger i 3) = '3'
  | (Builtins.equalsInteger i 4) = '4'
  | (Builtins.equalsInteger i 5) = '5'
  | (Builtins.equalsInteger i 6) = '6'
  | (Builtins.equalsInteger i 7) = '7'
  | (Builtins.equalsInteger i 8) = '8'
  | (Builtins.equalsInteger i 9) = '9'
  | otherwise = '0' -- Fix this

Feel free to try and reverse this to get what you want. It might be easier going the other direction, I don't have time rn to figure out what it would look like but I feel your pain, so I thought I'd share.

4
  • What does 'intToInts' do ?
    – Jey
    Sep 22, 2021 at 19:55
  • It splits all the digits of the integer: intToInts 5701 == [5, 7, 0, 1] Sep 22, 2021 at 20:13
  • Thank you, I understand. I will post my solution as soon as I have it. It's crazy that we have to use such work arounds on Plutus.
    – Jey
    Sep 23, 2021 at 6:38
  • Yeah. It's young still. There's plenty of room for people to add libraries. There's a big chance I missed some tools as well. Sep 23, 2021 at 6:43
1

This is slow but works.

{-# LANGUAGE  OverloadedStrings  #-}

module StackExchange where

import Prelude
import PlutusTx.Builtins.Class
import PlutusTx.Builtins.Internal
import Data.ByteString hiding (map)
import Data.Char

s = stringToBuiltinByteString "123"

bsToMaybeInteger :: BuiltinByteString -> Maybe Integer
bsToMaybeInteger str
  | Prelude.all (\x -> x >= 48 && x <= 57) unpackedString = Just (Prelude.read (Prelude.map chr unpackedString) :: Integer)
  | otherwise                                             = Nothing
  where
    unpackedString = map fromEnum . unpack . fromBuiltin $ str

Can be tested in a cabal repl session like this:

λ> StackExchange.bsToMaybeInteger StackExchange.s
Just 123
3
  • Have you tried this in compiled on-chain code? Sep 21, 2021 at 21:40
  • fair point, I have not done that yet... I guess there may be some slight modifications necessary.
    – Matthias Sieber
    Sep 21, 2021 at 21:46
  • Yeah. That's where I had the biggest headache, especially since the Plutus compiler doesn't give very helpful error messages. Sep 21, 2021 at 22:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.