1

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
    Commented Sep 22, 2021 at 19:55
  • It splits all the digits of the integer: intToInts 5701 == [5, 7, 0, 1] Commented 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
    Commented 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. Commented 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? Commented Sep 21, 2021 at 21:40
  • fair point, I have not done that yet... I guess there may be some slight modifications necessary. Commented 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. Commented Sep 21, 2021 at 22:09

Your Answer

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

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