#parse struct in indexer
19 messages · Page 1 of 1 (latest)
Hi @thin shoal. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
To load a transaction from the indexer and parse a custom struct (e.g., MyStruct) returned as an app call return value in TypeScript, you can use AlgoKit Utils for type-safe indexer queries and the ARC4 Struct utility for struct parsing.
Below is a script outline based on the knowledge sources:
-
Query the transaction from the indexer
Use AlgoKit Utils' indexer wrapper to fetch the transaction by ID. The response types are available for casting, e.g.,TransactionLookupResultIndexer lookups / searching, Indexer API response types. -
Define your struct using ARC4 Struct
Use theStructbase type to define your struct in TypeScriptVariable: Struct. -
Parse the return value
Extract the return value from the transaction and decode it using your struct definition.
Example Script
import { indexer } from '@algorandfoundation/algokit-utils';
import { TransactionLookupResult } from '@algorandfoundation/algokit-utils/types/indexer';
import { Struct } from '@algorandfoundation/algorand-typescript/arc4';
// 1. Define your struct
class MyStruct extends Struct<{ x: number; y: string; z: Uint8Array }> {}
// 2. Load the transaction from the indexer
const transactionId = 'YOUR_TRANSACTION_ID';
const client = algorand.client.indexer; // Assume algorand client is initialized
async function loadAndParseStruct() {
// Fetch transaction
const txResult = (await client.lookupTransactionByID(transactionId).do()) as TransactionLookupResult;
// 3. Extract the return value (assuming it's in the first inner-tx/app call return)
const returnValueB64 = txResult.transaction?.application_transaction?.return_value;
if (!returnValueB64) throw new Error('No return value found');
// 4. Decode base64 to Uint8Array
const returnValueBytes = Uint8Array.from(Buffer.from(returnValueB64, 'base64'));
// 5. Parse struct
const myStruct = MyStruct.decode(returnValueBytes);
console.log(myStruct);
}
loadAndParseStruct().catch(console.error);
**Notes:**
- Replace `YOUR_TRANSACTION_ID` with your actual transaction ID.
- Adjust the struct fields/types in `MyStruct` to match your contract definition.
- The script assumes the return value is in the `return_value` field of the transaction's application call. Adjust the extraction logic if your return value is elsewhere.
This approach leverages AlgoKit's type-safe indexer wrappers and ARC4 struct utilities for robust parsing, as described in the documentation[Indexer lookups / searching](<https://dev.algorand.co/algokit/utils/typescript/indexer/#_top>), [Variable: Struct](<https://dev.algorand.co/reference/algorand-typescript/api-reference/arc4/variables/struct/#variable-struct>), [Structs](<https://dev.algorand.co/algokit/client-generator/typescript/#structs>).
If you need more details on struct field types or decoding, please refer to your contract's ABI and the ARC4 documentation.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@thin shoal Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@jagged mirage parse hex 151f7c75000000000000000200000000000cb735000000000311936900000000000000000000000000000000000000000000000000000000000f42400000000000000000992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6 to data structure
class MyStruct extends arc4.Struct<{
state: UintN64
winProbability: UintN64
round: UintN64
deposit: UintN256
assetId: UintN64
gameCreator: Address
owner: Address
}> {}
create unit test for it
Let me check the knowledge base for you again. One moment! :books:
Certainly! Here’s how you can write a unit test in TypeScript to parse the provided hex string into your custom ARC4 struct, using the ARC4 types and struct utilities as described in the knowledge sources.
1. Define the Struct
import { arc4 } from '@algorandfoundation/algorand-typescript';
class MyStruct extends arc4.Struct<{
state: arc4.UintN64,
winProbability: arc4.UintN64,
round: arc4.UintN64,
deposit: arc4.UintN256,
assetId: arc4.UintN64,
gameCreator: arc4.Address,
owner: arc4.Address,
}> {}
2. Write the Unit Test
import { describe, it, expect } from 'vitest'; // or your preferred test runner
import { arc4 } from '@algorandfoundation/algorand-typescript';
const hex =
'151f7c75000000000000000200000000000cb735000000000311936900000000000000000000000000000000000000000000000000000000000f42400000000000000000992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6';
class MyStruct extends arc4.Struct<{
state: arc4.UintN64,
winProbability: arc4.UintN64,
round: arc4.UintN64,
deposit: arc4.UintN256,
assetId: arc4.UintN64,
gameCreator: arc4.Address,
owner: arc4.Address,
}> {}
describe('MyStruct ARC4 parsing', () => {
it('should parse hex string into MyStruct', () => {
// Remove the ARC4 return prefix (0x151f7c75) if present
const hexData = hex.startsWith('151f7c75') ? hex.slice(8) : hex;
const bytes = Uint8Array.from(Buffer.from(hexData, 'hex'));
const parsed = MyStruct.decode(bytes);
// Example assertions (replace with expected values)
expect(parsed).toBeInstanceOf(MyStruct);
expect(parsed.state.native).toBeDefined();
expect(parsed.winProbability.native).toBeDefined();
expect(parsed.round.native).toBeDefined();
expect(parsed.deposit.native).toBeDefined();
expect(parsed.assetId.native).toBeDefined();
expect(parsed.gameCreator.native).toBeDefined();
expect(parsed.owner.native).toBeDefined();
});
});
**Notes:**
- The test removes the ARC4 return prefix (`0x151f7c75`) as per ARC4 conventions.
- The `.decode` method is used to parse the bytes into the struct instance, as is standard for ARC4 types.
- Replace the assertions with your expected values if you know them.
This approach is directly supported by the ARC4 struct utilities in the TypeScript SDK, as described in the documentation[Variable: Struct](<https://dev.algorand.co/reference/algorand-typescript/api-reference/arc4/variables/struct/#variable-struct>). If you need to access the native values, use the `.native` property on each field as shown in the test.
If you need more detailed field-by-field assertions, you can log or inspect the parsed object and add specific checks.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
@thin shoal Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@jagged mirage this does not work.. Property 'decode' does not exist on type 'typeof MyStruct'.ts(2339)
can you do it from generated client without using "@algorandfoundation/algorand-typescript" library please?
Let me check the knowledge base for you again. One moment! :books:
Thank you for your clarification. Based on the knowledge sources provided, the recommended way to parse ABI return values (including structs) from a hex or base64 string using a generated client (from AlgoKit Client Generator) is to use the parsing/decoding utilities that are included in the generated client itself. These clients are tailored to your contract’s ABI and provide type-safe methods for decoding return values.
However, the knowledge sources do not provide explicit code examples or documentation for parsing a raw hex string into a struct using only the generated client, without relying on @algorandfoundation/algorand-typescript. The documentation describes that the generated client gives you type-safe methods for interacting with the contract and handling return values, but it does not detail a method for manually decoding a raw hex string into a struct instance outside of a contract call context Typed application clients, Client Generator.
Summary:
I'm sorry, but the knowledge sources do not contain enough information to provide a code example for parsing a raw hex string into a struct using only the generated client, without @algorandfoundation/algorand-typescript. If you have a generated client, it is designed to handle ABI encoding/decoding internally when you interact with the contract, but manual parsing of arbitrary hex data is not documented in the provided sources.
If you need to parse raw ABI-encoded data outside of contract calls, you may need to use lower-level ABI utilities, but these are not described in the context of the generated client in the current documentation.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@thin shoal Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@jagged mirage how to parse const hex = '151f7c75000000000000000200000000000cb735000000000311936900000000000000000000000000000000000000000000000000000000000f42400000000000000000992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6' to abiTuple: [bigint, bigint, bigint, bigint, bigint, string, string]
Let me check the knowledge base for you again. One moment! :books:
To parse the provided hex string into an ABI tuple of the form [bigint, bigint, bigint, bigint, bigint, string, string] using the Algorand JavaScript SDK, you should:
- Convert the hex string to a
Uint8Array. - Use the ABI type system to decode the tuple.
The Algorand JS SDK provides the ABITupleType class, which can be constructed with the appropriate child types and used to decode a byte array into a tuple. Here’s how you can do it:
import { ABITupleType, ABIUintType, ABIAddressType, hexToBytes } from 'algosdk';
// 1. Remove the ARC4 return prefix (first 4 bytes, 8 hex chars)
const hex =
'151f7c75000000000000000200000000000cb735000000000311936900000000000000000000000000000000000000000000000000000000000f42400000000000000000992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6992536ce7348ce82f5e9cd03398f18929625b3cab8a76439d3ca6fd3bbfaf6c6';
const hexData = hex.slice(8);
// 2. Convert hex to bytes
const bytes = hexToBytes(hexData);
// 3. Define the ABI tuple type
const tupleType = new ABITupleType([
new ABIUintType(64), // state: uint64
new ABIUintType(64), // winProbability: uint64
new ABIUintType(64), // round: uint64
new ABIUintType(256), // deposit: uint256
new ABIUintType(64), // assetId: uint64
new ABIAddressType(), // gameCreator: address
new ABIAddressType(), // owner: address
]);
// 4. Decode the bytes
const abiTuple = tupleType.decode(bytes);
// abiTuple is now: [bigint, bigint, bigint, bigint, bigint, string, string]
console.log(abiTuple);
- The
hexToBytesfunction converts the hex string to aUint8ArrayhexToBytes. - The
ABITupleType.decodemethod decodes the byte array into the tuple ABITupleType.decode.
Note: The two address fields will be returned as Algorand address strings.