2

How can I make the following function to retrieve only digit portion from the TokenName and use it on chain?

For example I want to retrieve the number 123 from "AAA123" (TokenName)

{-# INLINABLE getIdFromTokenName #-}
getIdFromTokenName :: TokenName -> Integer
getIdFromTokenName tn = ...

and I have the check function for state machine, as follows:

{-# INLINABLE check #-}
check :: Game -> GameDatum -> GameRedeemer -> ScriptContext -> Bool
check g _ (Buy tn) _ = ix > 0 && gMaxItems g >= ix
                            where
                                ix = getIdFromTokenName tn

2 Answers 2

1

given the request on way would be the following:

getIdFromTokenName :: TokenName -> Integer
getIdFromTokenName tn = getIdFromStr 0 $ (BS8.unpack . unTokenName) tn -- BS8.unpack :: ByteString -> String
  where
    getIdFromStr :: Integer -> String -> Integer
    getIdFromStr accumulatedNum strName =
      case strName of
        (char: restStr) ->
          case maybeIntegerFormChar char of
            Nothing  -> getIdFromStr accumulatedNum restStr
            Just int -> getIdFromStr (10 * accumulatedNum + int) restStr
        _               -> accumulatedNum

    maybeIntegerFormChar :: Char -> Maybe Integer
    maybeIntegerFormChar ch =
      case ch of
        '0' -> Just 0
        '1' -> Just 1
        '2' -> Just 2
        '3' -> Just 3
        '4' -> Just 4
        '5' -> Just 5
        '6' -> Just 6
        '7' -> Just 7
        '8' -> Just 8
        '9' -> Just 9
        _   -> Nothing

this should satisfy the codition of getting out 123 from "AAA123" but note that "AAA123BB45" will result in 12345

1
  • 1
    I like the addition of maybe, but would like to add that his might increase the script size. Another option to still be on the safe side is to first check the policy id and then use the unsafe getIdFromStr function. If the minting of the names is federated the occurrence of the edge case is not a problem.
    – Fermat
    Commented Jul 5, 2022 at 12:39
0

Token name is a Bytestring therefore it has to handle like that. I am learning and my attempt at extracting the integer value is like this:-

import Data.Char ( ord )
import Data.ByteString.Char8 (ByteString, unpack,pack)

getIdFromTokenName :: ByteString -> Integer
getIdFromTokenName tn = numbers (reverse (unpack tn)) 0 1

numbers :: String->Integer->Integer -> Integer 
numbers [] x y = x
numbers (l:ls) x y = if ord l >= 48 && ord l <= 57
    then numbers ls ((toInteger (ord l) - 48)* y + x) (y*10)
    else numbers ls x y

I used pack unpacked from the module imported above in ghci it was working like this

*Main> getIdFromTokenName (pack "NUM123") 
123

This is not a safe function to extract numbers and is also not the best method I feel. It's not checked in the Plutus setting also.

0

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.