Returns:
diff --git a/src/features/abi-methods/data/abi-method.ts b/src/features/abi-methods/data/abi-method.ts
index 9cf5af1e..b432b096 100644
--- a/src/features/abi-methods/data/abi-method.ts
+++ b/src/features/abi-methods/data/abi-method.ts
@@ -12,6 +12,7 @@ import { invariant } from '@/utils/invariant'
import { isArc32AppSpec, isArc4AppSpec } from '@/features/common/utils'
import { createAppInterfaceAtom } from '@/features/app-interfaces/data'
import { sum } from '@/utils/sum'
+import { Hint, Struct } from '@/features/app-interfaces/data/types/arc-32/application'
const MAX_LINE_LENGTH = 20
@@ -21,17 +22,17 @@ export const abiMethodResolver = (transaction: TransactionResult): Atom
argument.multiline) || sum(methodArguments.map((arg) => arg.length)) > MAX_LINE_LENGTH
return {
- name: abiMethod.name,
+ name: abiMethodWithHint.abiMethod.name,
arguments: methodArguments,
return: methodReturn,
multiline,
@@ -39,7 +40,7 @@ export const abiMethodResolver = (transaction: TransactionResult): Atom> => {
+const createAbiMethodWithHintAtom = (transaction: TransactionResult): Atom> => {
return atom(async (get) => {
invariant(transaction['application-transaction'], 'application-transaction is not set')
@@ -56,28 +57,43 @@ const createAbiMethodAtom = (transaction: TransactionResult): Atom {
const abiMethod = new algosdk.ABIMethod(m)
return uint8ArrayToBase64(abiMethod.getSelector()) === transactionArgs[0]
})
- if (contractMethod) return new algosdk.ABIMethod(contractMethod)
+ if (contractMethod) {
+ const abiMethod = new algosdk.ABIMethod(contractMethod)
+ const hint = hints?.[abiMethod.getSignature()]
+ return { abiMethod, hint }
+ }
}
}
return undefined
})
}
-const createMethodArgumentsAtom = (transaction: TransactionResult, abiMethod: algosdk.ABIMethod): Atom> => {
+const createMethodArgumentsAtom = (
+ transaction: TransactionResult,
+ abiMethodWithHint: AbiMethodWithHint
+): Atom> => {
return atom(async (get) => {
invariant(transaction['application-transaction'], 'application-transaction is not set')
invariant(transaction['application-transaction']?.['application-args'], 'application-transaction application-args is not set')
+ const { abiMethod, hint } = abiMethodWithHint
const referencedTransactionIds = await get(getReferencedTransactionIdsAtom(transaction, abiMethod))
const abiValues = getAbiValueArgs(transaction, abiMethod)
const abiArguments: AbiMethodArgument[] = abiMethod.args.map((argumentSpec, index) => {
const argName = argumentSpec.name ?? `arg${index}`
+ const argHint =
+ hint && argumentSpec.name && (hint.structs?.[argumentSpec.name] || hint.default_arguments?.[argumentSpec.name])
+ ? ({
+ struct: hint.structs?.[argumentSpec.name],
+ } satisfies AbiValueHint)
+ : undefined
if (algosdk.abiTypeIsTransaction(argumentSpec.type)) {
const transactionId = referencedTransactionIds.shift()!
@@ -136,7 +152,7 @@ const createMethodArgumentsAtom = (transaction: TransactionResult, abiMethod: al
return {
name: argName,
- ...getAbiValue(argumentSpec.type, abiValue),
+ ...getAbiValue(argumentSpec.type, abiValue, argHint),
}
})
@@ -144,18 +160,27 @@ const createMethodArgumentsAtom = (transaction: TransactionResult, abiMethod: al
})
}
-const getMethodReturn = (transaction: TransactionResult, abiMethod: algosdk.ABIMethod): AbiMethodReturn => {
+const getMethodReturn = (transaction: TransactionResult, abiMethodWithHint: AbiMethodWithHint): AbiMethodReturn => {
+ const { abiMethod, hint } = abiMethodWithHint
+
if (abiMethod.returns.type === 'void') return 'void'
invariant(transaction.logs && transaction.logs.length > 0, 'transaction logs is not set')
+ const returnHint =
+ hint && hint.structs?.['output']
+ ? ({
+ struct: hint.structs?.['output'],
+ } satisfies AbiValueHint)
+ : undefined
+
const abiType = algosdk.ABIType.from(abiMethod.returns.type.toString())
// The first 4 bytes are SHA512_256 hash of the string "return"
const bytes = base64ToBytes(transaction.logs.slice(-1)[0]).subarray(4)
const abiValue = abiType.decode(bytes)
- return getAbiValue(abiType, abiValue)
+ return getAbiValue(abiType, abiValue, returnHint)
}
-const getAbiValue = (abiType: algosdk.ABIType, abiValue: algosdk.ABIValue): AbiValue => {
+const getAbiValue = (abiType: algosdk.ABIType, abiValue: algosdk.ABIValue, hint?: AbiValueHint): AbiValue => {
if (abiType instanceof algosdk.ABITupleType) {
const childTypes = abiType.childTypes
const abiValues = abiValue as algosdk.ABIValue[]
@@ -164,14 +189,38 @@ const getAbiValue = (abiType: algosdk.ABIType, abiValue: algosdk.ABIValue): AbiV
}
const childrenValues = abiValues.map((abiValue, index) => getAbiValue(childTypes[index], abiValue))
- const length = sum(childrenValues.map((v) => v.length))
- const multiline = childrenValues.some((v) => v.multiline) || length > MAX_LINE_LENGTH
- return {
- type: AbiType.Tuple,
- values: childrenValues,
- multiline,
- length,
+ if (hint?.struct) {
+ const values = childTypes.map(
+ (_, index) => {
+ const value = childrenValues[index]
+ const name = hint.struct!.elements[index][0]
+ return {
+ name: name,
+ value: value,
+ }
+ },
+ [{} as Record]
+ )
+ const length = sum(values.map((v) => `${v.name}: ${v.value}`.length))
+ const multiline = values.some((v) => v.value.multiline) || length > MAX_LINE_LENGTH
+
+ return {
+ type: AbiType.Struct,
+ values: values,
+ multiline: multiline,
+ length: length,
+ }
+ } else {
+ const length = sum(childrenValues.map((v) => v.length))
+ const multiline = childrenValues.some((v) => v.multiline) || length > MAX_LINE_LENGTH
+
+ return {
+ type: AbiType.Tuple,
+ values: childrenValues,
+ multiline,
+ length,
+ }
}
}
if (abiType instanceof algosdk.ABIArrayStaticType || abiType instanceof algosdk.ABIArrayDynamicType) {
@@ -335,3 +384,12 @@ const bigintToString = (value: bigint, decimalScale: number): string => {
const fractionString = valueString.slice(valueString.length - decimalScale)
return `${numberString}.${fractionString}`
}
+
+type AbiValueHint = {
+ struct?: Struct
+}
+
+type AbiMethodWithHint = {
+ abiMethod: algosdk.ABIMethod
+ hint?: Hint
+}
diff --git a/src/features/abi-methods/models/index.ts b/src/features/abi-methods/models/index.ts
index 44442a5d..c8758465 100644
--- a/src/features/abi-methods/models/index.ts
+++ b/src/features/abi-methods/models/index.ts
@@ -11,6 +11,7 @@ export enum AbiType {
Transaction = 'Transaction',
Application = 'Application',
Asset = 'Asset',
+ Struct = 'Struct',
}
type RepresentationProps = {
@@ -19,6 +20,11 @@ type RepresentationProps = {
}
export type AbiTupleValue = { type: AbiType.Tuple; values: AbiValue[] } & RepresentationProps
export type AbiArrayValue = { type: AbiType.Array; values: AbiValue[] } & RepresentationProps
+export type AbiStructElementValue = {
+ name: string
+ value: AbiValue
+}
+export type AbiStructValue = { type: AbiType.Struct; values: AbiStructElementValue[] } & RepresentationProps
export type AbiValue =
| ({
type: AbiType.String
@@ -46,6 +52,7 @@ export type AbiValue =
} & RepresentationProps)
| AbiArrayValue
| AbiTupleValue
+ | AbiStructValue
export type AbiReferenceValue =
| ({ type: AbiType.Account; value: string } & RepresentationProps)
diff --git a/src/features/applications/components/application-method-definitions.tsx b/src/features/applications/components/application-method-definitions.tsx
index a8d7c7cb..e8813157 100644
--- a/src/features/applications/components/application-method-definitions.tsx
+++ b/src/features/applications/components/application-method-definitions.tsx
@@ -93,6 +93,9 @@ function Method({ applicationId, method, appSpec, r
addr: activeAddress,
signer,
},
+ sendParams: {
+ populateAppCallResources: true,
+ },
})
const sentTxns = asTransactionFromSendResult(result)