<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chinyere John-Nnah</title>
    <description>The latest articles on DEV Community by Chinyere John-Nnah (@neraa).</description>
    <link>https://dev.to/neraa</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3883959%2Fc4575041-65f3-4192-82cb-0c6c81207030.jpg</url>
      <title>DEV Community: Chinyere John-Nnah</title>
      <link>https://dev.to/neraa</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/neraa"/>
    <language>en</language>
    <item>
      <title>From Chatbots to Coworkers: What Google Cloud Next '26 Means for Developers</title>
      <dc:creator>Chinyere John-Nnah</dc:creator>
      <pubDate>Mon, 27 Apr 2026 09:14:39 +0000</pubDate>
      <link>https://dev.to/neraa/from-chatbots-to-coworkers-what-google-cloud-next-26-means-for-developers-2lnf</link>
      <guid>https://dev.to/neraa/from-chatbots-to-coworkers-what-google-cloud-next-26-means-for-developers-2lnf</guid>
      <description>&lt;p&gt;&lt;em&gt;A developer's breakdown of everything that matters from the Google Cloud Next '26 keynote and what to build with it next.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-cloud-next-2026-04-22"&gt;Google Cloud NEXT Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For the last two years, every AI keynote has felt like a magic show "look at this thing that can write a poem." &lt;/p&gt;

&lt;p&gt;Google Cloud Next '26 was different. &lt;/p&gt;

&lt;p&gt;The magic show is over. &lt;/p&gt;

&lt;p&gt;The actual machinery is here.&lt;/p&gt;

&lt;p&gt;Thomas Kurian and Sundar Pichai opened the keynote with a single, quietly disruptive idea: we're done with chatbots that talk. The new era is about agents that do: systems with persistent reasoning and autonomous execution that can hold context for days, plan multi-step workflows, and verify their own work. &lt;/p&gt;

&lt;p&gt;2024 and 2025 asked, "Can we build an agent?", 2026 asks, "How do we manage thousands of them?"&lt;br&gt;
For developers especially those of us building at the intersection of frontend, data, and distributed systems this is the most consequential Next in years. Here's what actually shipped, what it means, and where to start.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Agentic Enterprise Blueprint
&lt;/h2&gt;

&lt;p&gt;Kurian framed the entire conference around one concept: &lt;strong&gt;The Agentic Enterprise&lt;/strong&gt;. The pitch is that the org chart of the future doesn't just have humans it has digital teammates working alongside them, and every employee becomes a builder who orchestrates a swarm of agents instead of executing tasks manually.&lt;/p&gt;

&lt;p&gt;The strategy rests on two ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Persistent reasoning&lt;/strong&gt;: Unlike a chatbot that forgets you the moment you close the tab, agents maintain state across days. They can pause, wait for an external trigger, resume, and finish the job like a human colleague would.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Owning the full stack:&lt;/strong&gt; Custom silicon (TPUs), the data layer (BigQuery), and the UX (Workspace) all built to work together. Kurian's not-so-subtle jab at competitors: they "hand you the pieces, not the platform."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you buy that framing or not, the takeaway is clear Google is betting that vertically integrated infrastructure wins the agent era. And the rest of the keynote was them showing receipts.&lt;/p&gt;




&lt;h2&gt;
  
  
  Gemini Enterprise Agent Platform (The Vertex AI Rebrand)
&lt;/h2&gt;

&lt;p&gt;The biggest rebrand of the event: &lt;strong&gt;Vertex AI&lt;/strong&gt; is now the &lt;strong&gt;Gemini Enterprise Agent Platform.&lt;/strong&gt; It's no longer a model garden it's a unified environment for the entire agent lifecycle, from prototype to production to post-deployment monitoring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ygoiwx6ox5h0tgeg269.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ygoiwx6ox5h0tgeg269.png" alt="Architecture diagram of the Gemini Enterprise Agent Platform" width="800" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The core features that make up the platform:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Studio:&lt;/strong&gt; A low-code, visual builder inside Workspace. Defines agent goals in natural language, wire up tools, and ship.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Development Kit (ADK) v1.0&lt;/strong&gt;: The pro-code framework for the rest of us. Supports Python, JavaScript, Java, and Go, and lets you build graph-based agent networks (think LangGraph, but native).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Identity:&lt;/strong&gt; Every agent gets a unique cryptographic ID. Every action it takes is auditable. This is huge for compliance finally, a real answer to "Which agent did that, and why?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Gateway:&lt;/strong&gt; Air traffic control for your agent fleet. Enforces policy, manages traffic, and uses Model Armor to block prompt injection attacks at the edge.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A2A (Agent-to-Agent) Protocol&lt;/strong&gt;: A standardized handshake that lets a Google-based agent securely delegate tasks to a Salesforce or SAP agent. Cross-vendor interoperability, finally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Runtime:&lt;/strong&gt; A re-engineered execution environment built for long-running agents. Your agent can fire off a task, wait three days for an external API to respond, and pick up exactly where it left off.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Simulation &amp;amp; Evaluation:&lt;/strong&gt; Stress-test your agent against thousands of simulated user interactions before it ever sees production. Catches logic drift before your users do.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Actually Shipping
&lt;/h2&gt;

&lt;p&gt;If Day 1 sold the strategy, Day 2 showed the developer loop underneath it. The framing: build an agent system that plans a marathon for 10,000 runners through the Las Vegas Strip, using three agents — a planner (generates routes), an evaluator (scores them against constraints), and a simulator (runs the route end-to-end). The entire codebase and every demo were open-sourced as a GitHub repo plus Codelabs. The platform was anchored around four pillars and each pillar got its own demo segment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🛠️ Build&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ADK (Agent Development Kit)&lt;/strong&gt;: the code-first framework, supporting Python, JavaScript, Java, and Go, with a new graph-based runtime for defining how agents collaborate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Studio&lt;/strong&gt;: the low-code counterpart. Define agent goals in natural language, wire up tools, publish.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managed MCP&lt;/strong&gt;: Google now hosts the Model Context Protocol layer, eliminating a week of self-hosting plumbing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Registry&lt;/strong&gt;: described as "the DNS of your internet of agents." Auto-indexes every agent deployed to Agent Runtime, making them discoverable and governable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Marketplace&lt;/strong&gt;: third-party agents from Atlassian, Box, Lovable, Oracle, ServiceNow, Workday, and more, deployable directly from Gemini Enterprise.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model Garden&lt;/strong&gt;: explicitly supports Claude, Gemini 3.1 Pro, Gemini 3.1 Flash, and others. Pick your model, swap when needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📈 Scale&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Serverless Agent Runtime&lt;/strong&gt;: handles long-running state across days. Agents pause, wait for an external trigger, and resume without losing context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A2A (Agent-to-Agent) Protocol&lt;/strong&gt;: the cross-vendor handshake. Created by Google, donated to the Linux Foundation. A Google agent can hand work to a Salesforce or SAP agent without brittle API code.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A2UI (Agent-to-User Interface)&lt;/strong&gt;: an open standard letting agents generate dynamic UI components instead of returning plain text. The marathon simulator's UI (Angular + 3D rendering of the Las Vegas Strip) was assembled live by the agent itself, not hardcoded.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The evaluation layer is now first-class. A separate model as a judge scores outputs across deterministic criteria (a marathon is exactly 26 miles 385 yards / 42.195 km) and non-deterministic ones (community impact, route quality). Agents auto-generate their evaluation UIs from the schema of their own outputs the path from "fragile, unpredictable agentic loops" to "a rigorously evaluated network of experts."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔒 Govern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The framing here was sharp: stop telling developers to "shift left" (own everything earlier) and start letting them "shift down" push the responsibility into the platform layer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Identity&lt;/strong&gt;: every agent gets a unique, immutable cryptographic credential. Every action is auditable back to a specific agent instance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Gateway&lt;/strong&gt;: air traffic control for the agent fleet. Understands MCP and A2A protocols. Uses IAM policies to scope which sources can invoke agent actions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Agent Policies&lt;/strong&gt;: configurable guardrails. An agent permitted to read from BigQuery but blocked from triggering spend over a threshold.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Model Armor&lt;/strong&gt;: inline protection against prompt injection, tool poisoning, and sensitive data leakage at the gateway layer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚙️ Optimize&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The end-to-end debugging story for when an agent breaks in production:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent Runtime trace view&lt;/strong&gt;: surfaces exactly where the reasoning chain or tool call failed.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gemini Cloud Assist Investigation&lt;/strong&gt;: takes a natural-language query and explores logs and events to surface the failing component down to a specific line.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Antigravity IDE&lt;/strong&gt;: powered by Gemini 3, connected via MCP. Proposes parameter-level remediations. In the demo: a missing token_threshold on the event-compaction config that was silently truncating the agent's working memory.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wiz Green Agent inside Claude Code with Opus&lt;/strong&gt;: Wiz now scans both agent code and infrastructure, and the same remediation surface runs inside Anthropic's IDE on Anthropic's model. An explicit multi-vendor signal: security tooling travels with the developer, regardless of stack.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What it means for you&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Day 1 sold the agentic enterprise. Day 2 laid out the loop you'll actually live in: build → scale → govern → optimize. Three things to actually act on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The evaluation layer is the part most teams will sleep on and regret. Judge models, deterministic + non-deterministic checks, auto-generated eval UIs: this is where agentic systems silently fail today, and it's now baked in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A2A and A2UI are open standards, not Google-only. The Linux Foundation handoff matters. Don't dismiss them as vendor lock-in.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Antigravity is the bet to watch. It's Google's claim on what "agentic developer experience" means in 2026 and the multi-vendor Wiz/Claude Code integration shows the surface area is intentionally portable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The AI Hypercomputer: 8th-Gen TPUs
&lt;/h2&gt;

&lt;p&gt;To run millions of persistent agents in production, you need silicon designed for the workload. Google's answer is the 8th-generation TPU and crucially, it's a dual-chip strategy that splits training and inference into purpose-built hardware. This is Google explicitly attacking the "memory wall" that's been bottlenecking large models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvi2iipcjlrqau26lrlqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvi2iipcjlrqau26lrlqq.png" alt="TPUs comparison with the previous" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What it means for you:&lt;/strong&gt; Cloud developers now have a dedicated inference engine in the TPU 8i. The economics of running a complex, multi-turn agent for every single user in your app just got real. The "one agent per user" pattern was a fantasy in 2024 at these unit costs, it becomes a default architecture.&lt;/p&gt;




&lt;h2&gt;
  
  
  Agentic Data Cloud: From Passive Storage to System of Action
&lt;/h2&gt;

&lt;p&gt;"Reasoning without context is just a guess" that's how Karthik Narain, Google Cloud's Chief Product and Business Officer, framed the thesis behind the Agentic Data Cloud, which reimagines data as something agents act on, not just query.&lt;/p&gt;

&lt;p&gt;Three pieces matter most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Knowledge Catalog&lt;/strong&gt;: Replaces traditional metadata catalogs. It auto-maps the business meaning of data across your entire estate (Google Docs, Slack, SQL warehouses, the lot). Your agents now understand that "ARR" in finance means the same thing as "Annual Recurring Revenue" in your CRM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Memory Bank:&lt;/strong&gt; Long-term memory for agents. Where chat sessions used to forget you in five minutes, Memory Bank persists user preferences and project history across months of interaction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managed MCP:&lt;/strong&gt; You no longer host your own Model Context Protocol servers. Google now manages the connective tissue between Gemini and your databases, which kills a whole class of plumbing work.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Agentic Defense: The Wiz Integration Goes Live
&lt;/h2&gt;

&lt;p&gt;With the $32 billion Wiz acquisition fully closed, Google rolled out a "Cyberforce" of defensive agents. The pitch: stop reacting to alerts, start hunting threats autonomously.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Threat Hunting Agent:&lt;/strong&gt; Proactively scans for novel attack patterns that signature-based firewalls miss.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Detection Engineering Agent&lt;/strong&gt;: Writes and deploys new security rules in real time as threats evolve. The rule that catches tomorrow's attack didn't exist yesterday.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wiz "Red Agent"&lt;/strong&gt;: An autonomous penetration tester that constantly probes your cloud infrastructure for unlocked doors before real attackers find them.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Agentic Taskforce: Companies Already Shipping&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0w9hujnn4m5xd4dl3pky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0w9hujnn4m5xd4dl3pky.png" alt="Grid of 10 enterprise companies using Gemini agents in production" width="800" height="733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The keynote closed with proof points companies actually getting ROI from agents in production right now. The pattern across all of them: agents handling the long-tail repetitive work, humans focusing on judgment calls. A few standouts worth zooming in on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;KPMG's Tax Swarms&lt;/strong&gt; are the clearest A2A protocol use case in the wild; their tax agent talks directly to a client's audit agent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Virgin Voyages&lt;/strong&gt; going from 6-hour rebookings to 11 minutes is the clearest "Agent Runtime + long-running state" example.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Goldman Sachs&lt;/strong&gt; querying 10,000+ page filings in minutes is what the Knowledge Catalog actually unlocks at enterprise scale.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Walmart and Bosch&lt;/strong&gt; prove agents work at the edge — store floors and factory floors, not just data centers.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;So What Should You Actually Do With This?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you take one thing from Next '26, take this: the agent era isn't a future bet, it's a current one. The infrastructure is shipping, the protocols are standardizing, and Fortune 500s are already in production.&lt;/p&gt;

&lt;p&gt;Concretely, here's where to start depending on your stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Frontend devs&lt;/strong&gt;: Play with Agent Studio. The low-code builder is the fastest way to feel what an agentic UX is even supposed to look like.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Backend / data folks&lt;/strong&gt;: The Knowledge Catalog and Memory Bank are the most underrated announcements. Try wiring an agent to your own data with Managed MCP and skip a month of plumbing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Infra / platform engineers&lt;/strong&gt;: Watch the TPU 8i pricing closely. The economics of "an agent per user" change your architecture decisions for the next two years.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Security teams&lt;/strong&gt;: Don't wait. Threat Hunting and Red Agent are the kind of tools your blue team will quietly start depending on by Q3.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The chatbot era taught us how to prompt. The agent era is going to teach us how to delegate. The developers who figure that out first are going to look like wizards by the end of 2026.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you watched the keynote too, what stood out for you? Drop a comment especially if you've started prototyping with the ADK. I'm curious what's actually working vs. what's still demo-ware.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>cloudnextchallenge</category>
      <category>googlecloud</category>
      <category>agents</category>
    </item>
    <item>
      <title>I Automated 90% of The Ethers.js v5 v6 Migration using Codemods and AI</title>
      <dc:creator>Chinyere John-Nnah</dc:creator>
      <pubDate>Sat, 18 Apr 2026 13:29:53 +0000</pubDate>
      <link>https://dev.to/neraa/i-automated-90-of-the-ethersjs-v5-v6-migration-using-codemods-and-ai-22n6</link>
      <guid>https://dev.to/neraa/i-automated-90-of-the-ethersjs-v5-v6-migration-using-codemods-and-ai-22n6</guid>
      <description>&lt;p&gt;Ethers v6 dropped a breaking change on every project that touched BigNumber, utils, or providers — which is basically every DeFi frontend ever written. The migration guide listed over 40 breaking changes. Some were simple renames. Some required understanding whether a variable was a BigNumber before deciding what to do with it. Doing this by hand across 31 files is exactly the kind of work that makes engineers quit. I built a codemod pipeline to handle the mechanical ones automatically — and wrote AI prompts for the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ethers v5 → v6 is painful
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;BigNumber is gone.&lt;/strong&gt; In v5, every numeric value coming off a contract was a &lt;code&gt;BigNumber&lt;/code&gt; instance with its own method API: &lt;code&gt;.add()&lt;/code&gt;, &lt;code&gt;.mul()&lt;/code&gt;, &lt;code&gt;.toNumber()&lt;/code&gt;, &lt;code&gt;.toHexString()&lt;/code&gt;. In v6, native JavaScript &lt;code&gt;bigint&lt;/code&gt; takes over. That's a good change long-term, but it means every arithmetic expression, every comparison, every conversion in your codebase needs to change — and if you mix a &lt;code&gt;bigint&lt;/code&gt; with a &lt;code&gt;number&lt;/code&gt; by accident, you get a runtime &lt;code&gt;TypeError&lt;/code&gt; with no static warning unless you're fully strict about types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The entire &lt;code&gt;ethers.utils&lt;/code&gt; namespace was flattened.&lt;/strong&gt; In v5, utility functions lived under &lt;code&gt;ethers.utils&lt;/code&gt;: &lt;code&gt;ethers.utils.parseEther&lt;/code&gt;, &lt;code&gt;ethers.utils.keccak256&lt;/code&gt;, &lt;code&gt;ethers.utils.arrayify&lt;/code&gt;. In v6, they're all top-level on the &lt;code&gt;ethers&lt;/code&gt; object. That's 15+ functions to find and rename across your codebase, and three of them got renamed too: &lt;code&gt;arrayify&lt;/code&gt; became &lt;code&gt;getBytes&lt;/code&gt;, &lt;code&gt;hexZeroPad&lt;/code&gt; became &lt;code&gt;zeroPadValue&lt;/code&gt;, and &lt;code&gt;splitSignature&lt;/code&gt; became &lt;code&gt;Signature.from()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Providers moved and Web3Provider is gone.&lt;/strong&gt; The entire &lt;code&gt;ethers.providers&lt;/code&gt; sub-namespace was dissolved. &lt;code&gt;new ethers.providers.JsonRpcProvider(url)&lt;/code&gt; is now &lt;code&gt;new ethers.JsonRpcProvider(url)&lt;/code&gt;. &lt;code&gt;new ethers.providers.Web3Provider(window.ethereum)&lt;/code&gt; — the line in basically every frontend DeFi app — is now &lt;code&gt;new ethers.BrowserProvider(window.ethereum)&lt;/code&gt;. &lt;code&gt;StaticJsonRpcProvider&lt;/code&gt; was merged into &lt;code&gt;JsonRpcProvider&lt;/code&gt;. If you have TypeScript type annotations using &lt;code&gt;ethers.providers.X&lt;/code&gt;, those need to change too.&lt;/p&gt;

&lt;h2&gt;
  
  
  My approach: codemods + AI
&lt;/h2&gt;

&lt;p&gt;The insight that made this tractable is recognizing that these changes fall into two completely different categories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mechanical renames&lt;/strong&gt; have one right answer. &lt;code&gt;ethers.utils.parseEther&lt;/code&gt; always becomes &lt;code&gt;ethers.parseEther&lt;/code&gt;. &lt;code&gt;new ethers.providers.Web3Provider(x)&lt;/code&gt; always becomes &lt;code&gt;new ethers.BrowserProvider(x)&lt;/code&gt;. These changes are safe to automate because the transformation is deterministic — given the same input, there's only one correct output. A codemod handles these at AST level: it parses the source into a syntax tree, finds the exact nodes to change, replaces them, and prints the result with formatting preserved. No regex, no string munging, no accidental replacements inside comments or string literals.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Semantic changes&lt;/strong&gt; require context. When you see &lt;code&gt;someVar.toNumber()&lt;/code&gt;, the right migration depends on where &lt;code&gt;someVar&lt;/code&gt; came from. If it's the direct result of &lt;code&gt;BigNumber.from(x)&lt;/code&gt;, you can mechanically replace it with &lt;code&gt;Number(BigInt(x))&lt;/code&gt;. But if it came from a contract call two scopes away, you need to understand the data flow, check whether the value could exceed &lt;code&gt;Number.MAX_SAFE_INTEGER&lt;/code&gt;, and decide whether &lt;code&gt;Number()&lt;/code&gt;, &lt;code&gt;parseInt()&lt;/code&gt;, or staying with &lt;code&gt;bigint&lt;/code&gt; is right. No static tool makes that call correctly 100% of the time. AI does, given enough context.&lt;/p&gt;

&lt;p&gt;The combination is the only approach that scales. Codemods alone leave the semantic cases as silent bugs. AI alone on a 31-file codebase is slow and expensive. Together, you get deterministic correctness where it's possible and targeted AI review where it's necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 8 transforms I built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;rename-utils&lt;/strong&gt; — Lifts all 17 &lt;code&gt;ethers.utils.*&lt;/code&gt; functions to the top-level namespace. Handles both &lt;code&gt;import * as ethers&lt;/code&gt; and &lt;code&gt;import { utils }&lt;/code&gt; styles, rewrites the import declaration, and covers the two structural changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arrayify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hexString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseEther&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bytes&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hexString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;bigNumber-to-bigint&lt;/strong&gt; — Replaces &lt;code&gt;BigNumber.from(x)&lt;/code&gt; with &lt;code&gt;BigInt(x)&lt;/code&gt; and rewrites instance methods on statically-confirmed BigNumber variables to native operators. Uses a conservative two-phase approach: method rewrites run first to handle chains like &lt;code&gt;BigNumber.from(x).toNumber()&lt;/code&gt; atomically, then standalone &lt;code&gt;BigNumber.from()&lt;/code&gt; nodes are replaced.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;BigNumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fee&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BigNumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1000000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fee&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rename-providers&lt;/strong&gt; — Renames all 7 provider classes and updates TypeScript type annotations. &lt;code&gt;StaticJsonRpcProvider&lt;/code&gt; merges into &lt;code&gt;JsonRpcProvider&lt;/code&gt;. Handles destructured &lt;code&gt;import { providers }&lt;/code&gt; by injecting the specific v6 names that were actually used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Web3Provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JsonRpcProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;BrowserProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JsonRpcProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;gasPrice-to-feeData&lt;/strong&gt; — Rewrites &lt;code&gt;await provider.getGasPrice()&lt;/code&gt; by replacing the entire &lt;code&gt;AwaitExpression&lt;/code&gt; node. This means the parentheses around the await are handled automatically by recast's printer based on operator precedence — I don't insert them manually.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gasPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getGasPrice&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gasPrice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFeeData&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nx"&gt;gasPrice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rename-constants&lt;/strong&gt; — Replaces all &lt;code&gt;ethers.constants.*&lt;/code&gt; accesses with their v6 equivalents. Named constants become top-level properties (&lt;code&gt;AddressZero → ZeroAddress&lt;/code&gt;, &lt;code&gt;MaxUint256 → MaxUint256&lt;/code&gt;). The four numeric constants become native bigint literals since BigNumber is gone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AddressZero&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MaxUint256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;One&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ZeroAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;max&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MaxUint256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;one&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rename-contract-methods&lt;/strong&gt; — Rewrites the four v5 contract method bucket patterns. In v5, less-common operations were accessed via intermediate buckets (&lt;code&gt;callStatic&lt;/code&gt;, &lt;code&gt;estimateGas&lt;/code&gt;, &lt;code&gt;populateTransaction&lt;/code&gt;, &lt;code&gt;functions&lt;/code&gt;). In v6 they moved to direct methods on the contract function itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;callStatic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gas&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;estimateGas&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balanceOf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;staticCall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;addr&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gas&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transfer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;estimateGas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;rename-provider-methods&lt;/strong&gt; — Handles three provider/transaction method changes. &lt;code&gt;sendTransaction&lt;/code&gt; was renamed on the Provider side to &lt;code&gt;broadcastTransaction&lt;/code&gt; (Signer's &lt;code&gt;sendTransaction&lt;/code&gt; is unchanged — the transform adds a TODO so you can verify which one it is). &lt;code&gt;parseTransaction&lt;/code&gt; and &lt;code&gt;serializeTransaction&lt;/code&gt; became &lt;code&gt;Transaction.from()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedTx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parseTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// after (with TODO comment added for sendTransaction)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;broadcastTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;signedTx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;update-imports&lt;/strong&gt; — Runs last. Removes deprecated specifiers (&lt;code&gt;utils&lt;/code&gt;, &lt;code&gt;BigNumber&lt;/code&gt;, &lt;code&gt;providers&lt;/code&gt;, &lt;code&gt;constants&lt;/code&gt;) from &lt;code&gt;import { ... } from 'ethers'&lt;/code&gt; declarations once the other transforms have finished introducing their replacements. If no specifiers remain, it removes the entire import statement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// before&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;BigNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// after&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Contract&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ethers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Does it actually work on real code?
&lt;/h2&gt;

&lt;p&gt;I ran the pipeline against &lt;a href="https://github.com/Uniswap/v3-periphery" rel="noopener noreferrer"&gt;Uniswap/v3-periphery&lt;/a&gt;, which is on ethers &lt;code&gt;^5.0.8&lt;/code&gt; — a production-grade codebase I had no hand in writing.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Files scanned&lt;/td&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Files automatically migrated&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lines changed&lt;/td&gt;
&lt;td&gt;502 lines (231 insertions, 271 deletions)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Files flagged for AI review&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Automated coverage&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;90.3%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;False positives&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I verified every change with &lt;code&gt;git diff&lt;/code&gt; before counting. The 0 false positives claim I validated separately: running the same pipeline against scaffold-eth-2 (already on ethers v6) produced 0 changes and 0 TODOs.&lt;/p&gt;

&lt;p&gt;One honest limitation: the codemod only tracks direct imports from &lt;code&gt;'ethers'&lt;/code&gt;. If your project wraps ethers behind an internal utility library or re-exports it from an index file, the transforms won't fire. I decided false negatives (missed cases) are safer than false positives (broken code), so the conservative approach was the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the AI handles
&lt;/h2&gt;

&lt;p&gt;The 3 flagged files — &lt;code&gt;PairFlash.spec.ts&lt;/code&gt;, &lt;code&gt;snapshotGasCost.ts&lt;/code&gt;, &lt;code&gt;TickLens.spec.ts&lt;/code&gt; — all had the same pattern: BigNumber method calls on variables that came from contract return values or function parameters. The codemod added a comment to each one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TODO(ethers-codemod): verify this BigNumber method call and migrate manually&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;returnedFromContract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For these, I used this prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;I&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;m migrating from ethers.js v5 to v6. In v6, BigNumber is replaced by native bigint.
The codemod flagged this code because it couldn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="nx"&gt;statically&lt;/span&gt; &lt;span class="nx"&gt;confirm&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;receiver&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;
&lt;span class="nx"&gt;BigNumber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nx"&gt;Please&lt;/span&gt; &lt;span class="nx"&gt;help&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt; &lt;span class="nx"&gt;migrate&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;paste&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;flagged&lt;/span&gt; &lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="nx"&gt;block&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nx"&gt;Key&lt;/span&gt; &lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt; &lt;span class="nx"&gt;fits&lt;/span&gt; &lt;span class="nx"&gt;safely&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;JS&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toHexString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;x  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;both&lt;/span&gt; &lt;span class="nx"&gt;sides&lt;/span&gt; &lt;span class="nx"&gt;must&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="nx"&gt;check&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;also&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;Values&lt;/span&gt; &lt;span class="nx"&gt;returned&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="nx"&gt;calls&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;already&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;ethers&lt;/span&gt; &lt;span class="nx"&gt;v6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;no&lt;/span&gt; &lt;span class="nx"&gt;conversion&lt;/span&gt; &lt;span class="nx"&gt;needed&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;If&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="nx"&gt;could&lt;/span&gt; &lt;span class="nx"&gt;exceed&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_SAFE_INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;keep&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three files, one prompt each, done in under ten minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How to use it right now&lt;/strong&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx ts-node src/run.ts ./your-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The runner finds all &lt;code&gt;.ts&lt;/code&gt;, &lt;code&gt;.tsx&lt;/code&gt;, &lt;code&gt;.js&lt;/code&gt;, &lt;code&gt;.jsx&lt;/code&gt; files, skips anything with no ethers imports, runs all 5 transforms in the correct order, and prints a summary with per-transform change counts and a list of any files that need AI review.&lt;/p&gt;

&lt;p&gt;Source and full documentation: &lt;strong&gt;&lt;a href="https://github.com/Chinyereee/ethers-v5-to-v6-codemod" rel="noopener noreferrer"&gt;https://github.com/Chinyereee/ethers-v5-to-v6-codemod&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;28 files migrated automatically. 502 lines changed with zero false positives. 3 files handed off to AI with precise, targeted prompts. Total time to run: under 30 seconds.&lt;/p&gt;

&lt;p&gt;This is what software maintenance should look like. Mechanical changes — the ones with one right answer — get automated at the AST level, fast and correct. Human judgment gets reserved for the semantic changes that actually need it: the data flow questions, the precision questions, the "what did the original author intend" questions that no static tool can answer reliably. The codemod tells you exactly which files those are and why. The AI handles them in minutes.&lt;/p&gt;

&lt;p&gt;The weekend you were dreading becomes an afternoon. Most of it spent verifying a diff, not writing one.&lt;/p&gt;

&lt;p&gt;A note on the test repo choice: I tried scaffold-eth-2 first. It was already on v6 — which was actually useful, it confirmed the codemod produces zero changes on modern code. But I needed a real v5 target. Uniswap v3-periphery is widely known, actively maintained, and represents how real protocols actually use ethers. It felt like the honest benchmark to report against.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>web3</category>
      <category>opensource</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
