Where does MetaMask get transaction token quantity from?


I have created a new contract on Polygon based on ERC20 and am having a bit of a useability issue with MetaMask (and probably other wallets) when making bespoke transfer transactions.

When I perform a normal transfer() transaction, the signature popup correctly shows the value, in myNewToken, of the transaction plus MATIC gas. BUT if I use my new commissionTransfer() transaction, which, on the contract, sends a portion of the payment to the payee and a portion to "the house" as commission, the signature popup doesn't show the value of the transaction, just the gas fee.

If I sign the transaction it goes through OK, with the right number of tokens going to the right addresses, but I really need the user to be able to have visibility of what they are signing. It shows if I add a "value: amount" to the transaction but that turns the transaction into a MATIC transfer.

const tx = {
        from: userAddress,
        to: contractAddress,
        data: contract.methods.commissionTransfer(payeeAddress, totalTransactionValue).encodeABI()
const sentTx = await web3.eth.sendTransaction(tx)

So. My question is, where does MetaMask get the transaction value it displays from? Is it from the transaction object? Is it from the Transfer event in the contract (so does the fact I have two calls to _transfer() in my transaction cause problems)?

    function commissionTransfer(address recipient, uint256 amount) public virtual returns (bool) {
        address sender = _msgSender();
        uint256 senderBalance = balanceOf(sender);
        require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
        uint256 payAmount = (amount / 1000) * (1000 - commission);
        uint256 comAmount = amount - payAmount;
        _transfer(sender, recipient, payAmount);
        _transfer(sender, minter, comAmount);
        return true;

Thanks in advance for any help.

In case anyone also wants to know this, it seems that MetaMask uses the function signature to determine that it's a transfer(). So the function needs to have a name of "transfer" and accept (address, uint256) arguments. That made it tricky to find an elegant solution for a single contract to run two different ways of performing a transfer() so, in the end, I created a new contract and overrode the transfer() function to call the commissionTransfer function of my token contract.