EIP-1193 Provider
EIP-1193 defines the standard JavaScript interface for Ethereum providers — the window.ethereum API.
Interface
interface EIP1193Provider {
request(args: { method: string; params?: unknown[] }): Promise<unknown>;
on(event: string, listener: (...args: unknown[]) => void): void;
removeListener(event: string, listener: (...args: unknown[]) => void): void;
}
Implemented methods
| Method | Status | Description |
|---|---|---|
eth_requestAccounts | ✅ | Opens Temple via Beacon, returns ['0xAlias'] |
eth_accounts | ✅ | Returns current connected alias |
tez_getAccounts | ✅ | Returns the connected tz1 address (non-standard, Tezos X-specific) |
eth_chainId | ✅ | Returns Tezos X chain ID |
net_version | ✅ | Chain ID as decimal string |
eth_sendTransaction | ✅ | Routes via NAC gateway, returns synthetic hash |
eth_getBalance | ✅ | Balance of the 0x alias |
eth_getTransactionByHash | ✅ | Resolves real kernel tx; scans blocks from send-time snapshot |
eth_getTransactionReceipt | ✅ | Resolves real kernel receipt; null while unresolved |
eth_getTransactionCount | ✅ | Proxied to Tezlink |
eth_call | ✅ | Proxied to Tezlink |
eth_estimateGas / eth_gasPrice / eth_maxPriorityFeePerGas / eth_feeHistory | ✅ | Short-circuited to fixed constants — see Fee model |
wallet_revokePermissions / wallet_disconnect | ✅ | Disconnects the Temple session |
| (any other method) | ✅ | Proxied to the Tezlink EVM node |
eth_sign | ❌ Rejected 4200 | Message signing is not supported |
personal_sign | ❌ Rejected 4200 | Message signing is not supported |
eth_signTypedData / _v3 / _v4 | ❌ Rejected 4200 | EIP-712 signing is not supported |
The five signing methods (eth_sign, personal_sign, eth_signTypedData,
eth_signTypedData_v3, eth_signTypedData_v4) are rejected with EIP-1193
error code 4200 (unsupported method). There is no ECDSA key behind the
0x alias — it is a kernel-computed mapping of a tz1 account — so
EVM-style message signatures cannot be produced by this provider.
Transaction receipts & the synthetic hash
When a dApp calls eth_sendTransaction, the relayer wraps the EVM transaction
into a Michelson runtime operation targeting the NAC gateway
(entrypoint call_evm, or call for a bare transfer).
Temple then asks the user to sign the Tezos operation.
At this point the relayer only has the Michelson runtime operation hash — not the
real EVM transaction hash. The EVM transaction is synthesized by the Tezos X
kernel once the Michelson operation is included in a block, and its hash is computed
as keccak256("CRAC-TX" || block_number_be || crac_id) where crac_id
depends on how many cross-runtime calls appear in the same block. Therefore
the real hash cannot be predicted at signing time.
Workaround: the relayer returns a synthetic hash
(keccak256(michelson_op_hash), see l1OpHashToEvmHash) to the dApp right
after signing, and records the EVM head block number at that moment. When the
dApp later calls eth_getTransactionByHash(syntheticHash) or
eth_getTransactionReceipt(syntheticHash), the resolver:
- Scans EVM blocks from the recorded send-time block up to the current head.
- Picks the matching kernel-synthesized transaction. Candidates whose
fromis the user's alias are preferred, with an exactto/valuemirror of the original request winning over afrom-only match (contract calls routed through the gateway carry the real call in the receipt logs, not the top-level fields). If no sender-side candidate exists, transactions to the alias are considered, but only when their receipt carries a log emitted by the NAC precompile — this covers kernel bookkeeping shapes such as the AliasForwarder. - Caches the real hash on the pending op and proxies the original RPC call
(
eth_getTransactionByHash/eth_getTransactionReceipt) to Tezlink with the real hash, returning the real transaction and receipt — with reallogs,gasUsed, andblockNumber.
Deduplication
Two invariants keep the resolver sane under the polling load ethers.js / viem put on providers:
- Per-hash in-flight promise: concurrent calls for the same synthetic hash share the same block-scan promise instead of each starting a fresh scan.
- Claim set: once a real hash has been claimed by one pending
op, no other pending op can match the same transaction. When a
PendingOpsStoreis injected (as the wallet does), pending ops and claimed hashes are persisted so resolution state survives across provider instances.
Fallback
Each resolution attempt scans for ~30 s (15 retries × 2 s). While the real transaction has not been found:
eth_getTransactionByHashreturns a pending-shaped transaction object (blockNumber: null), as EIP-1474 prescribes for a submitted-but-unmined transaction — so ethers.js / viem pollers keep polling instead of aborting.eth_getTransactionReceiptreturnsnull, the standard answer for a transaction that is not yet mined.resolveSyntheticHash()(the public wallet-facing method) resolves tonullon timeout, letting the caller fall back to the Michelson operation hash.
Example
// Connect
const accounts = await window.ethereum.request({
method: 'eth_requestAccounts'
});
console.log(accounts); // ['0x341af4de...']
// Get chain
const chainId = await window.ethereum.request({ method: 'eth_chainId' });
// Send transaction
const hash = await window.ethereum.request({
method: 'eth_sendTransaction',
params: [{ to: '0x...', value: '0xde0b6b3a7640000' }]
});