Thank you!
We'll be in touch soon.
Rebel Ants is a gamified NFT dApp where users mint Ant NFTs. Rebel Ants merges digital art with AI-driven storytelling mechanics. In "Battle for the Colony," ants engage in weekly battles within their gang contexts. These battles are narrated and resolved by AI narrative engines, transforming trait-based probabilities into immersive mini-stories for holders.
Owners register their ants for battle. Winning gang members receive rewards based on contribution to their gang's power, blending gaming mechanics with participatory rewards.
Despite supporting over 500 wallet providers via ThirdWeb, Rebel Ants users encountered a critical issue on mobile browsers:
window.ethereum
for all contract interactions (via Web3.js or ethers.js).window.ethereum
is not injected unless using a wallet's in-app browser (like MetaMask Mobile).window.ethereum
Is Not Available on Mobile BrowsersThe window.ethereum
object is injected into the browser environment by wallet extensions like MetaMask-but only on desktop browsers (Chrome, Firefox, Brave) or within the in-app browser of wallet apps (such as MetaMask Mobile).
On standard mobile browsers (e.g., Safari or Chrome), there is no extension to inject window.ethereum
.
As a result, dApp code that relies on this object for contract interactions will fail-because the object simply doesn't exist.
This means that although users can connect wallets using WalletConnect or ThirdWeb, any dApp logic relying on window.ethereum
for transactions will silently break outside of wallet-specific browsers.
We replaced all contract interactions to use ThirdWeb's SDK, which does not depend on window.ethereum
and is fully compatible with WalletConnect and public RPCs.
We refactored battle logic (registration flows, power calculations, and metadata fetches) to use ThirdWeb's getContract
, readContract
, and transaction
hooks.
From this:
const CONTRACTS = {
BattleForColony: {
address: "0xdcE21E84a3DC99E2B0124276E21D4566F8421219",
abi: ColonyABI,
},
};
export const getContractInstance = (contractKey) => {
const contractConfig = CONTRACTS[contractKey];
if (!contractConfig) {
console.error(`Contract configuration for ${contractKey} not found.`);
return null;
}
try {
const web3Instance = getWeb3Instance();
return new web3Instance.eth.Contract(
contractConfig.abi,
contractConfig.address,
);
} catch (error) {
console.error(
`Failed to create contract instance for ${contractKey}:`,
error.message,
);
return null;
}
};
const battleContract = useMemo(() => {
if (!account) return null;
try {
return getContractInstance("BattleForColony");
} catch (error) {
console.error("Failed to get contract:", error);
return null;
}
}, [account]);
const gangPower = await battleContract.methods.gangPower(account.address).call();
To this:
const thirdwebBattleContract = getContract({
client,
chain: apechain,
address: "0xdcE21E84a3DC99E2B0124276E21D4566F8421219",
abi: RebelAntsABI,
});
const gangPower = await readContract({
contract: thirdwebBattleContract,
method: "gangPower",
params: [account.address],
});
window.ethereum
.window.ethereum
if you want consistent behavior across desktop and mobile browsers.Werner Petrick
Software Engineer
Werner is a tenacious problem solver at puzzl with a knack for creative solutions and clear communication. He picks up new concepts quickly, documents his findings thoroughly, and thrives on tackling fresh challenges. Always eager to contribute, Werner is a driving force behind some of puzzl's most innovative initiatives.
Rebel Ants NFT
Battle of the Colony - NFT Game
rebelants.io ↗“When puzzl built the portal, they delivered exactly like they always do, fast, reliable, and with a level of professionalism that is hard to find. They show up when it matters, handle pressure with calm, and always gets the job done right.”
How we chose between SQL and NoSQL for a multi-brand marketplace.
Improving smart contract event log fetching and backend services.
We'll be in touch soon.