[BUG] Rabby agent approval fails because EIP-712 chainId is hard-coded to 421614
Update after further debugging
I have some additional findings after investigating both the frontend and backend.
1. Rabby is working correctly
The wallet is connected correctly.
window.ethereum.isRabby
// true
window.ethereum.chainId
// "0xa4b1"
window.ethereum.selectedAddress
// 0xe1...The wallet is on Arbitrum One (42161).
2. The frontend signs using a hard-coded chain
Intercepting the EIP-712 request shows NOFX builds the typed-data with:
{
"domain": {
"chainId": 421614
},
"message": {
"signatureChainId": "0x66eee",
"hyperliquidChain": "Mainnet"
}
}Rabby rejects this because the connected wallet is on Arbitrum One (42161).
3. After patching the wallet request
I monkey-patched the frontend so that the wallet signs using:
domain.chainId = 42161
signatureChainId = 0xa4b1This allows Rabby to display the signing popup.
So the original issue is definitely caused by the frontend constructing the EIP-712 payload with a hard-coded chain.
4. The backend rejects the patched request
Once the wallet signs successfully, the request reaches the backend.
Instead of succeeding, the backend returns:
POST /api/hyperliquid/submit-exchange
400 Bad Request
{
"error": "invalid signatureChainId"
}Looking through the repository shows why.
The backend explicitly validates:
if strings.TrimSpace(fmt.Sprint(action["signatureChainId"])) != "0x66eee" {
return fmt.Errorf("invalid signatureChainId")
}The frontend also hard-codes:
signatureChainId: "0x66eee"in multiple places.
5. This creates a compatibility deadlock
Current behavior:
- Wallet on Arbitrum One → Rabby refuses to sign because the typed-data uses 421614.
- Patch frontend to use the wallet chain → backend rejects the request because it only accepts
0x66eee.
So both the frontend and backend currently assume a fixed signature chain.
6. I don't believe this is a wallet issue
The wallet is functioning normally.
The problem appears to be that NOFX assumes:
signatureChainId = 0x66eeeeverywhere.
This works only if every wallet accepts signing for that domain.
Rabby follows EIP-712 more strictly and requires the signing domain to match the active chain.
Suggested fix
The frontend should obtain the connected wallet chain dynamically:
const chainId = await provider.request({
method: "eth_chainId",
});and sign using that chain.
The backend should validate that the signature is valid rather than requiring:
signatureChainId == "0x66eee"This would make Hyperliquid onboarding compatible with Rabby and other EIP-1193 wallets while preserving Hyperliquid Mainnet operation.
Source: NoFxAiOS/nofx