Skip to main content
POST /prepare-transactions returns ethers-style unsigned transactions. They are built to be passed to wallet.signTransaction() and submitted through POST /send-transactions. They are not EIP-1193 payloads. Handing one straight to eth_sendTransaction fails, and the way it fails is misleading.

Why it fails, and why every wallet fails differently

A prepared transaction looks like this:
Four things break an injected provider:
  • nonce, chainId, and type are numbers; EIP-1193 requires hex strings.
  • maxPriorityFeePerGas and maxFeePerGas are decimal strings without a 0x prefix.
  • The gas key is gasLimit; eth_sendTransaction expects gas.
  • from is the wallet the API prepared for, which may not be the account the user connected.
Each wallet validates parameters in its own code, so each one throws a different generic error from inside its own validator — Internal JSON-RPC error, e.startsWith is not a function, undefined is not a function. These errors are not coming from your application, and the differences between them mean nothing. They are all the same malformed payload.

Normalise before sending

Convert the numeric fields to hex, rename gasLimit to gas, and let the wallet supply the nonce and the gas fees itself.
This sends the first transaction only. Some responses carry more than one — see Multi-transaction responses below — so iterate rather than assuming a single entry.
Switch the chain before sending. A wallet pointed at a different network will either reject the call or, worse, prompt the user to sign against the wrong chain.

Report the hash back

eth_sendTransaction broadcasts the transaction itself, so the wallet returns a real transaction hash rather than the txId from the prepare step. Close the loop by telling Brickken which hash corresponds to which prepared transaction, using the client-broadcast execution mode:
Prepare with "executionMode": "client-broadcast" when you intend to broadcast from the wallet, so the prepared transaction is recorded for that mode. See Send Transactions for all three execution modes.

MetaMask error 4100

4100 — The requested account and/or method has not been authorized by the user means from is not an account the user has connected. The transaction must be signed by the wallet that actually holds the asset — the token holder for a transfer, the investor for newInvest and claimTokens, the issuer for issuance operations. If that wallet can differ from the connected one in your application, check them and ask the user to switch rather than letting the wallet reject the request.
If the signing wallet is a Brickken-managed wallet, no injected wallet can sign for it at all, because the browser does not hold its key. Those flows must go through POST /send-transactions with a locally signed transaction instead.

Multi-transaction responses

Some responses contain more than one transaction — approve when an existing allowance has to be reset first, and mintToken when a recipient still needs whitelisting. Prepared transactions carry sequential nonces, so they must be signed and broadcast in order, each one confirmed before the next.
Broadcasting only the second transaction leaves it stranded on a nonce that will never be used, and it silently never mines. If a later call reports a balance or a token that “should” exist, this is usually why.

Send Transactions

Execution modes and submission shapes.

Troubleshooting

Decode a failed call.