Skip to content

Three example/doc gaps found testing Base Account SDK v2.5.7 (dataCallback shape, prolink missing 'from', send_calls gas note) #1730

Description

@Kajko25

Found while building an agent (Kokosh) that exercises Base Account SDK v2.5.7 and Base MCP end-to-end on mainnet. Three separate example/documentation gaps, all reproduced live and cross-checked against the currently live base/docs content (not just a cached copy) before filing.

1. base-account/reference/core/capabilities/datacallback — callback payload shape doesn't match the live request body

The reference page's example (and the "Example Implementation" callback handler) reads:

const { requestedInfo } = requestData.capabilities.dataCallback;

The actual POST body Base sends to the callbackURL has requestedInfo as a top-level field, sibling to calls/capabilities/chainId — there is no requestData.capabilities.dataCallback.requestedInfo nesting.

Diagnosed by logging the raw request body in production after every live attempt using the documented shape returned 400 (Coinbase's own backend, api.wallet.coinbase.com/rpc/v3/scw/submitDataCallbackUpdate, rejected the echoed response built from the wrong shape). Once the handler was changed to read requestData.requestedInfo directly, a real $0.05 USDC Base Pay payment with payerInfo settled correctly in production.

2. base-account/reference/prolink-utilities/decodeProlink — "Validate Before Execution" example is missing from

The example executes the decoded request directly:

const result = await provider.request({
  method: decoded.method,
  params: decoded.params
});

For a wallet_sendCalls prolink that was encoded as a payment request (the common case — the encoder doesn't know who will open the link, so it has no from), this throws "The requested account and/or method has not been authorized by the user." The example needs an extra line connecting first and injecting the connected address into params[0].from before executing, e.g.:

const { accounts } = await provider.request({ method: 'wallet_connect', params: [{ version: '1' }] });
const sendParams = [{ ...decoded.params[0], from: accounts[0].address }];
const result = await provider.request({ method: decoded.method, params: sendParams });

Reproduced live: the unmodified example throws the unauthorized error on mainnet against a real payment-request prolink; adding the from injection fixes it and the transaction settles.

3. agents/guides/batch-calls — no mention that send_calls may need native gas, unlike other Base MCP/Base Account flows

Nothing on this page (or elsewhere I could find under agents/) notes that send_calls transactions may require the Base Account to hold native ETH for gas. This is easy to miss because other flows against the same Base Account — Base Pay's pay(), and a wallet_sendCalls executed directly via a first-party SDK popup — settle gaslessly (sponsored), while a send_calls submitted through Base MCP against a zero-ETH smart account failed with an insufficient-funds error until the account was funded with a small amount of ETH.

Worth a short caveat on this page (or wherever gas sponsorship for Base MCP write tools is centrally documented) noting that gas sponsorship is not guaranteed for every path that can produce a wallet_sendCalls-shaped transaction, so agents/users may need to fund the Base Account with native gas before using send_calls even if other flows against the same account have been gasless.


All three were hit while building https://github.com/Kajko25/kokosh (JOURNAL.md has the full reproduction detail with tx hashes) and while updating base/skills#148.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions