Skip to content

feat: withdraw agent-wallet funds and pay the agent a commission#1389

Merged
MicBun merged 2 commits into
mainfrom
feat/maa-fund-and-withdraw
Jun 4, 2026
Merged

feat: withdraw agent-wallet funds and pay the agent a commission#1389
MicBun merged 2 commits into
mainfrom
feat/maa-fund-and-withdraw

Conversation

@MicBun

@MicBun MicBun commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

resolves: https://github.com/truflation/website/issues/4038

Summary by CodeRabbit

Release Notes

  • New Features
    • Introduced modular agent address (MAA) withdrawal system supporting configurable commission handling via flat and basis-point fee modes.
    • Added multi-bridge token routing for withdrawal and bridge-out operations across different chains.
    • Enabled balance inquiry and off-chain recipient payment capabilities for L1 transfers.
    • Comprehensive end-to-end test coverage for MAA withdrawal and commission logic.

@MicBun
MicBun requested a review from pr-time-tracker June 4, 2026 11:23
@MicBun MicBun self-assigned this Jun 4, 2026
@holdex

holdex Bot commented Jun 4, 2026

Copy link
Copy Markdown

Time Submission Status

Member Status Time Action Last Update
MicBun ✅ Submitted 4h Update time Jun 4, 2026, 11:57 AM

You can submit time with the command. Example:

@holdex pr submit-time 15m

See available commands to help comply with our Guidelines.

@MicBun

MicBun commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@holdex pr submit-time 4h

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@MicBun, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 27 minutes and 23 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e0c1c472-4128-432a-b964-424caed1e2e6

📥 Commits

Reviewing files that changed from the base of the PR and between cfeeef8 and a577ee6.

📒 Files selected for processing (2)
  • internal/migrations/049-maa-funding.sql
  • tests/streams/maa/withdraw_test.go
📝 Walkthrough

Walkthrough

This PR adds a complete MAA withdrawal feature enabling agents to withdraw and bridge funds with commission handling. The core migration defines bridge dispatch helpers, a two-leg atomic settlement that transfers commission first then routes payout internally or to L1, and public entry points. A production migration override and end-to-end test suite validate the implementation.

Changes

MAA Withdrawal Feature

Layer / File(s) Summary
Core withdrawal logic and public APIs
internal/migrations/049-maa-funding.sql
Migration introduces bridge dispatch helpers routing operations to eth_usdc or eth_truf based on bridge parameter, a commission calculator supporting flat and bps modes, and maa_do_withdraw private implementation that validates caller identity, resolves MAA instance and fee terms, checks sufficient free balance, computes clamped commission, atomically transfers commission then either transfers payout internally or bridges to L1 recipient, and records WITHDRAW event. Exposes public maa_withdraw, maa_bridge_out, and maa_get_balance.
Production migration generation
scripts/generate_prod_migrations.py, internal/migrations/049-maa-funding.prod.sql
Script adds generation target for prod override. Prod migration includes generated header and three dispatch actions that conditionally route balance/transfer/bridge operations to eth_usdc or eth_truf, failing closed on unsupported bridges.
End-to-end withdrawal test coverage
tests/streams/maa/withdraw_test.go
Test file implements TestMAAWithdraw with utility helpers for funding bridge addresses, fetching normalized balances, and initializing funded MAA state. Four test cases validate: basis-points commission on internal withdrawal, guard checks (non-MAA caller, over-balance, zero amount), flat-fee clamping when fee exceeds gross, and bridge-out where commission lands with agent internally while payout bridges to L1 and owner's internal balance remains unchanged.

Sequence Diagram

sequenceDiagram
  participant Caller as MAA Caller
  participant WithdrawAPI as maa_withdraw / maa_bridge_out
  participant DoWithdraw as maa_do_withdraw
  participant Ledger as Token Ledger
  participant Events as Event Log
  Caller->>WithdrawAPI: invoke with bridge and amount
  WithdrawAPI->>DoWithdraw: delegate with offramp flag
  DoWithdraw->>Ledger: resolve MAA instance and fee terms
  DoWithdraw->>Ledger: check free balance >= amount
  DoWithdraw->>Ledger: compute commission (flat or bps)
  DoWithdraw->>Ledger: transfer commission to restricted address
  alt offramp = false
    DoWithdraw->>Ledger: transfer payout to owner
  else offramp = true
    DoWithdraw->>Ledger: bridge payout to L1 recipient
  end
  DoWithdraw->>Events: record WITHDRAW event
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

type: feat

Poem

A rabbit hops through withdrawal gates,
With commissions split and two-leg fates,
From ledgers deep to bridges high,
The MAA finds its balance—oh my! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: withdraw agent-wallet funds and pay the agent a commission' directly and accurately summarizes the main change—the introduction of agent-wallet withdrawal functionality with commission handling, which aligns with the new SQL migration and test files added.
Docstring Coverage ✅ Passed Docstring coverage is 88.89% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/maa-fund-and-withdraw

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/streams/maa/withdraw_test.go (1)

123-134: ⚡ Quick win

Make WITHDRAW event assertion deterministic and rule-local.

This assertion is currently coupled to goldenRuleIDHex and to “last non-nil amount” across all rows. Prefer asserting against the created test rule ID and reading amount only from the WITHDRAW row.

💡 Proposed refactor
-func setupFundedMAA(
+func setupFundedMAA(
 	t *testing.T, ctx context.Context, platform *kwilTesting.Platform,
 	restricted, unrestricted util.EthereumAddress, feeBps int64, salt []byte, fund string,
-) []byte {
+) ([]byte, []byte) {
 	t.Helper()
 	require.NoError(t, erc20bridge.ForTestingInitializeExtension(ctx, platform))

 	ruleID := createDefaultRule(t, ctx, platform, restricted, feeBps, salt)
 	maa := joinRule(t, ctx, platform, unrestricted, ruleID)

 	orderedsync.ForTestingReset()
 	maaAddr := addrFromBytes(maa)
 	fundAddress(t, ctx, platform, maaAddr.Address(), fund, 1)
-	return maa
+	return maa, ruleID
 }
-		maa := setupFundedMAA(t, ctx, platform, restricted, unrestricted, 250, repeat(0xab, 32), "100000000000000000000")
+		maa, ruleID := setupFundedMAA(t, ctx, platform, restricted, unrestricted, 250, repeat(0xab, 32), "100000000000000000000")
 		maaAddr := addrFromBytes(maa)
...
-		var evtTypes []string
-		var lastAmount string
+		var evtTypes []string
+		var withdrawAmount string
 		require.NoError(t, callAs(ctx, platform, restricted, "maa_get_events", []any{
-			func() []byte { b, _ := hex.DecodeString(goldenRuleIDHex); return b }(), int64(100), int64(0),
+			ruleID, int64(100), int64(0),
 		}, func(row *common.Row) error {
-			evtTypes = append(evtTypes, row.Values[2].(string))
-			if row.Values[7] != nil {
-				lastAmount = row.Values[7].(*kwilTypes.Decimal).String()
+			eventType := row.Values[2].(string)
+			evtTypes = append(evtTypes, eventType)
+			if eventType == "WITHDRAW" && row.Values[7] != nil {
+				withdrawAmount = row.Values[7].(*kwilTypes.Decimal).String()
 			}
 			return nil
 		}))
 		require.Contains(t, evtTypes, "WITHDRAW")
-		require.Equal(t, "100000000000000000000", lastAmount, "WITHDRAW records the gross amount")
+		require.Equal(t, "100000000000000000000", withdrawAmount, "WITHDRAW records the gross amount")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/streams/maa/withdraw_test.go` around lines 123 - 134, The test
currently checks for a WITHDRAW event using the global goldenRuleIDHex and
captures the last non-nil amount across all rows; change it to use the test's
created rule ID (the local variable that holds the rule ID you create in this
test) instead of goldenRuleIDHex and, inside the callAs row callback (used by
maa_get_events), only read and assert lastAmount when the row corresponds to the
WITHDRAW event (e.g., check row.Values[...] == "WITHDRAW" using the same index
used for evtTypes or match the rule ID column to the created rule ID) so the
amount is taken from that specific WITHDRAW row and the assertion becomes
deterministic and rule-local.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/migrations/049-maa-funding.sql`:
- Around line 127-153: In maa_do_withdraw, after the for-loop that reads
maa_rules for $rule_id, add an explicit check that a row was found (e.g. test
$restricted_bytes IS NOT NULL or another field) and raise an ERROR if not found,
and also validate $fee_mode is non-NULL and one of the allowed values before
calling maa_commission; ensure these checks occur before computing $commission
and $payout so you never reach event recording with NULL fee/payee fields
(referencing symbols: maa_do_withdraw, maa_rules, $restricted_bytes, $fee_mode,
maa_commission).

---

Nitpick comments:
In `@tests/streams/maa/withdraw_test.go`:
- Around line 123-134: The test currently checks for a WITHDRAW event using the
global goldenRuleIDHex and captures the last non-nil amount across all rows;
change it to use the test's created rule ID (the local variable that holds the
rule ID you create in this test) instead of goldenRuleIDHex and, inside the
callAs row callback (used by maa_get_events), only read and assert lastAmount
when the row corresponds to the WITHDRAW event (e.g., check row.Values[...] ==
"WITHDRAW" using the same index used for evtTypes or match the rule ID column to
the created rule ID) so the amount is taken from that specific WITHDRAW row and
the assertion becomes deterministic and rule-local.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 186fc066-0f78-4f09-afcf-0e2a09d2df11

📥 Commits

Reviewing files that changed from the base of the PR and between ba19890 and cfeeef8.

📒 Files selected for processing (4)
  • internal/migrations/049-maa-funding.prod.sql
  • internal/migrations/049-maa-funding.sql
  • scripts/generate_prod_migrations.py
  • tests/streams/maa/withdraw_test.go

Comment thread internal/migrations/049-maa-funding.sql
@MicBun
MicBun merged commit 61e945a into main Jun 4, 2026
6 of 7 checks passed
@MicBun
MicBun deleted the feat/maa-fund-and-withdraw branch June 4, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant