How I can convert value of Global State to human-readable

Hi everybody,

I wanna push data (string type) to store in Global State of Smart Contract.

This my TEAL code:

#pragma version 2
byte "myKey"
txna ApplicationArgs 0
app_global_put
int 1
return

“appArgs” is required Uint8Array so I convert my string data and then create the transaction.

let appArgs = [];  
appArgs[0] = stringToUint8Array('This is my data');
let txn = algosdk.makeApplicationCreateTxn(recoveredAccount.addr, suggestedParams, 0,
            approvalProgByteArray, clearProgByteArray, localInts, localBytes,
            globalInts, globalBytes, appArgs);

I used this function to read Global State data

async function readGlobalState(client, account, index){
    let accountInfoResponse = await client.accountInformation(account.addr).do();
    for (let i = 0; i < accountInfoResponse['created-apps'].length; i++) { 
        if (accountInfoResponse['created-apps'][i].id == index) {
            console.log("Application's global state:");
            for (let n = 0; n < accountInfoResponse['created-apps'][i]['params']['global-state'].length; n++) {
                console.log(accountInfoResponse['created-apps'][i]['params']['global-state'][n]);
            }
        }
    }
}

I got the result and I tried to convert it to human-readable but I can’t.

{
  key: 'bXlLZXk=',
  value: {
    bytes: 'AAAAAAANCgo=',
    type: 1,
    uint: 0
  }
}

Could someone help me, please?
Thanks!

1 Like

Can you try something similar to:

console.log("Converted String:",Buffer.from(transactionResponse['global-state-delta'][0].key, "base64").toString());

In that example, I am just converting the key but you should be able to do the value as well. Also note that I am only doing the first global.

1 Like

The problem is that ‘AAAAAAANCgo=’ doesn’t correspont to the base64 of ‘This is my data’.
The base64 form of ‘This is my data’ is ‘77+5VGhpcyBpcyBteSBkYXRh’

I got this to work using:

async function readGlobalState(client, account, index){
    let accountInfoResponse = await client.accountInformation(account.addr).do();
    for (let i = 0; i < accountInfoResponse['created-apps'].length; i++) { 
        if (accountInfoResponse['created-apps'][i].id == index) {
            console.log("Application's global state:");
            for (let n = 0; n < accountInfoResponse['created-apps'][i]['params']['global-state'].length; n++) {
                const gs = accountInfoResponse['created-apps'][i]['params']['global-state'][n]
                console.log("Key: " + Buffer.from(gs.key, "base64").toString());
                console.log("Value: " + Buffer.from(gs.value.bytes, "base64").toString());
            }
        }
    }

and I set it using this code:

    let appArgs = [];
    const enc = new TextEncoder(); // always utf-8
    appArgs[0] = enc.encode("This is my data");
1 Like

Thank Jason. This solution work for me.

In Python I manage to decode the key field but not the bytes field (I get UnicodeDecodeError) :

        dict_state["key"] = base64.b64decode(dict_state["key"]).decode()
        dict_state["value"]["bytes"] = base64.b64decode(dict_state["value"]["bytes"]).decode()  # NOT WORKING

The value is :
"bytes": "E9IakdtRwMU+/ZtaF5LP97oQKUkOlxWC5NEkDlyuV3Q="

And the error is :

UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xd2 in position 1: invalid continuation byte

The bytes corresponding to the base64 representation E9IakdtRwMU+/ZtaF5LP97oQKUkOlxWC5NEkDlyuV3Q= does not represent a valid UTF-8 string.
Not all byte arrays are valid strings.

This smart contract key/value does not store actual strings but instead store some raw data that needs to be displayed differently to be human readable.

In your specific case, the base64 representation corresponds to a 32-byte array. So it’s very likely it’s an Algorand address (but there is no way to be sure without checking the smart contract). To display it in a human-readable way:

$ python3 -c "import base64, sys, algosdk; [print(algosdk.encoding.encode_address(base64.b64decode(line.strip()))) for line in sys.stdin if line.strip()]" <<< E9IakdtRwMU+/ZtaF5LP97oQKUkOlxWC5NEkDlyuV3Q=
CPJBVEO3KHAMKPX5TNNBPEWP665BAKKJB2LRLAXE2ESA4XFOK52CIGZDYA

Note that some smart contracts do not even use valid strings as keys.

1 Like

Thanks Fabrice it works !
Indeed I did not precise it but it is an address.
I have a function to make keys and values human readable and I will need to add a specific case for addresses.

Hi everybody! got a question for @fabrice : There’s a way to do the same as you suggested in Java? i can’t find an encoder method in the Java sdk to convert the bytes value (which actually is an Algorand address in human readable format) into the readable 58 chars String. Thanks a lot!