How to call a payable transaction with abstract accounts (AA)

I am trying to familiarize myself with this new revolution of abstract accounts. I have seen zerodev's tutorial but I want to do my own tests.

I want to mimic a "normal" behavior of EOA account with an AA account.
That is, it pays for what it does.
But I can't get the account pay gas.
Everything is paid by the service.

I guess that's why I can't call a payable function to buy an nft.
To begin with I don't know if it is well implemented like this, introducing the value parameter as in the ethers.js library:

  const { config } = usePrepareContractWrite({
    address: contractAddress,
    abi: contractABI,
    functionName: "safeMint",
    args: [address, {value:"100000000000000000000"}],
    enabled: true
  });

Although I didn't get the above error I didn't manage to call a payable function.

There is an example in the tutorial for making subscriptions with what are called modules:

This is the only place where the AA account pays something.

Should we always create modules for an AA account to pay for a call?

There's a closing curly brace missing here.
Also, that number is larger than Javascript's Number.MAX_SAFE_INTEGER, so you should pass it as a string.

Sorry, I added by hand, hardcoded, that value.
It is now corrected and as you indicated.

Now I will pass you the code I use with the call to the payable function in my test

I also add the abi of the contract:

export const contractABI = [
  'function mint(address buyer) public',
  'function safeMint(address buyer) public payable',
  'function balanceOf(address owner) external view returns (uint256 balance)'
]

Now to reload the page I check in console "Error: cannot estimate gas; transaction may fail or may require manual gas limit".

I don't know if it has to do with the "safeMint" function being a dependency in the useCallback().

  const { config } = usePrepareContractWrite({
    address: contractAddress,
    abi: contractABI,
    functionName: "safeMint",
    args: [address, {value:"100000000000000000000"}],
    enabled: true
  });

 
  const { write: safeMint, isLoading } = useContractWrite(config);

  const { data: balance = 0, refetch } = useContractRead({
    address: contractAddress,
    abi: contractABI,
    functionName: "balanceOf",
    args: [address],
  });

  const interval = useRef<any>()

  const handleClick = useCallback(() => {
    if (safeMint) {
      safeMint();
      interval.current = setInterval(() => {
        refetch()
      }, 1000)
    }
  }, [safeMint, refetch])

I have managed to eliminate this error when loading the page by disabling the automatic execution.


  const { config } = usePrepareContractWrite({
    address: contractAddress,
    abi: contractABI,
    functionName: "safeMint",
    args: [address, {value:"100000000000000000000"}],
    enabled: false // automatic run
  });

I have placed a console log inside the handle and I get undefined. This explains why it does not fire the function.
I don't know why it arrives uninitialized.

  const handleClick = useCallback(() => {
     console.log(`safeMint`, safeMint);
    if (safeMint) {
      safeMint();
      interval.current = setInterval(() => {
        refetch()
      }, 1000)
    }
  }, [safeMint, refetch])

Try this instead:

export const contractABI = [
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "buyer",
                "type": "address"
            }
        ],
        "name": "mint",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "buyer",
                "type": "address"
            }
        ],
        "name": "safeMint",
        "outputs": [],
        "stateMutability": "payable",
        "type": "function"
    },
    {
        "inputs": [
            {
                "internalType": "address",
                "name": "owner",
                "type": "address"
            }
        ],
        "name": "balanceOf",
        "outputs": [
            {
                "internalType": "uint256",
                "name": "balance",
                "type": "uint256"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    }
}

It makes sense to use the typical ABI structure.
But, I tested it with the same result: undefined.

The contractABI variable was configured this way by the sample code in Zerodev's tutorial.

@barakman Where would you set the gas limit?

here?

    args: [address, {value:"100000000000000000000", gasLimit: "100000000"}],

I have executed it but the payment has not been made. In the hash transaction you only see a gas payment transfer. But no transfer for the nft price is seen.

Depends on what package you're using (web3.js, ethers.js, etc).
And possibly even what version of that package you're using.
It is mostly denoted either with gas or with gasLimit.

Zerodev use wagmi and ethers.js

In order to solve my problem I would have to solve the first concern. Can payable functions be used with AA?
Because without knowing that I don't know if I am wasting my time and using the tool incorrectly.