Replies: 11 comments
-
Have just stumbled over a similar behavior with wagmi/actions Side note: This is happening with wagmi <1.0 on my side, although the example repo @TateB provided shows that the problem persists in v1.0+ as well. |
Beta Was this translation helpful? Give feedback.
-
Having similar issue. Finding a quick and reasonably elegant fix without modifying code inside import { useState } from "react";
import { Address, parseAbi } from "viem";
import {
useAccount,
useContractEvent,
usePublicClient,
useQuery,
useWaitForTransaction,
} from "wagmi";
const useIsWalletContract = (address: Address | undefined) => {
const publicClient = usePublicClient();
return useQuery(["isWalletContract", address], async () => {
if (!address) {
return undefined;
}
const bytecode = await publicClient.getBytecode({
address,
});
return bytecode !== undefined;
});
};
const useGnosisTransaction = (
...args: Parameters<typeof useWaitForTransaction>
) => {
const publicClient = usePublicClient();
const hash = args[0]?.hash;
return useQuery(
["gnosisTransaction", hash],
async () => {
if (!hash) {
throw new Error("Hash not found");
}
const receipt = await publicClient.getTransactionReceipt({
hash: hash,
});
return receipt;
},
{
...args[0],
enabled: !!hash && args[0]?.enabled !== false,
}
);
};
type useWaitForTransactionWrappedType = (
...args: Parameters<typeof useWaitForTransaction>
) => ReturnType<typeof useWaitForTransaction> & {
txHash: `0x${string}` | undefined;
};
const gnosisAbi = parseAbi([
"event ExecutionSuccess(bytes32 txHash, uint256 payment)",
]);
export const useWaitForTransactionWrapped: useWaitForTransactionWrappedType = (
args
) => {
const { address } = useAccount();
const { data: isWalletContract } = useIsWalletContract(address);
const [gnosisTxHash, setGnosisTxHash] = useState<`0x${string}` | undefined>();
const unwatch = useContractEvent({
abi: gnosisAbi,
address,
eventName: "ExecutionSuccess",
listener: (logs) => {
logs.forEach((log) => {
if (log.args.txHash === args?.hash) {
if (!log.transactionHash) {
throw new Error("Transaction hash not found");
}
setGnosisTxHash(log.transactionHash);
unwatch?.();
}
});
},
});
const plain = useWaitForTransaction({
...args,
hash: isWalletContract === false ? args?.hash : undefined,
});
const gnosis = useGnosisTransaction({
...args,
hash: gnosisTxHash,
});
if (isWalletContract) {
return {
...gnosis,
status:
args?.hash && gnosis.status === "idle" ? "loading" : gnosis.status,
txHash: gnosisTxHash,
};
}
return {
...plain,
txHash: isWalletContract === false ? args?.hash : undefined,
};
}; There are few limitations - for example, the returned status is Hope this helps someone. EDIT: refactored code a bit |
Beta Was this translation helpful? Give feedback.
-
As an alternative (without hooks) one can also make use of import SafeAppsSDK, { TransactionStatus } from "@safe-global/safe-apps-sdk";
...
const transaction = await writeContract(...);
if(!isSafe) {
/** The usual case, outside of a Safe environment */
const receipt = await waitForTransaction({hash: transaction.hash});
}
else {
/** The hash will be a safeHash, which needs to be resolved to an on chain one */
const sdk = new SafeAppsSDK(...);
while (true) {
/** The SDK will be pinged until a txHash is available and the txStatus is in an end-state */
const queued = await sdk.txs.getBySafeTxHash(hash);
if (
queued.txStatus === TransactionStatus.AWAITING_CONFIRMATIONS ||
queued.txStatus === TransactionStatus.AWAITING_EXECUTION
) {
/** Mimic a status watcher by checking once every 5 seconds */
await sleep(5000);
}
else {
/** The txStatus is in an end-state (e.g. success) so we probably have a valid, on chain txHash*/
const receipt = await waitForTransaction({ hash: queued.txHash });
return receipt;
}
}
} |
Beta Was this translation helpful? Give feedback.
-
Would love to see this get fixed in the near future. We have several Safe users that are having difficulty interacting with our app because of this issue. |
Beta Was this translation helpful? Give feedback.
-
I've tried your answer razgraf but it doesn't work for me. |
Beta Was this translation helpful? Give feedback.
-
That's what the I suggest watching how the result of that |
Beta Was this translation helpful? Give feedback.
-
razgraf The hash in getBySafeTxHash(hash) is the transaction value from const transaction = await writeContract(...); ?
|
Beta Was this translation helpful? Give feedback.
-
Can you try with Also, not sure function sleep(ms = 1000): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
} |
Beta Was this translation helpful? Give feedback.
-
razgraf I tried but it's doesn't work. |
Beta Was this translation helpful? Give feedback.
-
Moving to discussion as this isn't the intent of |
Beta Was this translation helpful? Give feedback.
-
Hey, I created a solution and described everything here: https://github.com/Sharqiewicz/wagmi-adapter-safe-wallet |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Is there an existing issue for this?
Package Version
1.0.6
Current Behavior
when using
useWaitForTransaction
, providing a hash from a transaction initiated withSafeConnector
will never return a receipt. this is becauseeth_sendTransaction
through the connector returns asafeTxHash
, which isn't equivalent to the onchain hash.Expected Behavior
not really sure of the best way to implement a solution to this, but there should probably be a way to use
useWaitForTransaction
with a tx hash from safe, and within the returned receipt the onchain tx hash. there should also be a way to know that the tx hash returned fromuseSendTransaction
is a safe tx hash and not an onchain one.Steps To Reproduce
(for use with repro repo)
pnpm build
andpnpm start
(dev doesn't work with safe browser)https://app.safe.global/apps/open?safe=gor:[your-safe-address]&appUrl=http%3A%2F%2Flocalhost%3A3000
Link to Minimal Reproducible Example (StackBlitz, CodeSandbox, GitHub repo etc.)
https://github.com/TateB/wagmi-safe-repro
Anything else?
stackblitz doesn't work properly with the safe browser, which is why the example is a github repo :(
the example includes a hacked together
NewSafeConnector
to help demonstrate the difference between the current returned data and the ideal returned data, it's far from the best way to implement a fix for thisBeta Was this translation helpful? Give feedback.
All reactions