<?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: carson</title>
    <description>The latest articles on DEV Community by carson (@carson2222).</description>
    <link>https://dev.to/carson2222</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%2F2875833%2F856f0387-ba6d-4434-a036-42ad3a658ccb.png</url>
      <title>DEV Community: carson</title>
      <link>https://dev.to/carson2222</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/carson2222"/>
    <language>en</language>
    <item>
      <title>AI + Foundry's cast: how I investigate smart contracts now</title>
      <dc:creator>carson</dc:creator>
      <pubDate>Thu, 19 Mar 2026 12:16:24 +0000</pubDate>
      <link>https://dev.to/carson2222/ai-foundrys-cast-how-i-investigate-smart-contracts-now-277m</link>
      <guid>https://dev.to/carson2222/ai-foundrys-cast-how-i-investigate-smart-contracts-now-277m</guid>
      <description>&lt;p&gt;I deploy Solidity contracts on HyperEVM. When the chain first launched in early 2025, the tooling around it was rough.&lt;/p&gt;

&lt;p&gt;The indexers couldn't access historical state. Subgraphs broke when you tried to query past blocks. The public RPC was rate-limited to 100 requests per minute. Block explorers showed incomplete data or wrong transaction hashes (a known issue where HyperEVM's S3-based block publishing caused hash mismatches with community tools like nanoreth).&lt;/p&gt;

&lt;p&gt;If I needed to investigate a contract — check its state, trace a transaction, understand what some unverified bytecode was doing — I did it the old way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old way
&lt;/h2&gt;

&lt;p&gt;Write a script. Call &lt;code&gt;eth_getLogs&lt;/code&gt;. Decode calldata manually. Piece it together from whatever fragments the broken tooling gave you.&lt;/p&gt;

&lt;p&gt;Something like this:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPublicClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;http&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;parseAbi&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;viem&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createPublicClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;http&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://rpc.hyperliquid.xyz/evm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Read contract state manually&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;owner&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readContract&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x815687F03D2Bab77Dd25237ae7f28bf599aBc2ee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parseAbi&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;function owner() view returns (address)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
  &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;owner&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Get logs, filter, decode each one, cross-reference...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;logs&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogs&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0x815687F03D2Bab77Dd25237ae7f28bf599aBc2ee&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fromBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;toBlock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;latest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Now you're manually decoding event data, matching selectors,&lt;/span&gt;
&lt;span class="c1"&gt;// figuring out what happened and in what order.&lt;/span&gt;
&lt;span class="c1"&gt;// On a chain where the explorer barely works.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works if you already know the ABI. If the contract isn't verified (common on new chains), you're looking at raw bytecode and guessing function signatures from 4-byte selectors.&lt;/p&gt;

&lt;p&gt;On Ethereum with Etherscan and working indexers? Annoying but manageable. On HyperEVM in early 2025? A full day for one contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed
&lt;/h2&gt;

&lt;p&gt;AI coding agents (Claude Code, Cursor, etc.) can now use CLI tools directly. Foundry's &lt;code&gt;cast&lt;/code&gt; is one of the most useful CLI tools for EVM interaction. Combine the two and you get something that actually works.&lt;/p&gt;

&lt;p&gt;Here's what the AI agent runs when I point it at a contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Read bytecode, check if there's anything to work with&lt;/span&gt;
cast code 0x815687F03D2Bab77Dd25237ae7f28bf599aBc2ee &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc.hyperliquid.xyz/evm

&lt;span class="c"&gt;# Read storage slots directly (slot 0 is usually owner in Ownable)&lt;/span&gt;
cast storage 0x815687F03D2Bab77Dd25237ae7f28bf599aBc2ee 0 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc.hyperliquid.xyz/evm

&lt;span class="c"&gt;# Call known functions without writing a full script&lt;/span&gt;
cast call 0x815687F03D2Bab77Dd25237ae7f28bf599aBc2ee &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"owner()(address)"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc.hyperliquid.xyz/evm

&lt;span class="c"&gt;# Trace a specific transaction&lt;/span&gt;
cast run 0x&amp;lt;txhash&amp;gt; &lt;span class="nt"&gt;--rpc-url&lt;/span&gt; https://rpc.hyperliquid.xyz/evm

&lt;span class="c"&gt;# Decode calldata without knowing the ABI&lt;/span&gt;
cast 4byte-decode 0x&amp;lt;calldata&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key: I don't run these myself anymore. I give the agent an address and a question. "What does this contract do?" or "Who can call the withdraw function?" or "Trace the last 5 transactions and tell me where the funds went."&lt;/p&gt;

&lt;p&gt;The agent decides what to query, runs the commands, reads the output, runs more queries based on what it found. Thirty to forty calls later, I get a summary.&lt;/p&gt;

&lt;p&gt;Five minutes instead of a day.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting it up
&lt;/h2&gt;

&lt;p&gt;The tool that makes this work: &lt;a href="https://github.com/PraneshASP/foundry-mcp-server" rel="noopener noreferrer"&gt;foundry-mcp-server&lt;/a&gt;. It wraps the entire Foundry toolchain (cast, forge, anvil) plus Heimdall (a bytecode decompiler) into MCP tools that any compatible AI agent can use.&lt;/p&gt;

&lt;p&gt;If you're on Claude Code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add foundry-mcp-server &lt;span class="nt"&gt;--&lt;/span&gt; npx @pranesh.asp/foundry-mcp-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set your RPC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RPC_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://rpc.hyperliquid.xyz/evm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your AI agent can read contract state, trace transactions, decode calldata, decompile unverified bytecode, and deploy contracts. All through natural language.&lt;/p&gt;

&lt;p&gt;There's also &lt;a href="https://github.com/0xGval/evm-mcp-tools" rel="noopener noreferrer"&gt;evm-mcp-tools&lt;/a&gt; if you want Etherscan and Moralis API integration for chains with decent explorer support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it falls apart
&lt;/h2&gt;

&lt;p&gt;Simple investigation: AI handles it. "What does this contract do?" "Who deployed it?" "What's the token balance at this address?" All fast, all correct.&lt;/p&gt;

&lt;p&gt;Medium complexity: AI speeds you up. It does the grunt work (reading storage, tracing calls, decoding events) and gives you a starting point. You take it from there.&lt;/p&gt;

&lt;p&gt;Hard stuff: AI hits a wall. Some examples from my own work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Chain-specific infra bugs.&lt;/strong&gt; HyperEVM had a phantom hash problem where the block explorer showed different transaction hashes than the official RPC. The cause: &lt;code&gt;nanoreth&lt;/code&gt; (a community tool that reads Hyperliquid's S3 block data) encodes system transaction signatures differently from the official node. No AI would figure this out without that context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complex proxy patterns.&lt;/strong&gt; AI can identify that something is a proxy. Understanding the upgrade path and storage layout across multiple implementations still takes manual work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Business logic with external dependencies.&lt;/strong&gt; I built a lottery contract that uses Pyth Entropy for on-chain randomness with a specific callback pattern. AI can read the code, but it can't tell you if the Pyth integration handles edge cases correctly without understanding Pyth's callback lifecycle.&lt;/p&gt;

&lt;p&gt;Anthropic published a benchmark (EVMbench, March 2026) where the best AI model scored 45.9% on vulnerability detection. When given hints about where to look, that jumped to ~90%. The bottleneck is finding where the problem is, not understanding it.&lt;/p&gt;

&lt;p&gt;That tracks with how I use it. Point the AI at something specific and it's fast. Ask it to find issues in a big project with no direction and it struggles.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it worth setting up?
&lt;/h2&gt;

&lt;p&gt;Yes. This is the biggest quality-of-life change I've had as a Web3 developer this past year. Not because AI is better at contract analysis than me. But it removes the dumb, repetitive work that used to eat hours.&lt;/p&gt;

&lt;p&gt;On newer chains where the tooling hasn't caught up (and on HyperEVM, it still hasn't fully), having an AI agent that queries the RPC directly and makes sense of raw data is the difference between a productive day and a wasted one.&lt;/p&gt;

&lt;p&gt;Try it. Point it at a contract you already understand and see if it gets it right. Then point it at something you don't know.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I build DeFi products on Hyperliquid and work as a fullstack Web3 engineer. More at &lt;a href="https://olafkrason.xyz" rel="noopener noreferrer"&gt;olafkrason.xyz&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>blockchain</category>
      <category>ai</category>
      <category>solidity</category>
    </item>
    <item>
      <title>I turned my private UI workflow into an open-source Agent Skill</title>
      <dc:creator>carson</dc:creator>
      <pubDate>Fri, 06 Mar 2026 17:04:21 +0000</pubDate>
      <link>https://dev.to/carson2222/i-turned-my-private-ui-workflow-into-an-open-source-agent-skill-342e</link>
      <guid>https://dev.to/carson2222/i-turned-my-private-ui-workflow-into-an-open-source-agent-skill-342e</guid>
      <description>&lt;p&gt;For a long time, this wasn't a skill.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;npx skills add carson2222/skills --skill design-exploration&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It was just a workflow I kept in my head.&lt;/p&gt;

&lt;p&gt;Every time I used AI for frontend work, I ran into the same problem: the result often looked decent, but it rarely felt genuinely designed. Too much of it landed in the same visual territory - safe layouts, familiar patterns, polished but forgettable output.&lt;/p&gt;

&lt;p&gt;So I started adjusting the way I worked.&lt;/p&gt;

&lt;p&gt;Instead of asking for one result and trying to polish it, I pushed the agent to explore multiple real directions at once. Not tiny visual tweaks. Real variants with different structure, hierarchy, tone, and emphasis.&lt;/p&gt;

&lt;p&gt;That changed a lot.&lt;/p&gt;

&lt;p&gt;It made the process feel closer to actual design exploration instead of autocomplete with Tailwind.&lt;/p&gt;

&lt;p&gt;Over time I kept refining that workflow. I changed what I asked for, what I forbade, how I framed constraints, how I handled existing design systems, and how I compared options. Eventually it became repeatable enough that it stopped feeling like "a good prompt" and started feeling like a tool.&lt;/p&gt;

&lt;p&gt;That's where design-exploration came from.&lt;/p&gt;

&lt;p&gt;A shoutout is deserved here too: one of Theo's design prompts was an early spark for this line of thinking. The idea of having the agent generate multiple variants instead of obsessing over one first try was a strong starting point. But the version I use today is something I tuned heavily through repeated real use.&lt;/p&gt;

&lt;p&gt;Another reason I finally packaged it properly is simple: people kept asking for it.&lt;/p&gt;

&lt;p&gt;Friends and coworkers saw the kind of output I was getting and wanted to try the same workflow themselves. At some point it became obvious that keeping it as a private mental prompt was silly. Wrapping it as a skill made it easier to reuse, easier to share, and easier to improve.&lt;/p&gt;

&lt;p&gt;I mostly use it with OpenCode and Opus 4.6. That combination has been the most reliable for me by far. Other models can absolutely produce strong UI, but they tend to be less predictable. For this kind of work, predictability matters almost as much as quality.&lt;/p&gt;

&lt;p&gt;One important thing, though: this is not magic.&lt;/p&gt;

&lt;p&gt;You still need to give the model context. You still need to explain what the product is, who it is for, what kind of feeling you want, and what tradeoffs matter. If you have assets, references, or constraints, give them. The better the context, the better the exploration.&lt;/p&gt;

&lt;p&gt;The skill helps structure the process.&lt;/p&gt;

&lt;p&gt;It does not replace taste.&lt;/p&gt;

&lt;p&gt;If you want to try it, the repo is here:&lt;br&gt;
&lt;a href="https://github.com/carson2222/skills" rel="noopener noreferrer"&gt;https://github.com/carson2222/skills&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there's interest, I'll write a follow-up on the exact workflow, what usually fails, and how I avoid the most common AI frontend traps.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>ui</category>
      <category>design</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How AI screws our projects</title>
      <dc:creator>carson</dc:creator>
      <pubDate>Wed, 23 Jul 2025 11:01:35 +0000</pubDate>
      <link>https://dev.to/carson2222/how-ai-screws-our-projects-5b8k</link>
      <guid>https://dev.to/carson2222/how-ai-screws-our-projects-5b8k</guid>
      <description>&lt;p&gt;As an efficient programmer, I've been using AI tools like Copilot or Cursor in my daily life. It definitely speeds up the whole process and makes it easier to ship real products.&lt;/p&gt;

&lt;p&gt;However, there is a big problem with using tools that powerful.&lt;br&gt;
Back in the day, when you encountered a problem, you just had to Google it. If there was no easy way to fix it, you'd either have to deep dive into the concept you were struggling with or get help from someone else.&lt;br&gt;
Then someone else (or you, with more knowledge about the topic) could look deeper into the code and find that the whole problem was in your approach. Instead of just dully fixing the issue, maybe you should change the whole approach — use other tools, libraries, or re-write the whole structure in a more efficient way?&lt;/p&gt;

&lt;p&gt;With AI, solving problems looks completely different.&lt;br&gt;
When you encounter a problem you can’t solve on your own, you just prompt it to an AI and boom — it gets solved. AI just finds a way to fix it. The code itself might work, but it can be very poor.&lt;/p&gt;

&lt;p&gt;Why am I writing this?&lt;br&gt;
Recently, I was doing a freelance project for a client. Everything was going great, and I had a deadline I’d easily meet. But one day, when I was out of the house with not much free time, the client asked me to make a "demo" example for the next day. The app was working, with some flaws I had to fix ASAP. So I just opened a Gemini CLI and started prompting. After a few unsuccessful prompts, I was finally able to fix the issues and finish the demo version.&lt;br&gt;
When I got back home, I started working on the project again. I looked at the code that AI had generated — it was awful. Then, on my own, I reviewed the whole codebase and realized the problem was much deeper. I just didn’t need that thing at all.&lt;br&gt;
If I had trusted the AI fully, I would’ve ended up with a useless feature that just litters my app.&lt;/p&gt;

&lt;p&gt;I believe I’m not the only one. Situations like this happen every day, and some people never realize how much AI screwed their code.&lt;br&gt;
Let’s start being more like real programmers instead of vibe coders.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>vibecoding</category>
      <category>ai</category>
    </item>
    <item>
      <title>Build Your Own Twitter AI Bot: The Ultimate Guide</title>
      <dc:creator>carson</dc:creator>
      <pubDate>Mon, 10 Mar 2025 19:29:05 +0000</pubDate>
      <link>https://dev.to/carson2222/build-your-own-twitter-ai-bot-the-ultimate-guide-4poa</link>
      <guid>https://dev.to/carson2222/build-your-own-twitter-ai-bot-the-ultimate-guide-4poa</guid>
      <description>&lt;h2&gt;
  
  
  How to Create Your Own Twitter AI Agent
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Recently, I received a freelance offer to create a Twitter AI Agent. It sounded like a cool experience, so I decided to take on the challenge. I used &lt;strong&gt;ElizaOS&lt;/strong&gt;, a framework built by the ai16z community that makes creating AI Agents much easier. After spending some time with it, I can confidently say that it has great potential. It just needs a bit more polish. Its main focus is to make AI Agent creation super user-friendly. I didn’t have to do much "coding," but a non-programmer might run into some challenges.&lt;/p&gt;

&lt;p&gt;One major issue I faced was the new update. Just a few days after I started working with ElizaOS, a major update was pushed. There were tons of guides, videos, and documentation on the old version, but I wanted to use the latest one since it had crucial new tooling. Since there were barely any resources on setting up the new version, I had to figure everything out through trial and error.&lt;/p&gt;

&lt;p&gt;In this article, I aim to save you time and make the setup process much easier. I won’t explain the entire ElizaOS framework—it’s massive with tons of tools and use cases. Instead, I'll provide a straightforward starting point, from which you can expand your AI Agent as needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Initialization
&lt;/h2&gt;

&lt;p&gt;Before cloning the ElizaOS project, make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Node.js 23+&lt;/strong&gt;: &lt;a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm" rel="noopener noreferrer"&gt;Download and Install&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pnpm 9+&lt;/strong&gt;: &lt;a href="https://pnpm.io/installation" rel="noopener noreferrer"&gt;Installation Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Git&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GitHub CLI&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Clone the Repository
&lt;/h3&gt;

&lt;p&gt;There are multiple ways to initialize the project. The following worked best for me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gh repo clone elizaOS/eliza
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:elizaOS/eliza.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate into the project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;eliza
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switch to the development branch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout develop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Handling &lt;code&gt;sqlite3&lt;/code&gt; Errors
&lt;/h4&gt;

&lt;p&gt;If you encounter an error related to &lt;code&gt;sqlite3&lt;/code&gt; during the build process, run the following command and retry the build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm &lt;span class="nb"&gt;exec &lt;/span&gt;npm rebuild better-sqlite3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any other issues arise during initialization, check the AI documentation, GitHub issues, or ask for help on their Discord server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup the Environment File
&lt;/h3&gt;

&lt;p&gt;Copy &lt;code&gt;.env.example&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Start the Agent (Test Run)
&lt;/h2&gt;

&lt;p&gt;To ensure everything is set up properly, let's run a sample chatbot. There’s already a built-in character sample we can use.&lt;/p&gt;

&lt;p&gt;Start the AI Agent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In a new terminal, start the built-in chat UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm start:client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:5173/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see a chatbot interface where you can interact with the default AI Agent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Create Your Own Character
&lt;/h2&gt;

&lt;p&gt;Creating a character personality file (&lt;code&gt;.json&lt;/code&gt;) hasn't changed much in the new version, so the existing documentation is helpful. The best way to refine your AI Agent’s personality is through trial and error.&lt;/p&gt;

&lt;p&gt;Here’s a tool to assist with character creation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://elizagen.howieduhzit.best/" rel="noopener noreferrer"&gt;ElizaGen&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Character examples for reference:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/elizaos/characters" rel="noopener noreferrer"&gt;GitHub Character Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save your character files in the &lt;code&gt;/characters&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;To use your custom AI Agent, start the program with a character flag:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm start &lt;span class="nt"&gt;--character&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"characters/myai.character.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Download the Twitter Plugin
&lt;/h2&gt;

&lt;p&gt;Adding plugins in ElizaOS is straightforward. Simply run one command and configure your character file.&lt;/p&gt;

&lt;p&gt;Here’s the list of official ElizaOS plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://elizaos.github.io/registry/" rel="noopener noreferrer"&gt;Plugin Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Or run:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npx elizaos plugins list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install the Twitter plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx elizaos plugins add @elizaos-plugins/client-twitter
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, modify your character’s JSON file to enable the plugin:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"clients"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"twitter"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"@elizaos-plugins/client-twitter"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Set Up Your AI Provider
&lt;/h2&gt;

&lt;p&gt;Running your own AI model locally (e.g., DeepSeek) would be great, but AI models require significant resources. Using an external AI provider is usually more practical.&lt;/p&gt;

&lt;p&gt;I found &lt;strong&gt;Heurist&lt;/strong&gt; to be the best provider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple setup&lt;/li&gt;
&lt;li&gt;Affordable&lt;/li&gt;
&lt;li&gt;Accepts crypto payments&lt;/li&gt;
&lt;li&gt;Offers various AI models, including uncensored ones&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Steps to Set Up Heurist:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign in to &lt;a href="https://www.heurist.ai" rel="noopener noreferrer"&gt;Heurist&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Deposit some credits (even a few cents are enough for testing)&lt;/li&gt;
&lt;li&gt;Generate and copy your API Key&lt;/li&gt;
&lt;li&gt;Add the API Key to your &lt;code&gt;.env&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;HEURIST_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;YourApiKey
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set your preferred AI models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SMALL_HEURIST_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek/deepseek-v3
&lt;span class="nv"&gt;MEDIUM_HEURIST_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek/deepseek-v3
&lt;span class="nv"&gt;LARGE_HEURIST_MODEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;deepseek/deepseek-v3
&lt;span class="nv"&gt;USE_HEURIST_EMBEDDING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For custom models, check:&lt;br&gt;
&lt;a href="https://docs.heurist.ai/dev-guide/supported-models#large-language-models-llms" rel="noopener noreferrer"&gt;Heurist's Model List&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Configure the Twitter Plugin
&lt;/h2&gt;

&lt;p&gt;To enable Twitter integration, set up the required credentials in &lt;code&gt;.env&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TWITTER_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_EMAIL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_2FA_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important Tip:&lt;/strong&gt; Set the Twitter account to "Automated" in the account settings. This informs Twitter that the account is run by code, reducing the risk of being banned.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional Twitter Configurations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TWITTER_DRY_RUN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;&lt;span class="nv"&gt;TWITTER_POLL_INTERVAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;600
&lt;span class="nv"&gt;TWITTER_TARGET_USERS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_RETRY_LIMIT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_SEARCH_ENABLE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;&lt;span class="nv"&gt;ENABLE_TWITTER_POST_GENERATION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;POST_INTERVAL_MIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;150
&lt;span class="nv"&gt;POST_INTERVAL_MAX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;300
&lt;span class="nv"&gt;POST_IMMEDIATELY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false
&lt;/span&gt;&lt;span class="nv"&gt;ENABLE_ACTION_PROCESSING&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add a &lt;strong&gt;Discord approval system&lt;/strong&gt; (so the bot doesn’t post anything dumb), create a bot in &lt;a href="https://discord.com/developers/applications" rel="noopener noreferrer"&gt;Discord Developer Portal&lt;/a&gt; and add these values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TWITTER_APPROVAL_DISCORD_CHANNEL_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_APPROVAL_DISCORD_BOT_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;TWITTER_APPROVAL_ENABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
&lt;/span&gt;&lt;span class="nv"&gt;TWITTER_APPROVAL_CHECK_INTERVAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Step: Run Your AI Agent
&lt;/h2&gt;

&lt;p&gt;Run your bot with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm start &lt;span class="nt"&gt;--character&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"characters/myai.character.json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thanks for reading! I hope this guide was helpful. If you need any assistance, feel free to ask in the comments or DM me!&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>ai</category>
      <category>twitter</category>
    </item>
    <item>
      <title>How to Secure Solana Tokens &amp; NFTs - Updating and Revoking Authorities</title>
      <dc:creator>carson</dc:creator>
      <pubDate>Wed, 19 Feb 2025 14:00:41 +0000</pubDate>
      <link>https://dev.to/carson2222/how-to-secure-a-solana-tokens-nfts-updating-and-revoking-authorities-25gb</link>
      <guid>https://dev.to/carson2222/how-to-secure-a-solana-tokens-nfts-updating-and-revoking-authorities-25gb</guid>
      <description>&lt;h2&gt;
  
  
  How to Secure a Solana NFT Collection - Updating and Revoking Authorities
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Terminology
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mint Authority:&lt;/strong&gt; Grants the ability to mint more tokens of an asset (irrelevant for NFTs, as they have a fixed supply of 1).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Freeze Authority:&lt;/strong&gt; Allows an account to freeze and unfreeze assets, restricting their movement.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update Authority (UA):&lt;/strong&gt; The wallet that has permission to modify an NFT’s metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revoking Authority:&lt;/strong&gt; The act of permanently removing control from any wallet to ensure security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Liquidity Pool (LP):&lt;/strong&gt; A decentralized reserve of tokens that facilitates trading.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In our previous article, we covered updating NFT metadata, migrating update authorities, and adjusting royalty share structures. If you haven't read it yet, I highly recommend checking it out: &lt;a href="https://dev.to/carson2222/how-to-derug-a-solana-nft-collection-updating-nft-authority-c0j"&gt;How to DeRug a Solana NFT Collection - Updating NFT Authority&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let's dive deeper into another critical aspect of securing an NFT or token collection: updating and revoking the &lt;strong&gt;Mint Authority&lt;/strong&gt; and &lt;strong&gt;Freeze Authority&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These authorities are crucial when dealing with &lt;strong&gt;SFTs (Semi-Fungible Tokens)&lt;/strong&gt; and &lt;strong&gt;fungible tokens&lt;/strong&gt;, as they can impact liquidity, security, and token economics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Revoking Authorities Matters
&lt;/h2&gt;

&lt;p&gt;For a token or NFT collection to be considered &lt;strong&gt;trustworthy&lt;/strong&gt;, these authorities must be properly managed. A well-known practice in legitimate projects is &lt;strong&gt;burning&lt;/strong&gt; the Mint &amp;amp; Freeze Authorities, meaning no one can mint extra tokens or freeze assets arbitrarily.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Real-World Example
&lt;/h3&gt;

&lt;p&gt;Imagine a liquidity pool with &lt;strong&gt;100 tokens and $100 in liquidity&lt;/strong&gt;. This means each token is worth &lt;strong&gt;$1&lt;/strong&gt;. Now, if someone mints &lt;strong&gt;100 billion more tokens&lt;/strong&gt; for themselves, the token supply becomes &lt;strong&gt;100,000,000,100&lt;/strong&gt;, while the liquidity pool remains at $100. This person now owns nearly &lt;strong&gt;100% of the supply&lt;/strong&gt; and can drain the liquidity pool, rendering the token worthless.&lt;/p&gt;

&lt;p&gt;Revoking these authorities ensures that such exploits are impossible, maintaining &lt;strong&gt;fairness and stability&lt;/strong&gt; in the ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Updating Authorities on Solana
&lt;/h2&gt;

&lt;p&gt;To manage these authorities, we'll use &lt;a href="https://github.com/metaplex-foundation/mpl-toolbox" rel="noopener noreferrer"&gt;Metaplex's mpl-toolbox&lt;/a&gt;, which provides a &lt;strong&gt;setAuthority&lt;/strong&gt; function to update or revoke permissions.&lt;/p&gt;

&lt;p&gt;Here, we'll build &lt;strong&gt;two transactions&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Updating the &lt;strong&gt;Mint Authority&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Updating the &lt;strong&gt;Freeze Authority&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Code Implementation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Setting New Authorities
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;setAuthority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;authorityType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MintTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;itemMint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&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="nf"&gt;setAuthority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;authorityType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FreezeAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;itemMint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;builder&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;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLatestBlockhash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;commitment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&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;tx&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;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendAndConfirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Explanation of Parameters:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;authorityType&lt;/code&gt;: Specifies which authority to update (Mint or Freeze Authority).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;newAuthority&lt;/code&gt;: New owner’s public key. Set to &lt;strong&gt;null&lt;/strong&gt; if you want to revoke the authority permanently.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;owned&lt;/code&gt;: Mint address of the asset to update.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;owner&lt;/code&gt;: The current authority owner’s public key.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Automating Authority Updates for Multiple Assets
&lt;/h4&gt;

&lt;p&gt;To update a collection of &lt;strong&gt;SFTs&lt;/strong&gt;, we need to retrieve and process them dynamically. Below is a script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Loads all SFTs belonging to a specific collection.&lt;/li&gt;
&lt;li&gt;Updates their &lt;strong&gt;Mint &amp;amp; Freeze Authorities&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Skips assets that are already updated.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;bs58&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bs58&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;createUmi&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="s2"&gt;@metaplex-foundation/umi-bundle-defaults&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;mplCore&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="s2"&gt;@metaplex-foundation/mpl-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;createSignerFromKeypair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signerIdentity&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="s2"&gt;@metaplex-foundation/umi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setAuthority&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="s2"&gt;@metaplex-foundation/mpl-toolbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&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;fetchAllDigitalAssetByUpdateAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchDigitalAsset&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="s2"&gt;@metaplex-foundation/mpl-token-metadata&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;migrateSFTsAuthorities&lt;/span&gt;&lt;span class="p"&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;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OLD_UA_SECRET_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;umi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUmi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RPC&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mplCore&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;signer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eddsa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createKeypairFromSecretKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bs58&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;signerIdentity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createSignerFromKeypair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signer&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;newAuthority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;PUBLIC_KEY&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;collectionKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;COLLECTION_KEY&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;assets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchAllDigitalAssetByUpdateAuthority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&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;filteredAssets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__option&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Some&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
             &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;collection&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="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;collectionKey&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
             &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;collectionKey&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Total assets: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filteredAssets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for &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;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;filteredAssets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&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;asset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchDigitalAsset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filteredAssets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&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;itemMint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;filteredAssets&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mintAuthority&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__option&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Some&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freezeAuthority&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__option&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Some&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mintAuthority&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="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&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="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
      &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freezeAuthority&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="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&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="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`#&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; is already updated`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Handling i: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, mint: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;itemMint&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="s2"&gt;`&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;builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;setAuthority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;authorityType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MintTokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;itemMint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&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="nf"&gt;setAuthority&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;authorityType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthorityType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;FreezeAccount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;owned&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;itemMint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;builder&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;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setLatestBlockhash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;commitment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&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;tx&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;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendAndConfirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&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="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&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="nx"&gt;err&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Success #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;migrateSFTsAuthorities&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mint &amp;amp; Freeze Authorities&lt;/strong&gt; play a vital role in asset security.&lt;/li&gt;
&lt;li&gt;Revoking them prevents supply manipulation and freezing exploits.&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;Metaplex's mpl-toolbox&lt;/strong&gt;, we can update or revoke authorities.&lt;/li&gt;
&lt;li&gt;Automating the process ensures large collections are updated efficiently.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;By properly securing the authorities of your NFTs and tokens, you can prevent exploits and reinforce trust in your project. If you're working with a Solana-based collection, taking these steps is &lt;strong&gt;essential&lt;/strong&gt; for security and decentralization.&lt;/p&gt;

&lt;p&gt;If you have any questions or need further help, feel free to reach out on &lt;strong&gt;&lt;a href="https://x.com/carson3068" rel="noopener noreferrer"&gt;X&lt;/a&gt; or &lt;a href="https://github.com/carson2222" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>javascript</category>
      <category>solana</category>
      <category>web3</category>
    </item>
    <item>
      <title>How to DeRug a Solana NFT Collection - Updating NFT Authority</title>
      <dc:creator>carson</dc:creator>
      <pubDate>Mon, 17 Feb 2025 17:56:23 +0000</pubDate>
      <link>https://dev.to/carson2222/how-to-derug-a-solana-nft-collection-updating-nft-authority-c0j</link>
      <guid>https://dev.to/carson2222/how-to-derug-a-solana-nft-collection-updating-nft-authority-c0j</guid>
      <description>&lt;h2&gt;
  
  
  How to DeRug a Solana NFT Collection - Updating NFT Authority
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Terminology
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Update Authority (UA):&lt;/strong&gt; The wallet address that has the power to modify an NFT's metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creators:&lt;/strong&gt; The list of wallets that are attributed as the creators of an NFT and can receive royalties.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metadata:&lt;/strong&gt; The stored data related to an NFT, such as its name, image, and attributes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unverify Creator:&lt;/strong&gt; The process of removing a wallet's verification as a creator, necessary before updating metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mint:&lt;/strong&gt; The unique identifier (public key) of an NFT or NFT collection on Solana.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Let's take a scenario where you gain access to an NFT collection owned by someone else. In this case, it is not very safe to keep it as is. The previous owners still have access to the NFTs, royalties, etc. So what should you do? In this article, I'll show you my approach to handling this issue.&lt;/p&gt;

&lt;p&gt;In my case, it wasn't exactly derugging a collection. Instead, I helped the Trippin' Ape Tribe NFT collection migrate all their NFTs to a new Update Authority wallet to ensure the previous developers no longer had access to them.&lt;/p&gt;

&lt;h3&gt;
  
  
  My Environment:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Language:&lt;/strong&gt; TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tools:&lt;/strong&gt; Multiple &lt;a href="https://developers.metaplex.com/" rel="noopener noreferrer"&gt;@metaplex-foundation&lt;/a&gt; tools (check imports for details)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find all functions in this GitHub repository: &lt;strong&gt;&lt;a href="https://github.com/carson2222/sol-tools" rel="noopener noreferrer"&gt;https://github.com/carson2222/sol-tools&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What We'll Be Updating
&lt;/h3&gt;

&lt;p&gt;To ensure the NFT collection is fully migrated to the new authority wallet, we will update:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;new update authority&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;new creators&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify/Unverify creators&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process needs to be done both for the collection itself and for each individual NFT.&lt;/p&gt;




&lt;h2&gt;
  
  
  Migrating Collection Authority
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Initializing Wallets
&lt;/h3&gt;

&lt;p&gt;First, we load two wallets and initialize a Metaplex Umi instance with them. The first wallet is the current NFT authority owner, and the second one is the new authority. Make sure both wallets have some SOL for transaction fees. Your wallet-loading method may vary depending on how your private key or seed phrase is stored.&lt;/p&gt;

&lt;p&gt;For security reasons, I use a private key stored as a string in my &lt;code&gt;.env&lt;/code&gt; file.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OLD_UA_SECRET_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;umi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUmi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RPC&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mplCore&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;signer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eddsa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createKeypairFromSecretKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bs58&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;signerIdentity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createSignerFromKeypair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signer&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;privateKeyNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEW_UA_SECRET_KEY&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&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;umiNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createUmi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;RPC&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;confirmed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mplCore&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;signerNew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eddsa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createKeypairFromSecretKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bs58&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;privateKeyNew&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nx"&gt;umiNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;signerIdentity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;createSignerFromKeypair&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signerNew&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Constants
&lt;/h3&gt;

&lt;p&gt;Update &lt;code&gt;mint&lt;/code&gt; with the public key of your collection. Since we are setting the new authority to the second wallet initialized, &lt;code&gt;newAuthority&lt;/code&gt; remains as is.&lt;/p&gt;

&lt;p&gt;If you want the new UA wallet to receive 100% of the royalties, leave the configuration unchanged. Otherwise, add more elements and adjust the share percentages, ensuring the total sum is 100%.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DmL46V46U5VM4UgrJbVQvWhVyD1zjZGGVRWeMv46eWt9&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;newAuthority&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;signerNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&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;newCreators&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildNewCreators&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&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="na"&gt;share&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}]);&lt;/span&gt; &lt;span class="c1"&gt;// Sum of shares must be 100%&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loading Collection Metadata
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialMetadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchMetadataFromSeeds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;mint&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Unverifying the Old Creator
&lt;/h3&gt;

&lt;p&gt;On Solana, you cannot remove a wallet from receiving royalties while it is still verified. To unverify it, you need access to this wallet.&lt;/p&gt;

&lt;p&gt;In this example, I assume there is only one verified creator—the UA wallet. Adjust the code if needed.&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="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;unverifyCreatorV1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sendAndConfirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Migrating the Authority &amp;amp; Creators
&lt;/h3&gt;

&lt;p&gt;Here, we update the metadata to set the new authority wallet and apply the new creator structure. If you want to change other metadata properties, update the object accordingly.&lt;/p&gt;

&lt;p&gt;Be sure to include all existing metadata fields when updating, or you might accidentally reset the entire data object.&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="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updateV1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;mint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;initialMetadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;creators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newCreators&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;newUpdateAuthority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newAuthority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sendAndConfirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verifying the New Creator
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;verifyCreatorV1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umiNew&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initialMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;authority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;umiNew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;sendAndConfirm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umiNew&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/carson2222/sol-tools/blob/main/metadata/migrateCollection.ts" rel="noopener noreferrer"&gt;Complete code&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Migrating NFTs Authority
&lt;/h2&gt;

&lt;p&gt;Since a collection is technically an NFT, we will repeat a similar process. However, we need to do this for EVERY NFT in the collection. Doing this manually would be inefficient, so we automate the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting a List of All NFTs
&lt;/h3&gt;

&lt;p&gt;There are multiple ways to retrieve all NFTs in a collection. My approach was to load all assets owned by a specific wallet and then filter them by symbol to target the ones I wanted to update.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchAllDigitalAssetByOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;umi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;signer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&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;filteredAssets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;assets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;symbol&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ReSHAPE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;publicKey&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nx"&gt;collectionMint&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we loop through the filtered list and repeat the same steps as we did for the collection:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Unverify the creator&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Update authority and creators&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Verify the creator&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/carson2222/sol-tools/blob/main/metadata/migrateCollectionItems.ts" rel="noopener noreferrer"&gt;Complete code&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this guide, we covered how to migrate an NFT collection's update authority to a new wallet, ensuring that the previous owner or developer no longer has control over the assets. We went through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializing and setting up wallets&lt;/li&gt;
&lt;li&gt;Unverifying the old creator&lt;/li&gt;
&lt;li&gt;Updating the update authority and creators&lt;/li&gt;
&lt;li&gt;Verifying the new creator&lt;/li&gt;
&lt;li&gt;Automating the migration process for all NFTs in a collection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following these steps, you can safely migrate an NFT collection and secure its ownership under a new update authority.&lt;/p&gt;

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

&lt;p&gt;Migrating an NFT collection's authority is a crucial step in securing ownership and preventing unwanted access. Whether you're taking over a project or assisting in a migration, automating this process can save time and ensure a seamless transition.&lt;/p&gt;

&lt;p&gt;If you found this guide helpful, consider checking out the full implementation on my GitHub: &lt;strong&gt;&lt;a href="https://github.com/carson2222/sol-tools" rel="noopener noreferrer"&gt;https://github.com/carson2222/sol-tools&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>solana</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
