hashgraph / hashgraph/hedera-agent-kit-py

Bug: normalise_delete_non_fungible_token_allowance silently drops scheduling_params and skips normalisation

Open
#323 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
11
Forks
10
PR merge metrics
No merged PRs in 30d

Description

## Summary

`HederaParameterNormaliser.normalise_delete_non_fungible_token_allowance` contains two related
correctness bugs on the same line that cause scheduling parameters to be silently lost when a
caller attempts to schedule an NFT allowance deletion. A third related issue exists at the
call site in `DeleteNonFungibleTokenAllowanceTool`.

## Location

- `python/hedera_agent_kit/shared/hedera_utils/hedera_parameter_normalizer.py`, line 2410
- `python/hedera_agent_kit/plugins/core_token_plugin/delete_non_fungible_token_allowance.py`, line 97

## The Bugs

### Bug 1 — wrong source variable (line 2410)

The function parses and validates raw input into `parsed_params` at lines 2381–2386. Every
other field in the return statement correctly reads from `parsed_params`. Line 2410 alone reads
from `params` — the raw, unvalidated input.

\`\`\`python
# current (wrong)
scheduling_params=getattr(params, "scheduling_params", None),

# all other fields in the same return statement read from parsed_params
transaction_memo=parsed_params.transaction_memo,
\`\`\`

When `params` arrives as a plain `dict` (the standard path in LLM agent contexts),
`getattr(dict, "scheduling_params", None)` returns `None` — dicts do not support attribute
access. The scheduling intent is silently discarded with no error or warning.

### Bug 2 — normalisation step is skipped entirely (line 2410)

Every other scheduling-capable normaliser in this file (11+ methods) follows the same pattern:

\`\`\`python
scheduling_params = None
if getattr(parsed_params, "scheduling_params", None):
if parsed_params.scheduling_params.is_scheduled:
scheduling_params = await HederaParameterNormaliser.normalise_scheduled_transaction_params(
parsed_params.scheduling_params, context, client
)
\`\`\`

This converts the raw `OptionalScheduledTransactionParams` into the `ScheduleCreateParams`
type expected by `tx_mode_strategy` downstream. `normalise_delete_non_fungible_token_allowance`
skips this call and passes the raw object directly. Even when `params` is already a Pydantic
model and Bug 1 does not trigger, the un-normalised value causes a type mismatch at execution
time.

### Bug 3 — missing `await` at call site (line 97)

`DeleteNonFungibleTokenAllowanceTool.normalize_params` calls the normaliser without `await`:

\`\`\`python
# delete_non_fungible_token_allowance.py line 97
async def normalize_params(self, params, context, client):
return HederaParameterNormaliser.normalise_delete_non_fungible_token_allowance(
params, context, client
)
\`\`\`

The normaliser is currently a synchronous `@staticmethod`, so this works today. However, the
correct fix for Bug 2 requires making the normaliser `async` (to `await` the
`normalise_scheduled_transaction_params` call). Without also adding `await` here, that fix
would silently return a coroutine object instead of the normalised params, breaking all
non-scheduled calls as well.

## Impact

Any attempt to schedule an NFT allowance deletion via this tool will either:

- Silently execute as an **immediate** transaction (scheduling dropped, no error raised), or
- Fail at execution time with a type mismatch in the transaction mode strategy

The failure is silent in the most common case — the tool returns a transaction ID for an
immediate execution while the caller expected a scheduled transaction.

## Steps to Reproduce

\`\`\`python
import asyncio
from hedera_agent_kit.shared.hedera_utils.hedera_parameter_normalizer import (
HederaParameterNormaliser,
)

# Simulate params as a dict — the standard input shape from an LLM agent
params = {
"token_id": "0.0.1234",
"serial_numbers": [1, 2],
"owner_account_id": "0.0.5678",
"scheduling_params": {
"is_scheduled": True,
"payer_account_id": "0.0.9999",
},
}

context = {}
client = None # not reached before the bug manifests

result = HederaParameterNormaliser.normalise_delete_non_fungible_token_allowance(
params, context, client
)

# Bug 1: scheduling_params is None despite being provided
print(result.scheduling_params) # → None (expected: ScheduleCreateParams)
\`\`\`

**Expected:** `result.scheduling_params` is a normalised `ScheduleCreateParams` object.

**Actual:** `result.scheduling_params` is `None`.

The same test with any other scheduling-capable normaliser (e.g.
`normalise_associate_token`) will correctly populate `scheduling_params`.

## Suggested Fix

\`\`\`python
@staticmethod
async def normalise_delete_non_fungible_token_allowance(
params: DeleteNonFungibleTokenAllowanceParameters,
context: Context,
client: Client,
) -> DeleteNftAllowanceParametersNormalised:

# ... existing logic unchanged up to the return statement ...

scheduling_params = None
if getattr(parsed_params, "scheduling_params", None):
if parsed_params.scheduling_params.is_scheduled:
scheduling_params = await HederaParameterNormaliser.normalise_scheduled_transaction_params(
parsed_params.scheduling_params, context, client
)

return DeleteNftAllowanceParametersNormalised(
nft_wipe=[nft_allowance],
transaction_memo=parsed_params.transaction_memo,
scheduling_params=scheduling_params,
)
\`\`\`

And at the call site in `delete_non_fungible_token_allowance.py`:

\`\`\`python
async def normalize_params(self, params, context, client):
return await HederaParameterNormaliser.normalise_delete_non_fungible_token_allowance(
params, context, client
)
\`\`\`

## Environment

- Repo: `hashgraph/hedera-agent-kit-py`
- Normaliser: `python/hedera_agent_kit/shared/hedera_utils/hedera_parameter_normalizer.py:2410`
- Tool: `python/hedera_agent_kit/plugins/core_token_plugin/delete_non_fungible_token_allowance.py:97`

Contributor guide

Open the contributing guide

Research direction

Start at python/hedera_agent_kit/shared/hedera_utils/hedera_parameter_normalizer.py:2410 and compare its scheduling handling with the other scheduling-capable normalisers. Then inspect python/hedera_agent_kit/plugins/core_token_plugin/delete_non_fungible_token_allowance.py:97; done means scheduled parameters are normalized into ScheduleCreateParams and immediate calls still return normalized parameters.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
api, backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
76/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.