Skip to content

feat(money-account-utils): add money account transaction batch builders - #9680

Merged
Jwhiles merged 5 commits into
mainfrom
feat/add-hooks
Aug 3, 2026
Merged

feat(money-account-utils): add money account transaction batch builders#9680
Jwhiles merged 5 commits into
mainfrom
feat/add-hooks

Conversation

@Jwhiles

@Jwhiles Jwhiles commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Explanation

Ports the Money Account deposit and withdrawal transaction batch builders from metamask-mobile (app/components/UI/Money/utils/moneyAccountTransactions.ts) into this package, so mobile and extension encode the vault calls identically rather than each keeping its own copy.

What moved: the ABIs, the calldata encoders, the slippage and share arithmetic, the mUSD deposit-asset resolution, and the two contract reads (previewDeposit on the lens, getRate on the accountant).

What deliberately did not move: the four client wrappers (updateMoneyAccountDepositTokenAmount, updateMoneyAccountWithdrawTokenAmount, getMoneyAccountDepositTransactionsData, getMoneyAccountWithdrawTransactionsData). Those read vault config, provider and recipient from mobile's Redux/Engine singletons and return a Confirmations-owned type, so they stay in the client and delegate to these builders.

Signatures are unchanged from mobile, including the injected provider, so client call sites only change their import path. @ethersproject/{abi,abstract-provider,contracts} v5 is used directly rather than the ethers umbrella, matching the convention already established by money-account-balance-service (which reads the same lens and accountant contracts).

References

N/A

Checklist

  • I've updated the test suite for new or updated code as appropriate (100% coverage maintained)
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed, highlighting breaking changes as necessary
  • I've prepared draft pull requests for clients and ensured that new or referenced constants are available in those clients

Note

Medium Risk
Changes on-chain calldata and share/slippage math for user fund movements; logic is well-tested (including the prior floor-division withdrawal bug) but mistakes could cause failed or mis-sized vault txs.

Overview
Ports Money Account vault deposit/withdraw batch encoding from MetaMask Mobile into @metamask/money-account-utils, so clients share one implementation for approve+deposit and withdraw+transfer flows.

Deposit: buildMoneyAccountDepositBatch reads previewDeposit on the lens, sets minimumMint via 0.2% slippage (applySlippage), and returns typed approve + teller deposit txs. Withdraw: buildMoneyAccountWithdrawBatch reads getRate, converts assets to shares with ceiling division (getSharesForWithdrawal) to avoid MinimumAssetsNotMet reverts, then encodes teller withdraw (to the money account) plus mUSD transfer to the recipient. Both full builders reject zero amounts and require an @ethersproject Provider.

Adds placeholder variants (buildMoneyAccountDepositPlaceholderBatch / buildMoneyAccountWithdrawPlaceholderBatch) that only resolve to, value, and TransactionType (no calldata, no RPC). Also exports getMoneyAccountDepositAssetId / getMoneyAccountDepositAssetAddress, TELLER_ABI, and related types; types MUSD_TOKEN_ASSET_ID_BY_CHAIN as CaipAssetType; adds @ethersproject/* deps and a large Jest suite.

Reviewed by Cursor Bugbot for commit 832c497. Bugbot is set up for automated code reviews on this repo. Configure here.

@Jwhiles
Jwhiles requested review from a team as code owners July 28, 2026 13:46
@Jwhiles
Jwhiles force-pushed the feat/money-account-utils-package branch 3 times, most recently from bc4b92b to d90583a Compare July 30, 2026 12:51
Base automatically changed from feat/money-account-utils-package to main July 30, 2026 13:45
@Jwhiles
Jwhiles force-pushed the feat/add-hooks branch 2 times, most recently from 061c619 to a42e8d0 Compare July 31, 2026 09:39
@Jwhiles

Jwhiles commented Jul 31, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.5-preview-a42e8d0d2
@metamask-previews/accounts-controller@39.0.5-preview-a42e8d0d2
@metamask-previews/address-book-controller@7.1.2-preview-a42e8d0d2
@metamask-previews/ai-controllers@0.8.0-preview-a42e8d0d2
@metamask-previews/analytics-controller@1.2.1-preview-a42e8d0d2
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-a42e8d0d2
@metamask-previews/announcement-controller@8.1.0-preview-a42e8d0d2
@metamask-previews/app-metadata-controller@2.0.1-preview-a42e8d0d2
@metamask-previews/approval-controller@9.0.2-preview-a42e8d0d2
@metamask-previews/assets-controller@11.3.1-preview-a42e8d0d2
@metamask-previews/assets-controllers@110.0.2-preview-a42e8d0d2
@metamask-previews/authenticated-user-storage@3.0.1-preview-a42e8d0d2
@metamask-previews/base-controller@9.1.0-preview-a42e8d0d2
@metamask-previews/base-data-service@0.1.3-preview-a42e8d0d2
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-a42e8d0d2
@metamask-previews/bridge-controller@78.0.1-preview-a42e8d0d2
@metamask-previews/bridge-status-controller@74.6.0-preview-a42e8d0d2
@metamask-previews/build-utils@3.0.4-preview-a42e8d0d2
@metamask-previews/chain-agnostic-permission@1.7.0-preview-a42e8d0d2
@metamask-previews/chomp-api-service@4.0.0-preview-a42e8d0d2
@metamask-previews/claims-controller@0.5.3-preview-a42e8d0d2
@metamask-previews/client-controller@1.0.1-preview-a42e8d0d2
@metamask-previews/client-utils@1.5.0-preview-a42e8d0d2
@metamask-previews/compliance-controller@2.1.0-preview-a42e8d0d2
@metamask-previews/composable-controller@12.0.1-preview-a42e8d0d2
@metamask-previews/config-registry-controller@1.0.0-preview-a42e8d0d2
@metamask-previews/connectivity-controller@0.3.0-preview-a42e8d0d2
@metamask-previews/controller-utils@12.3.0-preview-a42e8d0d2
@metamask-previews/core-backend@8.0.0-preview-a42e8d0d2
@metamask-previews/delegation-controller@3.0.2-preview-a42e8d0d2
@metamask-previews/earn-controller@12.2.2-preview-a42e8d0d2
@metamask-previews/eip-5792-middleware@3.0.5-preview-a42e8d0d2
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-a42e8d0d2
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-a42e8d0d2
@metamask-previews/ens-controller@19.1.5-preview-a42e8d0d2
@metamask-previews/eth-block-tracker@15.0.1-preview-a42e8d0d2
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-a42e8d0d2
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-a42e8d0d2
@metamask-previews/foundryup@1.0.1-preview-a42e8d0d2
@metamask-previews/gas-fee-controller@26.3.0-preview-a42e8d0d2
@metamask-previews/gator-permissions-controller@5.0.0-preview-a42e8d0d2
@metamask-previews/geolocation-controller@0.1.3-preview-a42e8d0d2
@metamask-previews/java-tron-up@1.0.0-preview-a42e8d0d2
@metamask-previews/json-rpc-engine@10.5.0-preview-a42e8d0d2
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-a42e8d0d2
@metamask-previews/keyring-controller@27.1.0-preview-a42e8d0d2
@metamask-previews/local-node-utils@1.0.0-preview-a42e8d0d2
@metamask-previews/logging-controller@8.0.2-preview-a42e8d0d2
@metamask-previews/message-manager@14.1.2-preview-a42e8d0d2
@metamask-previews/messenger@2.0.0-preview-a42e8d0d2
@metamask-previews/messenger-cli@0.2.0-preview-a42e8d0d2
@metamask-previews/money-account-api-data-service@0.4.0-preview-a42e8d0d2
@metamask-previews/money-account-balance-service@2.4.0-preview-a42e8d0d2
@metamask-previews/money-account-controller@0.3.3-preview-a42e8d0d2
@metamask-previews/money-account-upgrade-controller@3.0.0-preview-a42e8d0d2
@metamask-previews/money-account-utils@1.0.0-preview-a42e8d0d2
@metamask-previews/multichain-account-service@13.0.0-preview-a42e8d0d2
@metamask-previews/multichain-api-middleware@4.0.1-preview-a42e8d0d2
@metamask-previews/multichain-network-controller@3.2.1-preview-a42e8d0d2
@metamask-previews/multichain-transactions-controller@7.1.1-preview-a42e8d0d2
@metamask-previews/name-controller@9.1.2-preview-a42e8d0d2
@metamask-previews/network-connection-banner-controller@0.1.1-preview-a42e8d0d2
@metamask-previews/network-controller@34.0.0-preview-a42e8d0d2
@metamask-previews/network-enablement-controller@6.0.0-preview-a42e8d0d2
@metamask-previews/notification-services-controller@26.0.0-preview-a42e8d0d2
@metamask-previews/passkey-controller@3.0.0-preview-a42e8d0d2
@metamask-previews/permission-controller@13.1.1-preview-a42e8d0d2
@metamask-previews/permission-log-controller@5.1.0-preview-a42e8d0d2
@metamask-previews/perps-controller@10.0.0-preview-a42e8d0d2
@metamask-previews/phishing-controller@17.3.0-preview-a42e8d0d2
@metamask-previews/platform-api-docs@0.0.0-preview-a42e8d0d2
@metamask-previews/polling-controller@16.0.8-preview-a42e8d0d2
@metamask-previews/preferences-controller@23.1.0-preview-a42e8d0d2
@metamask-previews/profile-metrics-controller@4.0.2-preview-a42e8d0d2
@metamask-previews/profile-sync-controller@28.3.0-preview-a42e8d0d2
@metamask-previews/ramps-controller@18.0.0-preview-a42e8d0d2
@metamask-previews/rate-limit-controller@7.0.1-preview-a42e8d0d2
@metamask-previews/react-data-query@0.2.2-preview-a42e8d0d2
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-a42e8d0d2
@metamask-previews/sample-controllers@5.0.3-preview-a42e8d0d2
@metamask-previews/seedless-onboarding-controller@10.1.0-preview-a42e8d0d2
@metamask-previews/selected-network-controller@26.1.5-preview-a42e8d0d2
@metamask-previews/sentinel-api-service@1.0.0-preview-a42e8d0d2
@metamask-previews/shield-controller@5.1.3-preview-a42e8d0d2
@metamask-previews/signature-controller@39.2.8-preview-a42e8d0d2
@metamask-previews/smart-transactions-controller@25.0.1-preview-a42e8d0d2
@metamask-previews/snap-account-service@2.1.0-preview-a42e8d0d2
@metamask-previews/social-controllers@2.7.0-preview-a42e8d0d2
@metamask-previews/solana-test-validator-up@1.0.0-preview-a42e8d0d2
@metamask-previews/stellar-quickstart-up@0.0.0-preview-a42e8d0d2
@metamask-previews/storage-service@1.0.2-preview-a42e8d0d2
@metamask-previews/subscription-controller@6.2.1-preview-a42e8d0d2
@metamask-previews/transaction-controller@69.3.0-preview-a42e8d0d2
@metamask-previews/transaction-pay-controller@26.0.1-preview-a42e8d0d2
@metamask-previews/user-operation-controller@41.2.7-preview-a42e8d0d2
@metamask-previews/wallet@8.1.0-preview-a42e8d0d2
@metamask-previews/wallet-cli@0.0.0-preview-a42e8d0d2

Comment on lines +458 to +480
const shareAmount =
amount === 0n
? 0n
: getSharesForWithdrawal(
amount,
await getVaultRate({ accountantAddress, provider }),
);
// Allow 1-unit slippage on minimumAssets as defense-in-depth against
// rounding: the contract's mulDivDown can truncate assetsOut by up to
// 1 unit relative to the requested amount. This tolerance is safe
// because ceiling division in getSharesForWithdrawal already guarantees
// assetsOut >= amount; the 1-unit slack here is a second line of
// defense, not a standalone fix. The subsequent ERC-20 transfer uses
// the original `amount`, so the tolerance does not affect how much the
// user receives — it only prevents a spurious revert from the teller's
// MinimumAssetsNotMet check.
const minimumAssets = amount > 0n ? amount - 1n : 0n;
const withdrawData = buildWithdrawData(
musdAddress,
shareAmount,
minimumAssets,
moneyAccountAddress,
);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Zero-amount withdraw placeholders encode shareAmount = 0, which Veda Teller rejects with ZeroShares.
Unlike deposit placeholders (which use a dedicated builder that omits calldata), withdraw placeholders may fail during simulation or submission before re-encoding.

Would it be worth adding a buildMoneyAccountWithdrawPlaceholderBatch, mirroring the deposit placeholder builder, to solve this ?

Returning something like
withdrawTx: teller target/type, no data,
transferTx: mUSD target/type, no data,
No amount, provider, accountant, recipient, or money-account address required

Then make buildMoneyAccountWithdrawBatch reject amount === 0n, so it cannot produce known-reverting calldata.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's a good idea - have added it and will re-integrate into my mobile PR

Jwhiles added a commit that referenced this pull request Aug 3, 2026
…zero amounts

Review feedback on #9680: a zero-amount withdraw encodes
`withdraw(mUSD, 0, 0, moneyAccount)`, which the teller rejects for redeeming no
shares. Unlike the deposit path — which got a dedicated placeholder builder that
omits calldata — the withdraw path had no way to express "targets resolved, no
amount yet" other than the `amount === 0n` sentinel.

Adds `buildMoneyAccountWithdrawPlaceholderBatch({ chainId, tellerAddress })`,
mirroring the deposit placeholder: synchronous, no provider, no accountant
address, no recipient, no money account address.

Both encoding builders now throw on a zero amount, before any vault read, so
neither can produce calldata that is valid and submittable but cannot succeed.
That removes the sentinel, the two dead parameters it implied, and the
zero-amount branches in both builders.

Note on the reported symptom: this does not change whether a placeholder batch
simulates cleanly. `generateEIP7702BatchTransaction` maps absent calldata to
`'0x'`, so the deposit placeholder encodes empty calls to the token and teller,
and with an atomic batch those revert too. The value here is that the illegal
state becomes unrepresentable, not that a simulation starts passing.

Consumers must guard a zero amount before calling the encoding builders — for a
cleared amount field there is nothing to re-encode.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Jwhiles

Jwhiles commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@metamaskbot publish-preview

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Preview builds have been published. Learn how to use preview builds in other projects.

Expand for full list of packages and versions.
@metamask-previews/account-tree-controller@7.5.5-preview-7aa2077d5
@metamask-previews/accounts-controller@39.0.5-preview-7aa2077d5
@metamask-previews/address-book-controller@7.1.2-preview-7aa2077d5
@metamask-previews/ai-controllers@0.8.0-preview-7aa2077d5
@metamask-previews/analytics-controller@1.2.1-preview-7aa2077d5
@metamask-previews/analytics-data-regulation-controller@0.0.0-preview-7aa2077d5
@metamask-previews/announcement-controller@8.1.0-preview-7aa2077d5
@metamask-previews/app-metadata-controller@2.0.1-preview-7aa2077d5
@metamask-previews/approval-controller@9.0.2-preview-7aa2077d5
@metamask-previews/assets-controller@11.3.1-preview-7aa2077d5
@metamask-previews/assets-controllers@110.0.2-preview-7aa2077d5
@metamask-previews/authenticated-user-storage@3.0.1-preview-7aa2077d5
@metamask-previews/base-controller@9.1.0-preview-7aa2077d5
@metamask-previews/base-data-service@0.1.3-preview-7aa2077d5
@metamask-previews/bitcoin-regtest-up@1.0.0-preview-7aa2077d5
@metamask-previews/bridge-controller@78.0.1-preview-7aa2077d5
@metamask-previews/bridge-status-controller@74.6.0-preview-7aa2077d5
@metamask-previews/build-utils@3.0.4-preview-7aa2077d5
@metamask-previews/chain-agnostic-permission@1.7.0-preview-7aa2077d5
@metamask-previews/chomp-api-service@4.0.0-preview-7aa2077d5
@metamask-previews/claims-controller@0.5.3-preview-7aa2077d5
@metamask-previews/client-controller@1.0.1-preview-7aa2077d5
@metamask-previews/client-utils@1.5.0-preview-7aa2077d5
@metamask-previews/compliance-controller@2.1.0-preview-7aa2077d5
@metamask-previews/composable-controller@12.0.1-preview-7aa2077d5
@metamask-previews/config-registry-controller@1.0.0-preview-7aa2077d5
@metamask-previews/connectivity-controller@0.3.0-preview-7aa2077d5
@metamask-previews/controller-utils@12.3.0-preview-7aa2077d5
@metamask-previews/core-backend@8.0.0-preview-7aa2077d5
@metamask-previews/delegation-controller@3.0.2-preview-7aa2077d5
@metamask-previews/earn-controller@12.2.2-preview-7aa2077d5
@metamask-previews/eip-5792-middleware@3.0.5-preview-7aa2077d5
@metamask-previews/eip-7702-internal-rpc-middleware@0.1.1-preview-7aa2077d5
@metamask-previews/eip1193-permission-middleware@2.0.1-preview-7aa2077d5
@metamask-previews/ens-controller@19.1.5-preview-7aa2077d5
@metamask-previews/eth-block-tracker@15.0.1-preview-7aa2077d5
@metamask-previews/eth-json-rpc-middleware@23.1.3-preview-7aa2077d5
@metamask-previews/eth-json-rpc-provider@6.0.1-preview-7aa2077d5
@metamask-previews/foundryup@1.0.1-preview-7aa2077d5
@metamask-previews/gas-fee-controller@26.3.0-preview-7aa2077d5
@metamask-previews/gator-permissions-controller@5.0.0-preview-7aa2077d5
@metamask-previews/geolocation-controller@0.1.3-preview-7aa2077d5
@metamask-previews/java-tron-up@1.0.0-preview-7aa2077d5
@metamask-previews/json-rpc-engine@10.5.0-preview-7aa2077d5
@metamask-previews/json-rpc-middleware-stream@8.0.8-preview-7aa2077d5
@metamask-previews/keyring-controller@27.1.0-preview-7aa2077d5
@metamask-previews/local-node-utils@1.0.0-preview-7aa2077d5
@metamask-previews/logging-controller@8.0.2-preview-7aa2077d5
@metamask-previews/message-manager@14.1.2-preview-7aa2077d5
@metamask-previews/messenger@2.0.0-preview-7aa2077d5
@metamask-previews/messenger-cli@0.2.0-preview-7aa2077d5
@metamask-previews/money-account-api-data-service@0.4.0-preview-7aa2077d5
@metamask-previews/money-account-balance-service@2.4.0-preview-7aa2077d5
@metamask-previews/money-account-controller@0.3.3-preview-7aa2077d5
@metamask-previews/money-account-upgrade-controller@3.0.0-preview-7aa2077d5
@metamask-previews/money-account-utils@1.0.0-preview-7aa2077d5
@metamask-previews/multichain-account-service@13.0.0-preview-7aa2077d5
@metamask-previews/multichain-api-middleware@4.0.1-preview-7aa2077d5
@metamask-previews/multichain-network-controller@3.2.1-preview-7aa2077d5
@metamask-previews/multichain-transactions-controller@7.1.1-preview-7aa2077d5
@metamask-previews/name-controller@9.1.2-preview-7aa2077d5
@metamask-previews/network-connection-banner-controller@0.1.1-preview-7aa2077d5
@metamask-previews/network-controller@34.0.0-preview-7aa2077d5
@metamask-previews/network-enablement-controller@6.0.0-preview-7aa2077d5
@metamask-previews/notification-services-controller@26.0.0-preview-7aa2077d5
@metamask-previews/passkey-controller@3.0.0-preview-7aa2077d5
@metamask-previews/permission-controller@13.1.1-preview-7aa2077d5
@metamask-previews/permission-log-controller@5.1.0-preview-7aa2077d5
@metamask-previews/perps-controller@10.0.0-preview-7aa2077d5
@metamask-previews/phishing-controller@17.3.0-preview-7aa2077d5
@metamask-previews/platform-api-docs@0.0.0-preview-7aa2077d5
@metamask-previews/polling-controller@16.0.8-preview-7aa2077d5
@metamask-previews/preferences-controller@23.1.0-preview-7aa2077d5
@metamask-previews/profile-metrics-controller@4.0.2-preview-7aa2077d5
@metamask-previews/profile-sync-controller@28.3.0-preview-7aa2077d5
@metamask-previews/ramps-controller@18.0.0-preview-7aa2077d5
@metamask-previews/rate-limit-controller@7.0.1-preview-7aa2077d5
@metamask-previews/react-data-query@0.2.2-preview-7aa2077d5
@metamask-previews/remote-feature-flag-controller@4.2.2-preview-7aa2077d5
@metamask-previews/sample-controllers@5.0.3-preview-7aa2077d5
@metamask-previews/seedless-onboarding-controller@10.1.0-preview-7aa2077d5
@metamask-previews/selected-network-controller@26.1.5-preview-7aa2077d5
@metamask-previews/sentinel-api-service@1.0.0-preview-7aa2077d5
@metamask-previews/shield-controller@5.1.3-preview-7aa2077d5
@metamask-previews/signature-controller@39.2.8-preview-7aa2077d5
@metamask-previews/smart-transactions-controller@25.0.1-preview-7aa2077d5
@metamask-previews/snap-account-service@2.1.0-preview-7aa2077d5
@metamask-previews/social-controllers@2.7.0-preview-7aa2077d5
@metamask-previews/solana-test-validator-up@1.0.0-preview-7aa2077d5
@metamask-previews/stellar-quickstart-up@0.0.0-preview-7aa2077d5
@metamask-previews/storage-service@1.0.2-preview-7aa2077d5
@metamask-previews/subscription-controller@6.2.1-preview-7aa2077d5
@metamask-previews/transaction-controller@69.3.0-preview-7aa2077d5
@metamask-previews/transaction-pay-controller@26.0.1-preview-7aa2077d5
@metamask-previews/user-operation-controller@41.2.7-preview-7aa2077d5
@metamask-previews/wallet@8.1.0-preview-7aa2077d5
@metamask-previews/wallet-cli@0.0.0-preview-7aa2077d5

ffmcgee725
ffmcgee725 previously approved these changes Aug 3, 2026
Jwhiles and others added 5 commits August 3, 2026 11:10
Ports the Money Account deposit and withdrawal batch builders from
metamask-mobile (`app/components/UI/Money/utils/moneyAccountTransactions.ts`)
so both clients encode the vault calls identically.

The client-resident wrappers around these builders stay in mobile: they read
vault config, provider and recipient from Redux/Engine singletons, which do
not belong in a shared package. Everything below that — ABIs, calldata
encoding, slippage and share arithmetic, and the two `previewDeposit`/`getRate`
reads — moves here, keeping the existing signatures so call sites only change
their import path.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The description predated the rescope: activity parsing and classification
were never extracted, and the vault transaction builders now are.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Address review feedback on the ported vault builders:

- Replace the `initialiseWithoutData` flag with a dedicated
  `buildMoneyAccountDepositPlaceholderBatch`. The flag path still awaited
  `previewDeposit` and discarded the result, and required five vault
  addresses it never used; the new builder is synchronous, takes only
  `chainId` and `tellerAddress`, and performs no vault reads.
- Make `MoneyAccountTxParams.params.data` required, with the no-calldata
  case as `MoneyAccountPlaceholderTxParams`, so callers of the encoding
  builders no longer have to narrow an optional field.
- Return `CaipAssetType | undefined` from `getMoneyAccountDepositAssetId`
  rather than silently defaulting to Monad, so an unsupported chain stays
  distinguishable. Clients apply their own default at the call site.
- Type `MUSD_TOKEN_ASSET_ID_BY_CHAIN` values as `CaipAssetType` and the
  deposit options' addresses as `Hex`, removing the internal casts.
- Fix withdraw comments describing the redeemed asset as USDC; the
  builders encode mUSD throughout.

Also reconcile the changelog with the released 1.0.0 of the package.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…zero amounts

Review feedback on #9680: a zero-amount withdraw encodes
`withdraw(mUSD, 0, 0, moneyAccount)`, which the teller rejects for redeeming no
shares. Unlike the deposit path — which got a dedicated placeholder builder that
omits calldata — the withdraw path had no way to express "targets resolved, no
amount yet" other than the `amount === 0n` sentinel.

Adds `buildMoneyAccountWithdrawPlaceholderBatch({ chainId, tellerAddress })`,
mirroring the deposit placeholder: synchronous, no provider, no accountant
address, no recipient, no money account address.

Both encoding builders now throw on a zero amount, before any vault read, so
neither can produce calldata that is valid and submittable but cannot succeed.
That removes the sentinel, the two dead parameters it implied, and the
zero-amount branches in both builders.

Note on the reported symptom: this does not change whether a placeholder batch
simulates cleanly. `generateEIP7702BatchTransaction` maps absent calldata to
`'0x'`, so the deposit placeholder encodes empty calls to the token and teller,
and with an atomic batch those revert too. The value here is that the illegal
state becomes unrepresentable, not that a simulation starts passing.

Consumers must guard a zero amount before calling the encoding builders — for a
cleared amount field there is nothing to re-encode.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Jwhiles
Jwhiles added this pull request to the merge queue Aug 3, 2026
Merged via the queue into main with commit 03eb071 Aug 3, 2026
46 checks passed
@Jwhiles
Jwhiles deleted the feat/add-hooks branch August 3, 2026 10:36
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.

2 participants