Compare commits

..
Author SHA1 Message Date
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
93bcdc557c Version Packages (#8640)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-15 17:26:04 -08:00
Joaquim VergesandGitHub d38deecaa1 Fix getCallStatus via EIP1193 provider (#8639) 2026-01-15 17:20:25 -08:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
a3ea002afd Version Packages (#8638)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-01-14 22:56:41 +07:00
FirekeeperandGitHub 6390052f8b Add fallback for gas fee estimation in zkSync (#8637) 2026-01-14 22:54:24 +07:00
19 changed files with 267 additions and 30 deletions
+16
View File
@@ -1,5 +1,21 @@
# wagmi-inapp
## 0.0.48
### Patch Changes
- Updated dependencies [[`d38deec`](https://github.com/thirdweb-dev/js/commit/d38deecaa1b1990a9af2fad79e2e620e61d4c0e3)]:
- thirdweb@5.117.2
- @thirdweb-dev/wagmi-adapter@0.2.203
## 0.0.47
### Patch Changes
- Updated dependencies [[`6390052`](https://github.com/thirdweb-dev/js/commit/6390052f8bc3b9b7d58d57f8f953c1da9a34066a)]:
- thirdweb@5.117.1
- @thirdweb-dev/wagmi-adapter@0.2.202
## 0.0.46
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "wagmi-inapp",
"private": true,
"version": "0.0.46",
"version": "0.0.48",
"type": "module",
"scripts": {
"dev": "vite",
+11 -4
View File
@@ -1,13 +1,14 @@
import type { ConnectionOptions } from "@thirdweb-dev/wagmi-adapter";
import { ConnectButton } from "thirdweb/react";
import { stringify } from "thirdweb/utils";
import { createWallet } from "thirdweb/wallets";
import {
useAccount,
useCallsStatus,
useConnect,
useDisconnect,
useSendCalls,
useSendTransaction,
useWaitForCallsStatus,
} from "wagmi";
import { chain, client, thirdwebChainForWallet, wallet } from "./wagmi.js";
@@ -28,7 +29,7 @@ function App() {
data: callStatus,
isLoading: isLoadingCallStatus,
error: callStatusError,
} = useCallsStatus({
} = useWaitForCallsStatus({
id: data?.id || "",
query: {
enabled: !!data?.id,
@@ -42,7 +43,7 @@ function App() {
<div>
status: {account.status}
<br />
addresses: {JSON.stringify(account.addresses)}
addresses: {stringify(account.addresses)}
<br />
chainId: {account.chainId}
</div>
@@ -122,6 +123,12 @@ function App() {
calls: [
{
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
data: "0x1234",
value: 0n,
},
{
to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
data: "0x1234",
value: 0n,
},
],
@@ -145,7 +152,7 @@ function App() {
</div>
<div>
{callStatus
? `Success: ${JSON.stringify(callStatus, null, 2)}`
? `Success: ${stringify(callStatus, null, 2)}`
: callStatusError
? callStatusError?.message
: ""}
+14
View File
@@ -1,5 +1,19 @@
# @thirdweb-dev/nebula
## 0.2.106
### Patch Changes
- Updated dependencies [[`d38deec`](https://github.com/thirdweb-dev/js/commit/d38deecaa1b1990a9af2fad79e2e620e61d4c0e3)]:
- thirdweb@5.117.2
## 0.2.105
### Patch Changes
- Updated dependencies [[`6390052`](https://github.com/thirdweb-dev/js/commit/6390052f8bc3b9b7d58d57f8f953c1da9a34066a)]:
- thirdweb@5.117.1
## 0.2.104
### Patch Changes
+1 -1
View File
@@ -57,5 +57,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.2.104"
"version": "0.2.106"
}
+12
View File
@@ -1,5 +1,17 @@
# thirdweb
## 5.117.2
### Patch Changes
- [#8639](https://github.com/thirdweb-dev/js/pull/8639) [`d38deec`](https://github.com/thirdweb-dev/js/commit/d38deecaa1b1990a9af2fad79e2e620e61d4c0e3) Thanks [@joaquim-verges](https://github.com/joaquim-verges)! - Fix getCallStatus via EIP1193 provider
## 5.117.1
### Patch Changes
- [#8637](https://github.com/thirdweb-dev/js/pull/8637) [`6390052`](https://github.com/thirdweb-dev/js/commit/6390052f8bc3b9b7d58d57f8f953c1da9a34066a) Thanks [@0xFirekeeper](https://github.com/0xFirekeeper)! - newer zkos chains no longer support zks\_ rpc endpoints, fallback to evm std
## 5.117.0
### Minor Changes
+1 -1
View File
@@ -430,5 +430,5 @@
}
},
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "5.117.0"
"version": "5.117.2"
}
@@ -194,14 +194,15 @@ export function toProvider(options: ToEip1193ProviderOptions): EIP1193Provider {
if (!account) {
throw new Error("Account not connected");
}
if (!account.getCallsStatus) {
if (!account.getCallsStatusRaw) {
throw new Error("Wallet does not support EIP-5792");
}
return account.getCallsStatus({
const result = await account.getCallsStatusRaw({
id: request.params[0],
chain: chain,
client: client,
});
return result;
}
default:
return rpcClient(request);
@@ -5,9 +5,13 @@ import {
TEST_ACCOUNT_B,
} from "../../../../test/src/test-wallets.js";
import { zkSyncSepolia } from "../../../chains/chain-definitions/zksync-sepolia.js";
import { defineChain } from "../../../chains/utils.js";
import { deployPublishedContract } from "../../../extensions/prebuilts/deploy-published.js";
import { prepareTransaction } from "../../prepare-transaction.js";
import { sendEip712Transaction } from "./send-eip712-transaction.js";
import {
getZkGasFees,
sendEip712Transaction,
} from "./send-eip712-transaction.js";
describe("sendEip712Transaction", () => {
// re-enable for testing, but disable for CI since it requires testnet funds
@@ -52,4 +56,34 @@ describe("sendEip712Transaction", () => {
expect(address).toBeDefined();
expect(address.length).toBe(42);
});
it("should fallback to standard EVM methods when zks_estimateFee is not available", async () => {
// Chain 278701 is a zkSync chain that doesn't support zks_estimateFee
const zkSyncChainWithoutZksSupport = defineChain(278701);
// Use a transaction with pre-defined gas to skip estimation (which requires balance)
// This tests that the fallback path is taken for fee estimation
const transaction = prepareTransaction({
chain: zkSyncChainWithoutZksSupport,
client: TEST_CLIENT,
gas: 21000n, // pre-define gas to skip eth_estimateGas
to: TEST_ACCOUNT_B.address,
value: 0n,
});
const gasFees = await getZkGasFees({
transaction,
from: TEST_ACCOUNT_A.address as `0x${string}`,
});
// Verify fallback worked - should have valid gas values
expect(gasFees.gas).toBeDefined();
expect(gasFees.gas).toBeGreaterThan(0n);
expect(gasFees.maxFeePerGas).toBeDefined();
expect(gasFees.maxFeePerGas).toBeGreaterThan(0n);
expect(gasFees.maxPriorityFeePerGas).toBeDefined();
expect(gasFees.maxPriorityFeePerGas).toBeGreaterThan(0n);
// Fallback should use 100k for gasPerPubdata
expect(gasFees.gasPerPubdata).toBe(100000n);
});
});
@@ -180,25 +180,59 @@ export async function getZkGasFees(args: {
) {
const rpc = getRpcClient(transaction);
const params = await formatTransaction({ from, transaction });
const result = (await rpc({
// biome-ignore lint/suspicious/noExplicitAny: TODO add to RPC method types
method: "zks_estimateFee" as any,
// biome-ignore lint/suspicious/noExplicitAny: TODO add to RPC method types
params: [replaceBigInts(params, toHex)] as any,
})) as {
gas_limit: string;
max_fee_per_gas: string;
max_priority_fee_per_gas: string;
gas_per_pubdata_limit: string;
};
gas = toBigInt(result.gas_limit) * 2n; // overestimating to avoid issues when not accounting for paymaster extra gas ( we should really pass the paymaster input above for better accuracy )
const baseFee = toBigInt(result.max_fee_per_gas);
maxFeePerGas = baseFee * 2n; // bumping the base fee per gas to ensure fast inclusion
maxPriorityFeePerGas = toBigInt(result.max_priority_fee_per_gas) || 1n;
gasPerPubdata = toBigInt(result.gas_per_pubdata_limit) * 2n; // doubling for fast inclusion;
if (gasPerPubdata < 50000n) {
// enforce a minimum gas per pubdata limit
gasPerPubdata = 50000n;
// Try zkSync-specific fee estimation first, fallback to standard EVM methods
try {
const result = (await rpc({
// biome-ignore lint/suspicious/noExplicitAny: TODO add to RPC method types
method: "zks_estimateFee" as any,
// biome-ignore lint/suspicious/noExplicitAny: TODO add to RPC method types
params: [replaceBigInts(params, toHex)] as any,
})) as {
gas_limit: string;
max_fee_per_gas: string;
max_priority_fee_per_gas: string;
gas_per_pubdata_limit: string;
};
gas = toBigInt(result.gas_limit) * 2n; // overestimating to avoid issues when not accounting for paymaster extra gas ( we should really pass the paymaster input above for better accuracy )
const baseFee = toBigInt(result.max_fee_per_gas);
maxFeePerGas = baseFee * 2n; // bumping the base fee per gas to ensure fast inclusion
maxPriorityFeePerGas = toBigInt(result.max_priority_fee_per_gas) || 1n;
gasPerPubdata = toBigInt(result.gas_per_pubdata_limit) * 2n; // doubling for fast inclusion;
if (gasPerPubdata < 50000n) {
// enforce a minimum gas per pubdata limit
gasPerPubdata = 50000n;
}
} catch {
// Fallback to standard EVM methods if zks_estimateFee is not available
const [{ estimateGas }, { getDefaultGasOverrides }] = await Promise.all([
import("../estimate-gas.js"),
import("../../../gas/fee-data.js"),
]);
const [estimatedGas, gasOverrides] = await Promise.all([
gas === undefined
? estimateGas({ transaction, from })
: Promise.resolve(gas),
getDefaultGasOverrides(transaction.client, transaction.chain),
]);
gas = estimatedGas * 2n; // overestimating similar to zkSync estimation
if ("maxFeePerGas" in gasOverrides && gasOverrides.maxFeePerGas) {
maxFeePerGas = gasOverrides.maxFeePerGas * 2n; // bumping for fast inclusion
} else if ("gasPrice" in gasOverrides && gasOverrides.gasPrice) {
maxFeePerGas = gasOverrides.gasPrice * 2n;
}
if (
"maxPriorityFeePerGas" in gasOverrides &&
gasOverrides.maxPriorityFeePerGas
) {
maxPriorityFeePerGas = gasOverrides.maxPriorityFeePerGas;
} else {
maxPriorityFeePerGas = 1n;
}
// Use 100k as default gasPerPubdata for non-zkSync chains
gasPerPubdata = 100000n;
}
}
return {
@@ -326,6 +326,22 @@ function createAccount({
throw error;
}
},
async getCallsStatusRaw(options) {
try {
const rawResponse = (await provider.request({
method: "wallet_getCallsStatus",
params: [options.id],
})) as GetCallsStatusRawResponse;
return rawResponse;
} catch (error) {
if (/unsupport|not support/i.test((error as Error).message)) {
throw new Error(
`${COINBASE} does not support wallet_getCallsStatus, reach out to them directly to request EIP-5792 support.`,
);
}
throw error;
}
},
async getCapabilities(options) {
const chainId = options.chainId;
try {
@@ -10,6 +10,7 @@ import type { Hex } from "../../../../utils/encoding/hex.js";
import { randomBytesHex } from "../../../../utils/random.js";
import type { PreparedSendCall } from "../../../eip5792/send-calls.js";
import type {
GetCallsStatusRawResponse,
GetCallsStatusResponse,
WalletCallReceipt,
} from "../../../eip5792/types.js";
@@ -108,3 +109,52 @@ export async function inAppWalletGetCallsStatus(args: {
version: "2.0.0",
};
}
/**
* @internal
*/
export async function inAppWalletGetCallsStatusRaw(args: {
chain: Chain;
client: ThirdwebClient;
id: string;
}): Promise<GetCallsStatusRawResponse> {
const { chain, client, id } = args;
const bundle = bundlesToTransactions.get(id);
if (!bundle) {
throw new Error("Failed to get calls status, unknown bundle id");
}
const request = getRpcClient({ chain, client });
let status = 200; // BATCH_STATE_CONFIRMED
const receipts: GetCallsStatusRawResponse["receipts"] = [];
for (const hash of bundle) {
try {
const receipt = await eth_getTransactionReceipt(request, { hash });
receipts.push({
blockHash: receipt.blockHash,
blockNumber: `0x${receipt.blockNumber.toString(16)}` as `0x${string}`,
gasUsed: `0x${receipt.gasUsed.toString(16)}` as `0x${string}`,
logs: receipt.logs.map((l) => ({
address: l.address as `0x${string}`,
data: l.data as `0x${string}`,
topics: l.topics as `0x${string}`[],
})),
status: receipt.status === "success" ? "0x1" : "0x0",
transactionHash: receipt.transactionHash as `0x${string}`,
});
} catch {
status = 100; // BATCH_STATE_PENDING
}
}
return {
atomic: false,
chainId: `0x${chain.id.toString(16)}` as `0x${string}`,
id: id as `0x${string}`,
receipts,
status,
version: "2.0.0",
};
}
@@ -351,6 +351,12 @@ export const create7702MinimalAccount = (args: {
);
return inAppWalletGetCallsStatus(options);
},
getCallsStatusRaw: async (options) => {
const { inAppWalletGetCallsStatusRaw } = await import(
"../eip5792/in-app-wallet-calls.js"
);
return inAppWalletGetCallsStatusRaw(options);
},
getCapabilities: async (options) => {
return {
[options.chainId ?? 1]: {
@@ -287,6 +287,12 @@ export class EnclaveWallet implements IWebWallet {
);
return inAppWalletGetCallsStatus(options);
},
getCallsStatusRaw: async (options) => {
const { inAppWalletGetCallsStatusRaw } = await import(
"../eip5792/in-app-wallet-calls.js"
);
return inAppWalletGetCallsStatusRaw(options);
},
getCapabilities: async (options) => {
return {
[options.chainId ?? 1]: {
@@ -373,6 +373,22 @@ function createAccount({
throw error;
}
},
async getCallsStatusRaw(options) {
try {
const rawResponse = (await provider.request({
method: "wallet_getCallsStatus",
params: [options.id],
})) as GetCallsStatusRawResponse;
return rawResponse;
} catch (error) {
if (/unsupport|not support/i.test((error as Error).message)) {
throw new Error(
`${id} does not support wallet_getCallsStatus, reach out to them directly to request EIP-5792 support.`,
);
}
throw error;
}
},
async getCapabilities(options) {
const chainIdFilter = options.chainId;
try {
@@ -19,6 +19,7 @@ import type {
SendCallsResult,
} from "../eip5792/send-calls.js";
import type {
GetCallsStatusRawResponse,
GetCallsStatusResponse,
WalletSendCallsId,
} from "../eip5792/types.js";
@@ -325,6 +326,14 @@ export type Account = {
chain: Chain;
client: ThirdwebClient;
}) => Promise<GetCallsStatusResponse>;
/**
* EIP-5792: Get the raw (unprocessed) status of the given call bundle
*/
getCallsStatusRaw?: (options: {
id: WalletSendCallsId;
chain: Chain;
client: ThirdwebClient;
}) => Promise<GetCallsStatusRawResponse>;
/**
* EIP-5792: Get the capabilities of the wallet
*/
@@ -389,6 +389,12 @@ async function createSmartAccount(
);
return inAppWalletGetCallsStatus(options);
},
getCallsStatusRaw: async (options) => {
const { inAppWalletGetCallsStatusRaw } = await import(
"../in-app/core/eip5792/in-app-wallet-calls.js"
);
return inAppWalletGetCallsStatusRaw(options);
},
getCapabilities: async (options) => {
return {
[options.chainId ?? 1]: {
@@ -567,6 +573,12 @@ function createZkSyncAccount(args: {
);
return inAppWalletGetCallsStatus(options);
},
getCallsStatusRaw: async (options) => {
const { inAppWalletGetCallsStatusRaw } = await import(
"../in-app/core/eip5792/in-app-wallet-calls.js"
);
return inAppWalletGetCallsStatusRaw(options);
},
getCapabilities: async (options) => {
return {
[options.chainId ?? 1]: {
+4
View File
@@ -1,5 +1,9 @@
# @thirdweb-dev/wagmi-adapter
## 0.2.203
## 0.2.202
## 0.2.201
## 0.2.200
+1 -1
View File
@@ -56,5 +56,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.2.201"
"version": "0.2.203"
}