3 min read

How to Change the Mint Authority of a Solana Token Account

In this tutorial, we'll walk through a TypeScript code snippet that changes the mint authority of a Solana token account. This can be useful when you want to modify the mint authority for testing purposes using solana-test-validator.

Prerequisites

Before we dive into the code, make sure you have the following:

  • Node.js installed
  • TypeScript installed
  • ethers (or bs58) library installed
  • fs module (comes with Node.js)
  • A JSON file containing the token account data (e.g., usdc.json)

Step-by-Step Explanation

Import Required Modules

import { base58 } from 'ethers/lib/utils';
import USDC_TOKEN from './usdc.json';
import { writeFileSync } from 'fs';

We import the base58 utility from the ethers library, the token data from usdc.json, and the writeFileSync function from the fs module.

Define the TokenData Interface

interface TokenData {
  pubkey: string;
  account: {
    lamports: number;
    data: [string, string]; // [base64 encoded data, encoding type]
    owner: string;
    executable: boolean;
    rentEpoch: number;
    space: number;
  };
}

We define an interface TokenData to represent the structure of the token account data.

Create the changeMintAuthority Function

async function changeMintAuthority(
  myAddress: string,
  tokenData: unknown,
  outputFile: string
) {
  try {
    // Read JSON file
    const token = tokenData as TokenData;

We create an asynchronous function changeMintAuthority that takes three parameters: myAddress (the new mint authority address), tokenData (the token account data), and outputFile (the output file path).

Convert Base64 to Byte Array

    // Convert base64 to byte array
    const data = Buffer.from(token.account.data[0], 'base64');
    console.log('Data:', data.toString('hex'));
    console.log('Authority', base58.encode(data.slice(4, 36)));

We convert the base64-encoded data to a byte array and log the data and current mint authority.

Replace Mint Authority

    // Replace mint authority (bytes 4-36) with new address
    const newAuthorityBytes = base58.decode(myAddress);
    data.set(newAuthorityBytes, 4);
    console.log('Data:', data.toString('hex'));
    console.log('Authority', base58.encode(data.slice(4, 36)));

We replace the mint authority (bytes 4-36) with the new address and log the updated data and new mint authority.

Update the Data with New Mint Authority

    // Update the data with new mint authority
    token.account.data[0] = data.toString('base64');

We update the token account data with the new mint authority.

Write Modified JSON to New File

    // Write modified JSON to new file
    writeFileSync(outputFile, JSON.stringify(token, null, 2));
    console.log(`Successfully changed mint authority to ${myAddress}`);
    console.log(`Modified JSON saved to ${outputFile}`);
  } catch (error) {
    console.error('Failed to change mint authority:', error);
    throw error;
  }
}

We write the modified token account data to a new JSON file and log a success message. If an error occurs, we log the error and throw it.

Run the Function

const MY_ADDRESS = '8vTM2FwzXT8bwT5jXyv556eo6LdPPPCnhynaCZcW2zRa';
changeMintAuthority(MY_ADDRESS, USDC_TOKEN, './usdc-mod.json');

We define the new mint authority address and call the changeMintAuthority function with the appropriate parameters.

Running the Code

To run the code, follow these steps:

Capture the token account data using the following command:

solana account AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE --output json --output-file usdc.json --url https://eclipse.helius-rpc.com

Execute the TypeScript code to change the mint authority:

ts-node changeMintAuthority.ts

Use the modified token account data with solana-test-validator:

solana-test-validator --url https://eclipse.helius-rpc.com --account AKEWE7Bgh87GPp171b4cJPSSZfmZwQ3KaqYqXoKLNAEE ./usdc-mod.json --reset

And that's it! You've successfully changed the mint authority of a Solana token account. Happy coding! 🎉

Here's the full source:

interface TokenData {
  pubkey: string;
  account: {
    lamports: number;
    data: [string, string]; // [base64 encoded data, encoding type]
    owner: string;
    executable: boolean;
    rentEpoch: number;
    space: number;
  };
}

async function changeMintAuthority(
  myAddress: string,
  tokenData: unknown,
  outputFile: string
) {
  try {
    // Read JSON file
    const token = tokenData as TokenData;

    // Convert base64 to byte array
    const data = Buffer.from(token.account.data[0], 'base64');
    console.log('Data:', data.toString('hex'));
    console.log('Authority', base58.encode(data.slice(4, 36)));

    // Replace mint authority (bytes 4-36) with new address
    const newAuthorityBytes = base58.decode(myAddress);
    data.set(newAuthorityBytes, 4);
    console.log('Data:', data.toString('hex'));
    console.log('Authority', base58.encode(data.slice(4, 36)));

    // Update the data with new mint authority
    token.account.data[0] = data.toString('base64');

    // Write modified JSON to new file
    writeFileSync(outputFile, JSON.stringify(token, null, 2));

    console.log(`Successfully changed mint authority to ${myAddress}`);
    console.log(`Modified JSON saved to ${outputFile}`);
  } catch (error) {
    console.error('Failed to change mint authority:', error);
    throw error;
  }
}

const MY_ADDRESS = '8vTM2FwzXT8bwT5jXyv556eo6LdPPPCnhynaCZcW2zRa';
changeMintAuthority(MY_ADDRESS, USDC_TOKEN, './scripts/usdc-modded.json');