diff --git a/.eslintignore b/.eslintignore
index c4855b08..339b0c01 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -5,4 +5,5 @@ package.json
 tsconfig.cjs.json
 tsconfig.esm.json
 tsconfig.json
-package-lock.json
\ No newline at end of file
+package-lock.json
+packages
\ No newline at end of file
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100755
index 00000000..d24fdfc6
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npx lint-staged
diff --git a/.husky/pre-push b/.husky/pre-push
new file mode 100755
index 00000000..879e9351
--- /dev/null
+++ b/.husky/pre-push
@@ -0,0 +1,4 @@
+#!/usr/bin/env sh
+. "$(dirname -- "$0")/_/husky.sh"
+
+npm run test
diff --git a/.prettierignore b/.prettierignore
index 326c466e..4ecd1575 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,5 @@
 .eslint/**/*
 packages/**/dist/**/*
 apps/**/.sveltekit/**/*
-tsconfig.json
\ No newline at end of file
+tsconfig.json
+packages
\ No newline at end of file
diff --git a/README.md b/README.md
index 1c3a92c4..b44d2e3f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# XRAY
+![https://xray.helius.xyz/](/doc/xray-cover-gh.jpg)
 
-A human-readable Solana transaction explorer powered by Helius.
+## Relevant Links
 
 🔗 **Link**: https://xray.helius.xyz/
 
@@ -12,9 +12,9 @@ A human-readable Solana transaction explorer powered by Helius.
 
 ## Support
 
-- 📝 [Start Discussion](https://github.com/helius-labs/xray/discussions)
-- 💡 [Submit Feature Request](https://github.com/helius-labs/xray/issues/new?assignees=&labels=question&template=FEATURE-REQUEST.yml&title=%F0%9F%92%A1+%5BREQUEST%5D+-+%3Ctitle%3E)
-- 🐛 [Submit Bug Report](https://github.com/helius-labs/xray/issues/new?assignees=&labels=bug&template=BUG-REPORT.yml&title=%F0%9F%90%9B+%5BBUG%5D+-+%3Ctitle%3E)
+-   📝 [Start Discussion](https://github.com/helius-labs/xray/discussions)
+-   💡 [Submit Feature Request](https://github.com/helius-labs/xray/issues/new?assignees=&labels=question&template=FEATURE-REQUEST.yml&title=%F0%9F%92%A1+%5BREQUEST%5D+-+%3Ctitle%3E)
+-   🐛 [Submit Bug Report](https://github.com/helius-labs/xray/issues/new?assignees=&labels=bug&template=BUG-REPORT.yml&title=%F0%9F%90%9B+%5BBUG%5D+-+%3Ctitle%3E)
 
 ## 🤝 Contribute
 
@@ -40,7 +40,7 @@ Then when you're ready to create the PR, click "Ready for review".
 
 To save time, run tests locally, but they will also run on all PRs to `dev` and `main`. Tests will need to be passing for your changes to be merged.
 
-### Auto merge `dev` -> `main`**
+### Auto merge `dev` -> `main`\*\*
 
 Once changes are approved and merged into `dev`, they will be assumed as good and auto merged to `main`. From here they can be deployed by merging to either the `vercel/staging` or `vercel/prod` branches.
 
@@ -217,50 +217,22 @@ WIP
 -   [TanstackQuery](https://tanstack.com/query/latest)
 -   [SvelteKit tRPC SvelteQuery Adapter](https://github.com/vishalbalaji/trpc-svelte-query-adapter)
 
-# 📦 @helius-labs/proton
+# 📦 @helius-labs/xray
 
-Used for parsing blockchain data and making it pretty for the UI.
+A package that includes our parser, which helps make blockchain data pretty for the UI, and search function.
 
 ## Important Files & Folders
 
-|                            |                                                                                       |
-| -------------------------- | ------------------------------------------------------------------------------------- |
-| 📄`./index.ts`             | UI calls the function in this file to parse transactions                              |
-| 📄`./src/types/index.ts`   | Contains the types, interfaces, and enums needed to understand to work on the parser. |
-| 📁`./src/parsers`          | Contains all parser methods.                                                          |
-| 📄`./src/parsers/index.ts` | Exports parser files in `./src/parsers`.                                              |
-| 📁`./src/utils`            | Utility functions for parser functions                                                |
-
-## General Work Flow When Adding a New Transaction Type
-
-1. Identify a transaction type that is not currently supported.
-    - [Helius API Docs](https://docs.helius.xyz/reference/transaction-types) - View all transaction types supported by Helius.
-2. Get to know the transaction type. Here is the resource I personally like to use for it:
-    - [SwaggerHub](https://app.swaggerhub.com/apis-docs/Helius/HeliusAPI/1.1.0#/Transactions/getEnrichedTransactions) - Use `/v0/addresses/{address}/transactions ` for addresses with the specific transaction type or `/v0/transactions/` for a transaction (also supports multiple transactions). I like downloading the JSON file and looking through it constantly. More transactions + edge cases are better to battle test your parser function.
-3. Add a new file or edit an existing one in `./src/parsers`. (refer to other files for general structures of what a parser function should look like)
-4. Export the function in `./src/parsers/index.ts`, add the transaction type to the `ProtonSupportedType` object in `./src/types/index.ts`, and add the transaction type with the corresponding parser function to the `protonParsers` object in `./src/types/index.ts`.
-5. Work on the parser function while testing it since it is now compatible with the UI.
-
-## Currently Supported Transactions
-
-|                      |                            |
-| -------------------- | -------------------------- |
-| **Transaction Type** | **File in `/src/parsers`** |
-| TRANSFER             | `/transfer.ts`             |
-| SWAP                 | `/swap.ts`                 |
-| BURN                 | `/burn.ts`                 |
-| BURN_NFT             | `/burn.ts`                 |
-| TOKEN_MINT           | `/token.ts`                |
-| NFT_MINT             | `/nft.ts`                  |
-| NFT_SALE             | `/nft.ts`                  |
-| NFT_LISTING          | `/nft.ts`                  |
-| NFT_CANCEL_LISTING   | `/nft.ts`                  |
-| NFT_BID              | `/nft.ts`                  |
-| NFT_BID_CANCELLED    | `/nft.ts`                  |
-| BORROW_FOX           | `/fox.ts`                  |
-| LOAN_FOX             | `/fox.ts`                  |
-| UNKNOWN              | `/unknown.ts`              |
+|                                         |                                                                                                                                                                      |
+| --------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 📄`./src/lib/parser/index.ts`           | UI calls the function in this file to parse transactions                                                                                                             |
+| 📄`./src/lib/parser/types.ts`           | Contains the types, interfaces, and enums needed to understand to work on the parser.                                                                                |
+| 📁`./src/lib/parser/parsers`            | Contains all parser methods.                                                                                                                                         |
+| 📄`./src/lib/parser/parsers/index.ts`   | Exports parser files in `./src/parsers`.                                                                                                                             |
+| 📄`./src/lib/parser/parsers/unknown.ts` | If there is no dedicated parser file for a Helius transaction type, they are parsed in this file. Changing the label on the UI is in `./apps/web/src/lib/config.ts`. |
+| 📁`./src/lib/parser/utils`              | Utility functions for the parser functions                                                                                                                           |
+| 📄`./src/lib/search.ts`                 | The function that resolves search inputs to a URL parameter.                                                                                                         |
 
 # 📦 @helius-labs/xray-database [WIP]
 
-A database for savaing metadata like transaction views or user details.
+A database for saving metadata like transaction views or user details.
diff --git a/apps/web/src/app.postcss b/apps/web/src/app.postcss
index 56ce81f6..08cbafcb 100644
--- a/apps/web/src/app.postcss
+++ b/apps/web/src/app.postcss
@@ -34,7 +34,12 @@ input::placeholder {
 }
 
 .card {
-    @apply rounded-lg border border-secondary bg-black p-3;
+    @apply rounded-lg border border-secondary bg-black p-3 transition-all duration-150;
+}
+
+a.card:hover,
+button.card:hover {
+    @apply border-[#fff]/50 bg-[#fff]/5;
 }
 
 .center {
@@ -49,6 +54,10 @@ input::placeholder {
     @apply fill-green-500;
 }
 
+.icon-stroke-success {
+    @apply stroke-green-500;
+}
+
 .icon-fill-black {
     @apply fill-black;
 }
diff --git a/apps/web/src/lib/components/account-header.svelte b/apps/web/src/lib/components/account-header.svelte
index e60b43cf..c5c5c9fb 100644
--- a/apps/web/src/lib/components/account-header.svelte
+++ b/apps/web/src/lib/components/account-header.svelte
@@ -1,3 +1,24 @@
+<style>
+    .username-block {
+        opacity: 90%;
+    }
+
+    .username-block:nth-child(3n + 2) {
+        background-color: #dbeafe;
+        color: #2563eb;
+    }
+
+    .username-block:nth-child(3n + 1) {
+        background-color: #fef08a;
+        color: #ca8a04;
+    }
+
+    .username-block:nth-child(3n + 3) {
+        background-color: #bbf7d0;
+        color: #16a34a;
+    }
+</style>
+
 <script lang="ts">
     import { page } from "$app/stores";
     import { trpcWithQuery } from "$lib/trpc/client";
@@ -8,6 +29,8 @@
     import formatMoney from "$lib/util/format-money";
 
     import CopyButton from "$lib/components/copy-button.svelte";
+    import Icon from "$lib/components/icon.svelte";
+    import Username from "$lib/components/providers/username-provider.svelte";
     import ShortenAddress from "./shorten-address.svelte";
 
     const client = trpcWithQuery($page);
@@ -35,33 +58,80 @@
     $: worth = $balance * $price?.data;
 </script>
 
-<div class="nav sticky top-16 z-30 bg-base-100 px-3 pt-2">
-    <div class="flex flex-wrap items-center justify-between bg-base-100">
-        <div class="flex items-center">
-            <h3 class="relative m-0 text-lg font-bold md:text-2xl">
-                <ShortenAddress address={account} />
-            </h3>
-            <div class="relative flex items-center">
-                <div class="my-2">
-                    <CopyButton text={account} />
-                    <CopyButton
-                        text={link}
-                        icon="link"
-                    />
+<Username
+    address={account}
+    let:usernames
+    let:usernameIsLoading
+>
+    <div class="nav sticky top-16 z-30 gap-2 bg-base-100 px-3 pt-2">
+        <div class="flex flex-col bg-base-100">
+            <div class="flex items-center justify-between">
+                <div class="flex items-center">
+                    <h3 class="relative m-0 text-lg font-bold md:text-2xl">
+                        <ShortenAddress address={account} />
+                    </h3>
+                    <div class="relative flex items-center">
+                        <div class="my-2">
+                            <CopyButton text={account} />
+                            <CopyButton
+                                text={link}
+                                icon="link"
+                            />
+                        </div>
+                    </div>
+                </div>
+                <div class="relative text-right">
+                    <h1 class="text-md md:block">
+                        <span class="">{$balance.toFixed(6)}</span>
+                        <span class="opacity-50">SOL</span>
+                    </h1>
+
+                    {#if !$price?.isLoading}
+                        <span class="ml-1 text-xs opacity-50 md:block"
+                            >{formatMoney(worth)} USD</span
+                        >
+                    {/if}
                 </div>
             </div>
-        </div>
-        <div class="relative text-right">
-            <h1 class="text-md md:block">
-                <span class="">{$balance.toFixed(6)}</span>
-                <span class="opacity-50">SOL</span>
-            </h1>
-
-            {#if !$price?.isLoading}
-                <span class="ml-1 text-xs opacity-50 md:block"
-                    >{formatMoney(worth)} USD</span
-                >
+            {#if usernameIsLoading}
+                <div class="flex flex-wrap gap-2 pt-2">
+                    {#each [1, 2, 3] as _}
+                        <div
+                            class="username-block inline-block h-6 w-[72px] animate-pulse rounded-full py-1 px-3 text-xs font-extrabold"
+                        />
+                    {/each}
+                </div>
+            {:else if usernames && usernames?.length > 0}
+                <div class="flex flex-wrap gap-2 pt-2">
+                    {#each usernames as username}
+                        {#if username.type === "backpack"}
+                            <div
+                                class="inline-block rounded-full bg-red-200/90 py-1 px-3 text-xs font-extrabold text-red-600/90"
+                            >
+                                <div
+                                    class="flex items-center justify-center gap-1"
+                                >
+                                    <Icon
+                                        id="backpack"
+                                        size="sm"
+                                    />
+                                    <!-- <span
+                                            class="flex items-center justify-center"
+                                        > -->
+                                    {username.username}
+                                    <!-- </span> -->
+                                </div>
+                            </div>
+                        {:else}
+                            <div
+                                class="username-block inline-block rounded-full py-1 px-3 text-xs font-extrabold"
+                            >
+                                {username.username}
+                            </div>
+                        {/if}
+                    {/each}
+                </div>
             {/if}
         </div>
     </div>
-</div>
+</Username>
diff --git a/apps/web/src/lib/components/collapse.svelte b/apps/web/src/lib/components/collapse.svelte
index d755b8b5..338e2b1c 100644
--- a/apps/web/src/lib/components/collapse.svelte
+++ b/apps/web/src/lib/components/collapse.svelte
@@ -1,11 +1,11 @@
 <script lang="ts">
     import Icon from "$lib/components/icon.svelte";
-    import type { Icon as IconType } from "$lib/types";
+    import type { Icon as IconType, NullableProp } from "$lib/types";
 
     export let iconId = "" as IconType;
-    export let sectionTitle = "";
+    export let sectionTitle: string = "";
+    export let sectionAditionalInfo: NullableProp<string | number> = null;
     export let hideIcon = false;
-
     export let showDetails = false;
 </script>
 
@@ -21,11 +21,17 @@
                     id={iconId}
                     size="md"
                     fill="success"
+                    stroke="success"
                 />
             </div>
         {/if}
-        <div class="ml-2">
+        <div class="ml-2 flex items-center gap-2">
             <p class="text-primary">{sectionTitle}</p>
+            {#if sectionAditionalInfo}
+                <span class="rounded-sm border bg-white/10 px-[0.4rem] text-sm"
+                    >{sectionAditionalInfo}</span
+                >
+            {/if}
         </div>
     </div>
     <div class="collapse-content">
diff --git a/apps/web/src/lib/components/icon.svelte b/apps/web/src/lib/components/icon.svelte
index 0ec2b9b3..35972af3 100644
--- a/apps/web/src/lib/components/icon.svelte
+++ b/apps/web/src/lib/components/icon.svelte
@@ -6,6 +6,7 @@
     export let id: Icon;
     export let path: string = "";
     export let fill: string = "current" as "current" | "success" | "base-100";
+    export let stroke: string = "current" as "current" | "success" | "base-100";
     export let size = "sm" as "xs" | "sm" | "md" | "lg";
 
     let el: SVGElement;
@@ -31,7 +32,8 @@
 
 <svg
     bind:this={el}
-    class="icon icon-{size} icon-fill-{fill}"
+    class="icon icon-{size} icon-fill-{fill} icon-stroke-{stroke}"
     viewBox="0 0 24 24"
+    preserveAspectRatio="xMidYMid meet"
     xmlns="http://www.w3.org/2000/svg"
 />
diff --git a/apps/web/src/lib/components/log-messages.svelte b/apps/web/src/lib/components/log-messages.svelte
index da59e228..604500d1 100644
--- a/apps/web/src/lib/components/log-messages.svelte
+++ b/apps/web/src/lib/components/log-messages.svelte
@@ -1,3 +1,62 @@
-<script>
+<style>
+    .text-sky {
+        @apply text-info-content;
+    }
+
+    .text-tangerine {
+        @apply text-[#e8a034];
+    }
+</style>
+
+<script lang="ts">
+    import { parseProgramLogs } from "$lib/util/program-logs";
+
     export let logs: string[];
+
+    const parsedLogs = parseProgramLogs(logs);
+
+    const totalComputeUnits = parsedLogs.reduce(
+        (sum, log) => sum + log.computeUnits,
+        0
+    );
 </script>
+
+<div class="pt-0">
+    {#each parsedLogs as instruction, idx}
+        {#if idx === 0}
+            <p class="px-3">
+                <span class="mb-1">
+                    {`#${idx + 1} - `}
+                </span>
+
+                <span>
+                    {`${instruction.invokedProgram} Instruction`}
+                </span>
+            </p>
+        {:else}
+            <p class="px-3 pt-3 pb-1">
+                <span class="mb-1">
+                    {`#${idx + 1} - `}
+                </span>
+
+                <span>
+                    {`${instruction.invokedProgram} Instruction`}
+                </span>
+            </p>
+        {/if}
+        {#each instruction.logs as log}
+            <p class={`px-3 pb-1 text-sm text-${log.style}`}>
+                <span class={`mr-1 text-${log.style}`}>{log.prefix}</span><span
+                    class={``}>{log.text}</span
+                >
+            </p>
+        {/each}
+    {/each}
+</div>
+
+{#if totalComputeUnits > 0}
+    <hr class="mx-3 my-1 border border-neutral opacity-80" />
+    <div class="px-3 pt-1 text-sm">
+        {`${totalComputeUnits} compute units consumed`}
+    </div>
+{/if}
diff --git a/apps/web/src/lib/components/providers/token-provider.svelte b/apps/web/src/lib/components/providers/token-provider.svelte
index 9b8f5683..3489fde8 100644
--- a/apps/web/src/lib/components/providers/token-provider.svelte
+++ b/apps/web/src/lib/components/providers/token-provider.svelte
@@ -19,14 +19,42 @@
         refetchOnWindowFocus: false,
     });
 
+    const accountInfo = client.accountInfo.createQuery(address, {
+        refetchOnMount: false,
+        refetchOnWindowFocus: false,
+    });
+
+    const token2022Metadata: {
+        [key: string]: {
+            description: string;
+            image: string;
+            name: string;
+        };
+    } = {
+        "2kMpEJCZL8vEDZe7YPLMCS9Y3WKSAMedXBn7xHPvsWvi": {
+            description: "Solana's 1 true moonshot. TW: @SolarMoonSol",
+            image: "https://gateway.ipfscdn.io/ipfs/bafkreifwdwgcv6fnh5icz3wkefokatsemsojck4hftsnuf4xcfjcvagsva/",
+            name: "SolarMoon (MOON)",
+        },
+        CKfatsPMUf8SkiURsDXs7eK6GWb4Jsd6UDbs7twMCWxo: {
+            description:
+                "BonkEarn is the first of many experiments on the Token2022 standard, Bernzy sends his regards",
+            image: "https://i.imgur.com/nd9AVZ4.jpeg",
+            name: "BonkEarn (BERN)",
+        },
+    };
+
     const metadata: UITokenMetadata = {
         address: "",
         attributes: [],
         collectionKey: "",
         creators: [],
+        delegate: "",
         description: "",
         image: "",
         name: "",
+        owner: "",
+        sellerFeeBasisPoints: 0,
     };
 
     const asset = client.asset.createQuery(address, {
@@ -49,12 +77,35 @@
         metadata.collectionKey = data?.collectionKey || "";
         metadata.image = data?.image || "";
         metadata.name = data?.name || "";
+        metadata.owner = data?.owner || "";
+        metadata.delegate = data?.delegate || "";
+        metadata.frozen = data?.frozen || false;
+        metadata.mutable = data?.mutable || false;
+        metadata.compressed = data?.compressed || false;
+        metadata.dataHash = data?.dataHash || "";
+        metadata.creatorHash = data?.creatorHash || "";
+        metadata.assetHash = data?.assetHash || "";
+        metadata.tree = data?.tree || "";
+        metadata.seq = data?.seq || 0;
+        metadata.leafId = data?.leafId || 0;
+    }
+    // TODO Property 'program' does not exist on type 'Buffer | ParsedAccountData'.
+    // @ts-ignore
+    else if ($accountInfo?.data?.value?.data?.program === "spl-token-2022") {
+        // const data = $accountInfo?.data?.value;
+        const data = token2022Metadata[address];
+        metadata.name = data.name || "";
+        metadata.description = data.description || "";
+        metadata.image = data.image || "";
+        metadata.address = address || "";
     } else {
         // Kicks off the query
         const data = $token?.data?.length ? $token.data[0] : {};
 
         metadata.address = data?.account;
         metadata.attributes = data?.offChainMetadata?.metadata?.attributes;
+        metadata.sellerFeeBasisPoints =
+            data?.onChainMetadata?.metadata?.data?.sellerFeeBasisPoints || 0;
         metadata.creators = data?.onChainMetadata?.metadata?.data?.creators;
         metadata.description = data?.offChainMetadata?.metadata?.description;
         metadata.collectionKey =
diff --git a/apps/web/src/lib/components/providers/username-provider.svelte b/apps/web/src/lib/components/providers/username-provider.svelte
new file mode 100644
index 00000000..69b13ca2
--- /dev/null
+++ b/apps/web/src/lib/components/providers/username-provider.svelte
@@ -0,0 +1,23 @@
+<script lang="ts">
+    import { page } from "$app/stores";
+
+    import { trpcWithQuery } from "$lib/trpc/client";
+
+    const client = trpcWithQuery($page);
+
+    export let address: string = "";
+
+    const usernameData = client.accountUsernames.createQuery(address, {
+        refetchOnMount: false,
+        refetchOnWindowFocus: false,
+    });
+
+    $: usernameIsLoading = $usernameData.isLoading;
+
+    $: usernames = $usernameData?.data || [];
+</script>
+
+<slot
+    {usernames}
+    {usernameIsLoading}
+/>
diff --git a/apps/web/src/lib/config.ts b/apps/web/src/lib/config.ts
index db1b7cf3..a3432539 100644
--- a/apps/web/src/lib/config.ts
+++ b/apps/web/src/lib/config.ts
@@ -31,6 +31,10 @@ export const transactionActionsMetadata: Record<
     ProtonActionType,
     TransactionActionMetadata
 > = {
+    ADD_ITEM: {
+        icon: "plus",
+        label: "Add Item",
+    },
     AIRDROP: {
         icon: "gift",
         label: "Airdropped",
@@ -57,6 +61,10 @@ export const transactionActionsMetadata: Record<
         icon: "flame",
         label: "Burned NFT",
     },
+    BUY_ITEM: {
+        icon: "sale",
+        label: "Buy Item",
+    },
     CANCEL_LOAN_REQUEST: {
         icon: "close",
         label: "Cancel Loan Request",
@@ -65,10 +73,26 @@ export const transactionActionsMetadata: Record<
         icon: "close",
         label: "Cancel Offer",
     },
+    CANCEL_ORDER: {
+        icon: "close",
+        label: "Cancel Order",
+    },
     CLAIM_NFT: {
         icon: "squareCheck",
         label: "Claim NFT",
     },
+    CLOSE_ITEM: {
+        icon: "close",
+        label: "Close Item",
+    },
+    CLOSE_ORDER: {
+        icon: "close",
+        label: "Close Item",
+    },
+    COMPRESSED_NFT_BURN: {
+        icon: "flame",
+        label: "Burned NFT",
+    },
     COMPRESSED_NFT_MINT: {
         icon: "mint",
         label: "NFT Mint",
@@ -77,11 +101,23 @@ export const transactionActionsMetadata: Record<
         icon: "lightning",
         label: "Transfer",
     },
+    CREATE_ORDER: {
+        icon: "plus",
+        label: "Create Order",
+    },
+    DELIST_ITEM: {
+        icon: "close",
+        label: "Delist Item",
+    },
     EXECUTE_TRANSACTION: {
         filterLabel: "Multisig Transaction",
         icon: "squad",
         label: "Multisig Transaction",
     },
+    FILL_ORDER: {
+        icon: "squareCheck",
+        label: "Fill Order",
+    },
     FORECLOSE_LOAN: {
         icon: "squareCheck",
         label: "Foreclose Loan",
@@ -94,10 +130,18 @@ export const transactionActionsMetadata: Record<
         icon: "handshake",
         label: "Lend",
     },
+    LIST_ITEM: {
+        icon: "list",
+        label: "List Item",
+    },
     LOAN_FOX: {
         icon: "handshake",
         label: "Loan Fox",
     },
+    MIGRATE_TO_PNFT: {
+        icon: "arrowRight",
+        label: "Migrate to pNFT",
+    },
     NFT_BID: {
         icon: "sale",
         label: "NFT Bid",
@@ -217,13 +261,25 @@ export const transactionActionsMetadata: Record<
         icon: "box",
         label: "Generic Transaction",
     },
+    UNSTAKE_TOKEN: {
+        icon: "cancel",
+        label: "Unstake Token",
+    },
+    UPDATE_ITEM: {
+        icon: "arrowUp",
+        label: "Update Item",
+    },
     UPDATE_OFFER: {
         icon: "cycle",
         label: "Update Offer",
     },
-    UNSTAKE_TOKEN: {
-        icon: "cancel",
-        label: "Unstake Token",
+    UPDATE_ORDER: {
+        icon: "arrowUp",
+        label: "Update Order",
+    },
+    UPGRADE_FOX_REQUEST: {
+        icon: "arrowUp",
+        label: "Upgrade Fox",
     },
     XNFT_INSTALL: {
         icon: "download",
@@ -363,4 +419,22 @@ export const enum IconPaths {
     newspaper = `<path d="M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2"></path><path d="M18 14h-8"></path><path d="M15 18h-5"></path><path d="M10 6h8v4h-8V6Z"></path>`,
 
     squareCheck = `<path d="m20 20h-15.25c-.414 0-.75.336-.75.75s.336.75.75.75h15.75c.53 0 1-.47 1-1v-15.75c0-.414-.336-.75-.75-.75s-.75.336-.75.75zm-1-17c0-.478-.379-1-1-1h-15c-.62 0-1 .519-1 1v15c0 .621.52 1 1 1h15c.478 0 1-.379 1-1zm-12.751 8.306c-.165-.147-.249-.351-.249-.556 0-.411.333-.746.748-.746.178 0 .355.062.499.19l2.371 2.011 4.453-4.962c.149-.161.35-.243.554-.243.417 0 .748.336.748.746 0 .179-.065.359-.196.503l-4.953 5.508c-.148.161-.35.243-.553.243-.177 0-.356-.063-.498-.19z" fill-rule="nonzero"/>`,
+
+    list = `<path d="m3.3 15.4c.717 0 1.3.583 1.3 1.3s-.583 1.3-1.3 1.3-1.3-.583-1.3-1.3.583-1.3 1.3-1.3zm2.7 1.85c0-.414.336-.75.75-.75h14.5c.414 0 .75.336.75.75s-.336.75-.75.75h-14.5c-.414 0-.75-.336-.75-.75zm-2.7-6.55c.717 0 1.3.583 1.3 1.3s-.583 1.3-1.3 1.3-1.3-.583-1.3-1.3.583-1.3 1.3-1.3zm2.7 1.3c0-.414.336-.75.75-.75h14.5c.414 0 .75.336.75.75s-.336.75-.75.75h-14.5c-.414 0-.75-.336-.75-.75zm-2.7-6c.717 0 1.3.583 1.3 1.3s-.583 1.3-1.3 1.3-1.3-.583-1.3-1.3.583-1.3 1.3-1.3zm2.7.75c0-.414.336-.75.75-.75h14.5c.414 0 .75.336.75.75s-.336.75-.75.75h-14.5c-.414 0-.75-.336-.75-.75z" fill-rule="nonzero"/>`,
+
+    key = `<path d="M16 2c3.309 0 6 2.691 6 6s-2.691 6-6 6-6-2.691-6-6 2.691-6 6-6zm0-2c-4.418 0-8 3.582-8 8s3.582 8 8 8 8-3.582 8-8-3.582-8-8-8zm-5.405 16.4l-1.472 1.6h-3.123v2h-2v2h-2v-2.179l5.903-5.976c-.404-.559-.754-1.158-1.038-1.795l-6.865 6.95v5h6v-2h2v-2h2l2.451-2.663c-.655-.249-1.276-.562-1.856-.937zm7.405-11.4c.551 0 1 .449 1 1s-.449 1-1 1-1-.449-1-1 .449-1 1-1zm0-1c-1.104 0-2 .896-2 2s.896 2 2 2 2-.896 2-2-.896-2-2-2z"/>`,
+
+    tree = `<path d="M13 24h-2v-4.829c-.695-.173-1.413-.502-1.951-.895-.5.15-1.019.225-1.549.225-3.033 0-5.5-2.505-5.5-5.584 0-1.283.421-2.494 1.197-3.477-.195-.496-.297-1.025-.297-1.565 0-2.025 1.403-3.721 3.298-4.12 1.042-2.27 3.301-3.755 5.802-3.755 2.501 0 4.761 1.485 5.803 3.756 1.894.398 3.297 2.094 3.297 4.119 0 .54-.102 1.07-.296 1.565.776.983 1.196 2.193 1.196 3.477 0 3.079-2.468 5.584-5.5 5.584-.528 0-1.046-.075-1.545-.224-.518.387-1.224.734-1.955.908v4.815zm-3.45-8.081c.948 1.371 2.191 1.384 2.506 1.384.341 0 1.567-.075 2.395-1.384.701.416 2.891 1.161 4.494-.438 1.389-1.392 1.615-4.14-.617-5.726 1.118-1.212.803-2.311.567-2.824-.343-.748-1.085-1.334-2.524-1.293-.416-1.98-2.462-3.638-4.371-3.638-1.894 0-3.986 1.616-4.37 3.638-1.245-.028-2.052.523-2.368 1.007-.325.5-.667 1.812.41 3.11-2.188 1.862-1.99 4.352-.616 5.726 1.866 1.864 4.011.648 4.494.438z"/>`,
+
+    cloudTransfer = `<path d="M16 16h-3v5h-2v-5h-3l4-4 4 4zm3.479-5.908c-.212-3.951-3.473-7.092-7.479-7.092s-7.267 3.141-7.479 7.092c-2.57.463-4.521 2.706-4.521 5.408 0 3.037 2.463 5.5 5.5 5.5h3.5v-2h-3.5c-1.93 0-3.5-1.57-3.5-3.5 0-2.797 2.479-3.833 4.433-3.72-.167-4.218 2.208-6.78 5.567-6.78 3.453 0 5.891 2.797 5.567 6.78 1.745-.046 4.433.751 4.433 3.72 0 1.93-1.57 3.5-3.5 3.5h-3.5v2h3.5c3.037 0 5.5-2.463 5.5-5.5 0-2.702-1.951-4.945-4.521-5.408z"/>`,
+
+    trees = `<path d="M6.514 24.015h-3v-3.39c-2.08-.638-3.5-2.652-3.5-5.04 0-1.19.202-1.693 1.774-5.603.521-1.294 1.195-2.97 2.068-5.179.204-.518.67-.806 1.17-.802.482.004.941.284 1.146.802.718 1.817 1.302 3.274 1.777 4.454.26-.596.567-1.288.928-2.103.694-1.565 1.591-3.592 2.754-6.265.258-.592.881-.906 1.397-.888.572.015 1.126.329 1.369.888 1.163 2.673 2.06 4.7 2.754 6.265 2.094 4.727 2.363 5.334 2.363 6.764 0 2.927-2.078 5.422-5 6.082v4.015h-3v-4.015c-.943-.213-1.797-.617-2.523-1.165-.612.845-1.466 1.48-2.477 1.79v3.39zm14.493-6c1.652 0 2.993 1.341 2.993 2.993s-1.341 2.993-2.993 2.993-2.993-1.341-2.993-2.993 1.341-2.993 2.993-2.993zm.007.993c1.104 0 2 .896 2 2s-.896 2-2 2-2-.896-2-2 .896-2 2-2zm-7.5 3.993v-3.839c4.906-.786 5-4.751 5-5.244 0-1.218-.216-1.705-2.277-6.359-2.134-4.82-2.721-6.198-2.755-6.261-.079-.145-.193-.292-.455-.297-.238 0-.37.092-.481.297-.034.063-.621 1.441-2.755 6.261-2.061 4.654-2.277 5.141-2.277 6.359 0 .493.094 4.458 5 5.244v3.839h1zm-6.123-12.448l-.08-.198c-1.589-3.957-2.04-5.116-2.067-5.171-.072-.151-.15-.226-.226-.228-.109 0-.188.13-.235.228-.028.05-.316.818-2.066 5.171-1.542 3.833-1.703 4.233-1.703 5.23 0 1.988 1.076 3.728 3.5 4.25v3.166h1v-3.166c1.266-.273 2.159-.876 2.725-1.666-1.078-1.12-1.725-2.619-1.725-4.251 0-.979.126-1.572.877-3.365z"/>`,
+
+    leaf = `<path d="M15.787 7.531c-5.107 2.785-12.72 9.177-15.787 15.469h2.939c.819-2.021 2.522-4.536 3.851-5.902 8.386 3.747 17.21-2.775 17.21-11.343 0-1.535-.302-3.136-.92-4.755-2.347 3.119-5.647 1.052-10.851 1.625-7.657.844-11.162 6.797-8.764 11.54 3.506-3.415 9.523-6.38 12.322-6.634z"/>`,
+
+    codeFork = `<path d="M21 3c0-1.657-1.343-3-3-3s-3 1.343-3 3c0 1.323.861 2.433 2.05 2.832.168 4.295-2.021 4.764-4.998 5.391-1.709.36-3.642.775-5.052 2.085v-7.492c1.163-.413 2-1.511 2-2.816 0-1.657-1.343-3-3-3s-3 1.343-3 3c0 1.305.837 2.403 2 2.816v12.367c-1.163.414-2 1.512-2 2.817 0 1.657 1.343 3 3 3s3-1.343 3-3c0-1.295-.824-2.388-1.973-2.808.27-3.922 2.57-4.408 5.437-5.012 3.038-.64 6.774-1.442 6.579-7.377 1.141-.425 1.957-1.514 1.957-2.803zm-16.8 0c0-.993.807-1.8 1.8-1.8s1.8.807 1.8 1.8-.807 1.8-1.8 1.8-1.8-.807-1.8-1.8zm3.6 18c0 .993-.807 1.8-1.8 1.8s-1.8-.807-1.8-1.8.807-1.8 1.8-1.8 1.8.807 1.8 1.8zm10.2-16.2c-.993 0-1.8-.807-1.8-1.8s.807-1.8 1.8-1.8 1.8.807 1.8 1.8-.807 1.8-1.8 1.8z"/>`,
+
+    hourglass = `<path d="M18.513 7.119c.958-1.143 1.487-2.577 1.487-4.036v-3.083h-16v3.083c0 1.459.528 2.892 1.487 4.035l3.087 3.68c.566.677.57 1.625.009 2.306l-3.13 3.794c-.937 1.136-1.453 2.555-1.453 3.995v3.107h16v-3.107c0-1.44-.517-2.858-1.453-3.994l-3.13-3.794c-.562-.681-.558-1.629.009-2.306l3.087-3.68zm-.513-4.12c0 1.101-.363 2.05-1.02 2.834l-.978 1.167h-8.004l-.978-1.167c-.66-.785-1.02-1.736-1.02-2.834h12zm-.996 15.172c.652.791.996 1.725.996 2.829h-1.061c-1.939-2-4.939-2-4.939-2s-3 0-4.939 2h-1.061c0-1.104.344-2.039.996-2.829l3.129-3.793c.342-.415.571-.886.711-1.377h.164v1h2v-1h.163c.141.491.369.962.711 1.376l3.13 3.794zm-6.004-1.171h2v1h-2v-1zm0-2h2v1h-2v-1z"/>`,
+
+    percentage = `<path fill-rule="evenodd" clip-rule="evenodd" d="M0.836838 0.836838C1.37266 0.301021 2.09938 2.12874e-08 2.85714 2.12874e-08C3.61491 2.12874e-08 4.34163 0.301021 4.87745 0.836838C5.41327 1.37266 5.71429 2.09938 5.71429 2.85714C5.71429 3.61491 5.41327 4.34163 4.87745 4.87745C4.34163 5.41327 3.61491 5.71429 2.85714 5.71429C2.09938 5.71429 1.37266 5.41327 0.836838 4.87745C0.301021 4.34163 2.12874e-08 3.61491 2.12874e-08 2.85714C2.12874e-08 2.09938 0.301021 1.37266 0.836838 0.836838ZM19.5816 0.418419C20.1395 0.976311 20.1395 1.88083 19.5816 2.43872L2.43872 19.5816C1.88083 20.1395 0.976311 20.1395 0.418419 19.5816C-0.139473 19.0237 -0.139473 18.1192 0.418419 17.5613L17.5613 0.418419C18.1192 -0.139473 19.0237 -0.139473 19.5816 0.418419ZM15.1226 15.1226C15.6584 14.5867 16.3851 14.2857 17.1429 14.2857C17.9006 14.2857 18.6273 14.5867 19.1632 15.1226C19.699 15.6584 20 16.3851 20 17.1429C20 17.9006 19.699 18.6273 19.1632 19.1632C18.6273 19.699 17.9006 20 17.1429 20C16.3851 20 15.6584 19.699 15.1226 19.1632C14.5867 18.6273 14.2857 17.9006 14.2857 17.1429C14.2857 16.3851 14.5867 15.6584 15.1226 15.1226Z"/>`,
 }
diff --git a/apps/web/src/lib/trpc/router.ts b/apps/web/src/lib/trpc/router.ts
index 5c0495fc..f972c6da 100644
--- a/apps/web/src/lib/trpc/router.ts
+++ b/apps/web/src/lib/trpc/router.ts
@@ -3,12 +3,15 @@ import type { Context } from "$lib/trpc/context";
 import { initTRPC } from "@trpc/server";
 
 import { accountInfo } from "$lib/trpc/routes/account-info";
+import { accountUsernames } from "$lib/trpc/routes/account-usernames";
 import { asset } from "$lib/trpc/routes/asset";
 import { balances } from "$lib/trpc/routes/balances";
+import { concurrentMerkleTree } from "$lib/trpc/routes/concurrent-merkle-tree";
 import { currentSlot } from "$lib/trpc/routes/current-slot";
 import { price } from "$lib/trpc/routes/price";
 import { rawTransaction } from "$lib/trpc/routes/raw-transaction";
 import { token } from "$lib/trpc/routes/token";
+import { token2022 } from "$lib/trpc/routes/token2022";
 import { tps } from "$lib/trpc/routes/tps";
 import { transaction } from "$lib/trpc/routes/transaction";
 import { transactions } from "$lib/trpc/routes/transactions";
@@ -18,13 +21,16 @@ export const t = initTRPC.context<Context>().create();
 
 export const router = t.router({
     accountInfo,
+    accountUsernames,
     asset,
     balances,
     blockTransactions,
+    concurrentMerkleTree,
     currentSlot,
     price,
     rawTransaction,
     token,
+    token2022,
     tps,
     transaction,
     transactions,
diff --git a/apps/web/src/lib/trpc/routes/account-usernames.ts b/apps/web/src/lib/trpc/routes/account-usernames.ts
new file mode 100644
index 00000000..bc47d526
--- /dev/null
+++ b/apps/web/src/lib/trpc/routes/account-usernames.ts
@@ -0,0 +1,57 @@
+import { t } from "$lib/trpc/t";
+
+import { z } from "zod";
+
+const { HELIUS_KEY } = process.env;
+
+interface Username {
+    type: "bonfida" | "backpack";
+    username: string;
+}
+
+const getBackpackUsername = async (usernames: Username[], address = "") => {
+    const response = await fetch(
+        `https://xnft-api-server.xnfts.dev/v1/users/fromPubkey?publicKey=${address}&blockchain=solana`
+    );
+    const data = await response.json();
+
+    if (data?.user?.username) {
+        usernames.push({
+            type: "backpack",
+            username: data.user.username,
+        });
+    }
+};
+
+const getSolanaDomain = async (usernames: Username[], address = "") => {
+    const url = `https://api.helius.xyz/v0/addresses/${address}/names?api-key=${HELIUS_KEY}`;
+    const response = await fetch(url);
+    const data = await response.json();
+
+    if (data?.domainNames) {
+        for (const domain of data.domainNames) {
+            usernames.push({
+                type: "bonfida",
+                username: `${domain}.sol`,
+            });
+        }
+    }
+};
+
+export const accountUsernames = t.procedure
+    .input(z.string())
+    .output(
+        z.array(
+            z.object({
+                type: z.string(),
+                username: z.string(),
+            })
+        )
+    )
+    .query(async ({ input: address }) => {
+        const usernames: Username[] = [];
+        await getBackpackUsername(usernames, address);
+        await getSolanaDomain(usernames, address);
+
+        return usernames || [];
+    });
diff --git a/apps/web/src/lib/trpc/routes/asset.ts b/apps/web/src/lib/trpc/routes/asset.ts
index 1a993bc5..68815385 100644
--- a/apps/web/src/lib/trpc/routes/asset.ts
+++ b/apps/web/src/lib/trpc/routes/asset.ts
@@ -24,13 +24,24 @@ export const asset = t.procedure.input(z.string()).query(async ({ input }) => {
     const data = await response.json();
     let metadata = {
         address: "",
+        assetHash: "",
         attributes: [],
         collectionKey: "",
         compressed: false,
+        creatorHash: "",
         creators: [],
+        dataHash: "",
+        delegate: "",
         description: "",
+        frozen: false,
         image: "",
+        leafId: 0,
+        mutable: false,
         name: "",
+        owner: "",
+        sellerFeeBasisPoints: 0,
+        seq: 0,
+        tree: "",
     };
 
     if (data?.result?.compression?.compressed === true) {
@@ -39,13 +50,26 @@ export const asset = t.procedure.input(z.string()).query(async ({ input }) => {
 
         metadata = {
             address: data?.result?.id || "",
+            assetHash: data?.result?.compression?.asset_hash,
             attributes: returnAssetData?.attributes || [],
             collectionKey: data?.result?.grouping[0]?.group_value || "",
             compressed: true,
+            creatorHash: data?.result?.compression?.creator_hash,
             creators: data?.result?.creators || [],
+            dataHash: data?.result?.compression?.data_hash,
+            delegate: data?.result?.ownership?.delegated
+                ? data?.result?.ownership?.delegate
+                : "",
             description: returnAssetData?.description || "",
+            frozen: data?.result?.ownership?.frozen,
             image: returnAssetData?.image || "",
+            leafId: data?.result?.compression?.leaf_id,
+            mutable: data?.result?.mutable,
             name: returnAssetData?.name || "",
+            owner: data?.result?.ownership?.owner || "",
+            sellerFeeBasisPoints: data?.result?.sellerFeeBasisPoints || 0,
+            seq: data?.result?.compression?.seq,
+            tree: data?.result?.compression?.tree,
         };
     }
     return metadata;
diff --git a/apps/web/src/lib/trpc/routes/concurrent-merkle-tree.ts b/apps/web/src/lib/trpc/routes/concurrent-merkle-tree.ts
new file mode 100644
index 00000000..8e16ab14
--- /dev/null
+++ b/apps/web/src/lib/trpc/routes/concurrent-merkle-tree.ts
@@ -0,0 +1,40 @@
+// https://github.com/solana-labs/explorer/blob/master/app/components/account/ConcurrentMerkleTreeCard.tsx
+
+import { t } from "$lib/trpc/t";
+import { connect } from "@helius-labs/xray";
+import { ConcurrentMerkleTreeAccount } from "@solana/spl-account-compression";
+import { PublicKey } from "@solana/web3.js";
+import { z } from "zod";
+
+const { HELIUS_KEY } = process.env;
+
+export const concurrentMerkleTree = t.procedure
+    .input(z.string())
+    .query(async ({ input: address }) => {
+        const connection = connect("mainnet", HELIUS_KEY);
+        const pubkey = new PublicKey(address);
+        const cmt = await ConcurrentMerkleTreeAccount.fromAccountAddress(
+            connection,
+            pubkey
+        );
+
+        const authority = cmt.getAuthority();
+        const root = cmt.getCurrentRoot();
+        const seq = cmt.getCurrentSeq().toString();
+        const canopyDepth = cmt.getCanopyDepth();
+        const maxBufferSize = cmt.getMaxBufferSize();
+        const treeHeight = cmt.getMaxDepth();
+        const creationSlot = cmt.getCreationSlot().toNumber();
+        const rightMostIndex = cmt.tree.rightMostPath.index;
+
+        return {
+            authority,
+            canopyDepth,
+            creationSlot,
+            maxBufferSize,
+            rightMostIndex,
+            root,
+            seq,
+            treeHeight,
+        };
+    });
diff --git a/apps/web/src/lib/trpc/routes/token2022.ts b/apps/web/src/lib/trpc/routes/token2022.ts
new file mode 100644
index 00000000..9fdf2180
--- /dev/null
+++ b/apps/web/src/lib/trpc/routes/token2022.ts
@@ -0,0 +1,56 @@
+import { t } from "$lib/trpc/t";
+import { PublicKey } from "@solana/web3.js";
+import { z } from "zod";
+
+const { HELIUS_KEY } = process.env;
+
+export const token2022 = t.procedure
+    .input(z.string())
+    .query(async ({ input }) => {
+        const TOKEN_2022_PROGRAM_ID = new PublicKey(
+            "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"
+        );
+
+        const walletPublicKey = new PublicKey(input);
+        const url = `https://rpc.helius.xyz/?api-key=${HELIUS_KEY}`;
+
+        const response = await fetch(url, {
+            body: JSON.stringify({
+                id: "accounts",
+                jsonrpc: "2.0",
+                method: "getTokenAccountsByOwner",
+                params: [
+                    walletPublicKey,
+                    {
+                        programId: TOKEN_2022_PROGRAM_ID,
+                    },
+                    {
+                        commitment: "confirmed",
+                        encoding: "jsonParsed",
+                    },
+                ],
+            }),
+            headers: {
+                "Content-Type": "application/json",
+            },
+            method: "POST",
+        }).then((res) => res.json());
+
+        type Accounts = {
+            amount: number;
+            mint: string;
+        };
+
+        // TODO: any type on this
+        const accounts: Accounts[] = response?.result?.value?.map(
+            (account: any) => {
+                return {
+                    amount: account.account.data.parsed.info.tokenAmount
+                        .uiAmount,
+                    mint: account.account.data.parsed.info.mint,
+                };
+            }
+        );
+
+        return accounts;
+    });
diff --git a/apps/web/src/lib/types.ts b/apps/web/src/lib/types.ts
index 038fab95..7db3c5b8 100644
--- a/apps/web/src/lib/types.ts
+++ b/apps/web/src/lib/types.ts
@@ -46,8 +46,20 @@ export interface UITokenMetadata {
     collectionKey: string;
     description?: string;
     attributes?: UITokenMetadataAttribute[];
+    sellerFeeBasisPoints?: number;
     creators?: UITokenMetadataCreators[];
     price?: number;
+    owner: string;
+    delegate?: string;
+    frozen?: boolean;
+    mutable?: boolean;
+    compressed?: boolean;
+    dataHash?: string;
+    creatorHash?: string;
+    assetHash?: string;
+    tree?: string;
+    seq?: number;
+    leafId?: number;
 }
 
 export type Icon = keyof typeof IconPaths;
@@ -85,3 +97,5 @@ export interface Modal {
 }
 
 export type Modals = keyof typeof modals;
+
+export type NullableProp<T> = T | null | undefined;
diff --git a/apps/web/src/lib/util/percentage.ts b/apps/web/src/lib/util/percentage.ts
new file mode 100644
index 00000000..fddc366c
--- /dev/null
+++ b/apps/web/src/lib/util/percentage.ts
@@ -0,0 +1,3 @@
+/** Converts metaplex sellerFeeBasisPoints to a "pretty" percentage based string */
+export default (sellerFeeBasisPoints: number): string =>
+    `${sellerFeeBasisPoints / 100}%`;
diff --git a/apps/web/src/lib/util/program-logs.ts b/apps/web/src/lib/util/program-logs.ts
new file mode 100644
index 00000000..691dbfe0
--- /dev/null
+++ b/apps/web/src/lib/util/program-logs.ts
@@ -0,0 +1,144 @@
+// https://github.com/solana-labs/explorer/blob/master/src/utils/program-logs.ts
+
+import { getProgramName } from "./program-name";
+
+export type LogMessage = {
+    text: string;
+    prefix: string;
+    style: "sky" | "success" | "error" | "tangerine" | "neutral";
+};
+
+export type InstructionLogs = {
+    invokedProgram: string | null;
+    programAddress: string;
+    logs: LogMessage[];
+    computeUnits: number;
+    truncated: boolean;
+    failed: boolean;
+};
+
+export const parseProgramLogs = (logs: string[]) => {
+    let depth = 0;
+    let parsedLogs: InstructionLogs[] = [];
+
+    function prefixBuilder(
+        // Indent level starts at 1.
+        indentLevel: number
+    ) {
+        let prefix;
+        if (indentLevel <= 0) {
+            // Log should always be at index level 1 or higher
+            prefix = "";
+        } else {
+            prefix = new Array(indentLevel - 1)
+                .fill("\u00A0\u00A0\u00A0\u00A0")
+                .join("");
+        }
+        return prefix + "> ";
+    }
+
+    logs.forEach((log) => {
+        if (log.startsWith("Program log:")) {
+            log = log.replace(/Program log: (.*)/g, (match, p1) => {
+                return `Logged "${p1}"`;
+            });
+
+            parsedLogs[parsedLogs.length - 1].logs.push({
+                prefix: prefixBuilder(depth),
+                style: "tangerine",
+                text: log,
+            });
+        } else if (log.startsWith("Log truncated")) {
+            parsedLogs[parsedLogs.length - 1].truncated = true;
+        } else {
+            const regex = /Program (\w*) invoke \[(\d)\]/g;
+            const matches = [...log.matchAll(regex)];
+
+            if (matches.length > 0) {
+                const programAddress = matches[0][1];
+                const programName = getProgramName(programAddress);
+
+                if (depth === 0) {
+                    parsedLogs.push({
+                        computeUnits: 0,
+                        failed: false,
+                        invokedProgram: programName,
+                        logs: [],
+                        programAddress,
+                        truncated: false,
+                    });
+                } else {
+                    parsedLogs[parsedLogs.length - 1].logs.push({
+                        prefix: prefixBuilder(depth),
+                        style: "sky",
+                        text: `Invoked ${programName}`,
+                    });
+                }
+
+                depth++;
+            } else if (log.includes("success")) {
+                parsedLogs[parsedLogs.length - 1].logs.push({
+                    prefix: prefixBuilder(depth),
+                    style: "success",
+                    text: `Returned success`,
+                });
+                depth--;
+            } else if (log.includes("failed")) {
+                const instructionLog = parsedLogs[parsedLogs.length - 1];
+                instructionLog.failed = true;
+
+                let currText = `Returned error "${log.slice(
+                    log.indexOf(": ") + 2
+                )}"`;
+                // failed to verify log of previous program so reset depth and print full log
+                if (log.startsWith("failed")) {
+                    depth++;
+                    currText = log.charAt(0).toUpperCase() + log.slice(1);
+                }
+
+                instructionLog.logs.push({
+                    prefix: prefixBuilder(depth),
+                    style: "error",
+                    text: currText,
+                });
+                depth--;
+            } else {
+                if (depth === 0) {
+                    parsedLogs.push({
+                        computeUnits: 0,
+                        failed: false,
+                        invokedProgram: null,
+                        logs: [],
+                        programAddress: "",
+                        truncated: false,
+                    });
+                    depth++;
+                }
+
+                // Remove redundant program address from logs
+                log = log.replace(
+                    /Program \w* consumed (\d*) (.*)/g,
+                    (match, p1, p2) => {
+                        // Only aggregate compute units consumed from top-level tx instructions
+                        // because they include inner ix compute units as well.
+                        if (depth === 1) {
+                            parsedLogs[parsedLogs.length - 1].computeUnits +=
+                                Number.parseInt(p1);
+                        }
+
+                        return `Consumed ${p1} ${p2}`;
+                    }
+                );
+
+                // native program logs don't start with "Program log:"
+                parsedLogs[parsedLogs.length - 1].logs.push({
+                    prefix: prefixBuilder(depth),
+                    style: "neutral",
+                    text: log,
+                });
+            }
+        }
+    });
+
+    return parsedLogs;
+};
diff --git a/apps/web/src/lib/util/program-name.ts b/apps/web/src/lib/util/program-name.ts
new file mode 100644
index 00000000..7247c187
--- /dev/null
+++ b/apps/web/src/lib/util/program-name.ts
@@ -0,0 +1,390 @@
+// Default Program Name : https://github.com/solana-labs/explorer/blob/master/src/utils/tx.ts
+
+import {
+    BPF_LOADER_DEPRECATED_PROGRAM_ID,
+    BPF_LOADER_PROGRAM_ID,
+    Ed25519Program,
+    SYSVAR_CLOCK_PUBKEY,
+    SYSVAR_RENT_PUBKEY,
+    SYSVAR_REWARDS_PUBKEY,
+    SYSVAR_STAKE_HISTORY_PUBKEY,
+    Secp256k1Program,
+    StakeProgram,
+    SystemProgram,
+    VOTE_PROGRAM_ID,
+} from "@solana/web3.js";
+
+export enum PROGRAM_NAMES {
+    // native built-ins
+    ADDRESS_LOOKUP_TABLE = "Address Lookup Table Program",
+    COMPUTE_BUDGET = "Compute Budget Program",
+    CONFIG = "Config Program",
+    STAKE = "Stake Program",
+    SYSTEM = "System Program",
+    VOTE = "Vote Program",
+
+    // native precompiles
+    SECP256K1 = "Secp256k1 SigVerify Precompile",
+    ED25519 = "Ed25519 SigVerify Precompile",
+
+    // spl
+    ASSOCIATED_TOKEN = "Associated Token Program",
+    ACCOUNT_COMPRESSION = "Account Compression Program",
+    FEATURE_PROPOSAL = "Feature Proposal Program",
+    LENDING = "Lending Program",
+    MEMO = "Memo Program",
+    MEMO_2 = "Memo Program v2",
+    NAME = "Name Service Program",
+    STAKE_POOL = "Stake Pool Program",
+    SWAP = "Swap Program",
+    TOKEN = "Token Program",
+    TOKEN_METADATA = "Token Metadata Program",
+    TOKEN_VAULT = "Token Vault Program",
+
+    // other
+    ACUMEN = "Acumen Program",
+    BREAK_SOLANA = "Break Solana Program",
+    CHAINLINK_ORACLE = "Chainlink OCR2 Oracle Program",
+    CHAINLINK_STORE = "Chainlink Store Program",
+    CLOCKWORK_1 = "Clockwork Thread Program v1",
+    CLOCKWORK_2 = "Clockwork Thread Program v2",
+    MANGO_GOVERNANCE = "Mango Governance Program",
+    MANGO_ICO = "Mango ICO Program",
+    MANGO_1 = "Mango Program v1",
+    MANGO_2 = "Mango Program v2",
+    MANGO_3 = "Mango Program v3",
+    MARINADE = "Marinade Staking Program",
+    MERCURIAL = "Mercurial Stable Swap Program",
+    METAPLEX = "Metaplex Program",
+    NFT_AUCTION = "NFT Auction Program",
+    NFT_CANDY_MACHINE = "NFT Candy Machine Program",
+    NFT_CANDY_MACHINE_V2 = "NFT Candy Machine Program V2",
+    ORCA_SWAP_1 = "Orca Swap Program v1",
+    ORCA_SWAP_2 = "Orca Swap Program v2",
+    ORCA_AQUAFARM = "Orca Aquafarm Program",
+    PORT = "Port Finance Program",
+    PYTH_DEVNET = "Pyth Oracle Program",
+    PYTH_TESTNET = "Pyth Oracle Program",
+    PYTH_MAINNET = "Pyth Oracle Program",
+    QUARRY_MERGE_MINE = "Quarry Merge Mine",
+    QUARRY_MINE = "Quarry Mine",
+    QUARRY_MINT_WRAPPER = "Quarry Mint Wrapper",
+    QUARRY_REDEEMER = "Quarry Redeemer",
+    QUARRY_REGISTRY = "Quarry Registry",
+    RAYDIUM_AMM = "Raydium AMM Program",
+    RAYDIUM_IDO = "Raydium IDO Program",
+    RAYDIUM_LP_1 = "Raydium Liquidity Pool Program v1",
+    RAYDIUM_LP_2 = "Raydium Liquidity Pool Program v2",
+    RAYDIUM_STAKING = "Raydium Staking Program",
+    SABER_ROUTER = "Saber Router Program",
+    SABER_SWAP = "Saber Stable Swap Program",
+    SERUM_1 = "Serum Dex Program v1",
+    SERUM_2 = "Serum Dex Program v2",
+    SERUM_3 = "Serum Dex Program v3",
+    SERUM_SWAP = "Serum Swap Program",
+    SERUM_POOL = "Serum Pool",
+    SOLEND = "Solend Program",
+    SOLIDO = "Lido for Solana Program",
+    STEP_SWAP = "Step Finance Swap Program",
+    SWIM_SWAP = "Swim Swap Program",
+    SWITCHBOARD = "Switchboard Oracle Program",
+    WORMHOLE = "Wormhole",
+    WORMHOLE_CORE = "Wormhole Core Bridge",
+    WORMHOLE_TOKEN = "Wormhole Token Bridge",
+    WORMHOLE_NFT = "Wormhole NFT Bridge",
+    SOLANART = "Solanart",
+    SOLANART_GO = "Solanart - Global offers",
+    STEPN_DEX = "STEPN Dex",
+    OPENBOOK_DEX = "OpenBook Dex",
+}
+
+export type ProgramInfo = {
+    name: string;
+};
+
+export const PROGRAM_INFO_BY_ID: { [address: string]: ProgramInfo } = {
+    "22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD": {
+        name: PROGRAM_NAMES.SERUM_SWAP,
+    },
+
+    "27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv": {
+        name: PROGRAM_NAMES.RAYDIUM_LP_2,
+    },
+    [StakeProgram.programId.toBase58()]: {
+        name: PROGRAM_NAMES.STAKE,
+    },
+    [SystemProgram.programId.toBase58()]: {
+        name: PROGRAM_NAMES.SYSTEM,
+    },
+    [VOTE_PROGRAM_ID.toBase58()]: {
+        name: PROGRAM_NAMES.VOTE,
+    },
+
+    // native precompiles
+    [Secp256k1Program.programId.toBase58()]: {
+        name: PROGRAM_NAMES.SECP256K1,
+    },
+    [Ed25519Program.programId.toBase58()]: {
+        name: PROGRAM_NAMES.ED25519,
+    },
+
+    "3XXuUFfweXBwFgFfYaejLvZE4cGZiHgKiGfMtdxNzYmv": {
+        name: PROGRAM_NAMES.CLOCKWORK_1,
+    },
+
+    "5ZfZAwP2m93waazg8DkrrVmsupeiPEvaEHowiUP7UAbJ": {
+        name: PROGRAM_NAMES.SOLANART_GO,
+    },
+
+    "5fNfvyp5czQVX77yoACa3JJVEhdRaWjPuazuWgjhTqEH": {
+        name: PROGRAM_NAMES.MANGO_2,
+    },
+
+    "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8": {
+        name: PROGRAM_NAMES.RAYDIUM_AMM,
+    },
+
+    "7sPptkymzvayoSbLXzBsXEF8TSf3typNnAWkrKrDizNb": {
+        name: PROGRAM_NAMES.MANGO_ICO,
+    },
+
+    "82yxjeMsvaURa4MbZZ7WZZHfobirZYkH1zF8fmeGtyaQ": {
+        name: PROGRAM_NAMES.ORCA_AQUAFARM,
+    },
+
+    "9HzJyW1qZsEiSfMUf6L2jo3CcTKAyBmSyKdwQeYisHrC": {
+        name: PROGRAM_NAMES.RAYDIUM_IDO,
+    },
+
+    "9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP": {
+        name: PROGRAM_NAMES.ORCA_SWAP_2,
+    },
+
+    "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin": {
+        name: PROGRAM_NAMES.SERUM_3,
+    },
+
+    // spl
+    ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL: {
+        name: PROGRAM_NAMES.ASSOCIATED_TOKEN,
+    },
+
+    // native built-ins
+    AddressLookupTab1e1111111111111111111111111: {
+        name: PROGRAM_NAMES.ADDRESS_LOOKUP_TABLE,
+    },
+
+    BJ3jrUzddfuSrZHXSCxMUUQsjKEyLmuuyZebkcaFp2fg: {
+        name: PROGRAM_NAMES.SERUM_1,
+    },
+
+    BrEAK7zGZ6dM71zUDACDqJnekihmwF15noTddWTsknjC: {
+        name: PROGRAM_NAMES.BREAK_SOLANA,
+    },
+    // other
+    C64kTdg1Hzv5KoQmZrQRcm2Qz7PkxtFBgw7EpFhvYn8W: {
+        name: PROGRAM_NAMES.ACUMEN,
+    },
+    CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz: {
+        name: PROGRAM_NAMES.SOLANART,
+    },
+    CLoCKyJ6DXBJqqu2VWx9RLbgnwwR6BMHHuyasVmfMzBh: {
+        name: PROGRAM_NAMES.CLOCKWORK_2,
+    },
+    ComputeBudget111111111111111111111111111111: {
+        name: PROGRAM_NAMES.COMPUTE_BUDGET,
+    },
+    Config1111111111111111111111111111111111111: {
+        name: PROGRAM_NAMES.CONFIG,
+    },
+    CrX7kMhLC3cSsXJdT7JDgqrRVWGnUpX3gfEfxxU2NVLi: {
+        name: PROGRAM_NAMES.SOLIDO,
+    },
+    Crt7UoUR6QgrFrN7j8rmSQpUTNWNSitSwWvsWGf1qZ5t: {
+        name: PROGRAM_NAMES.SABER_ROUTER,
+    },
+
+    DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1: {
+        name: PROGRAM_NAMES.ORCA_SWAP_1,
+    },
+    Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j: {
+        name: PROGRAM_NAMES.STEPN_DEX,
+    },
+    DtmE9D2CSB4L5D6A15mraeEjrGMm6auWVzgaD8hK2tZM: {
+        name: PROGRAM_NAMES.SWITCHBOARD,
+    },
+    EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o: {
+        name: PROGRAM_NAMES.SERUM_2,
+    },
+    EhhTKczWMGQt46ynNeRX1WfeagwwJd7ufHvCDjRxjo5Q: {
+        name: PROGRAM_NAMES.RAYDIUM_STAKING,
+    },
+    Feat1YXHhH6t1juaWF74WLcfv4XoNocjXA6sPWHNgAse: {
+        name: PROGRAM_NAMES.FEATURE_PROPOSAL,
+    },
+    FsJ3A3u2vn5cTVofAjvy6y5kwABJAqYWpe4975bi2epH: {
+        name: PROGRAM_NAMES.PYTH_MAINNET,
+    },
+    GqTPL6qRf5aUuqscLh8Rg2HTxPUXfhhAXDptTLhp1t2J: {
+        name: PROGRAM_NAMES.MANGO_GOVERNANCE,
+    },
+    HEvSKofvBgfaexv23kMabbYqxasxU3mQ4ibBMEmJWHny: {
+        name: PROGRAM_NAMES.CHAINLINK_STORE,
+    },
+    JD3bq9hGdy38PuWQ4h2YJpELmHVGPPfFSuFkpzAd9zfu: {
+        name: PROGRAM_NAMES.MANGO_1,
+    },
+    LendZqTs7gn5CTSJU1jWKhKuVpjJGom45nnwPb2AMTi: {
+        name: PROGRAM_NAMES.LENDING,
+    },
+    MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky: {
+        name: PROGRAM_NAMES.MERCURIAL,
+    },
+    MarBmsSgKXdrN1egZf5sqe1TMai9K1rChYNDJgjq7aD: {
+        name: PROGRAM_NAMES.MARINADE,
+    },
+    Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo: {
+        name: PROGRAM_NAMES.MEMO,
+    },
+    MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr: {
+        name: PROGRAM_NAMES.MEMO_2,
+    },
+    Port7uDYB3wk6GJAw4KT1WpTeMtSu9bTcChBHkX2LfR: {
+        name: PROGRAM_NAMES.PORT,
+    },
+    QMMD16kjauP5knBwxNUJRZ1Z5o3deBuFrqVjBVmmqto: {
+        name: PROGRAM_NAMES.QUARRY_MERGE_MINE,
+    },
+    QMNeHCGYnLVDn1icRAfQZpjPLBNkfGbSKRB83G5d8KB: {
+        name: PROGRAM_NAMES.QUARRY_MINE,
+    },
+    QMWoBmAyJLAsA1Lh9ugMTw2gciTihncciphzdNzdZYV: {
+        name: PROGRAM_NAMES.QUARRY_MINT_WRAPPER,
+    },
+    QRDxhMw1P2NEfiw5mYXG79bwfgHTdasY2xNP76XSea9: {
+        name: PROGRAM_NAMES.QUARRY_REDEEMER,
+    },
+    QREGBnEj9Sa5uR91AV8u3FxThgP5ZCvdZUW2bHAkfNc: {
+        name: PROGRAM_NAMES.QUARRY_REGISTRY,
+    },
+    RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr: {
+        name: PROGRAM_NAMES.RAYDIUM_LP_1,
+    },
+    SPoo1Ku8WFXoNDMHPsrGSTSG1Y47rzgn41SLUNakuHy: {
+        name: PROGRAM_NAMES.STAKE_POOL,
+    },
+    SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1: {
+        name: PROGRAM_NAMES.STEP_SWAP,
+    },
+    SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ: {
+        name: PROGRAM_NAMES.SABER_SWAP,
+    },
+    SWiMDJYFUGj6cPrQ6QYYYWZtvXQdRChSVAygDZDsCHC: {
+        name: PROGRAM_NAMES.SWIM_SWAP,
+    },
+    So1endDq2YkqhipRh3WViPa8hdiSpxWy6z3Z6tMCpAo: {
+        name: PROGRAM_NAMES.SOLEND,
+    },
+    SwaPpA9LAaLfeLi3a68M4DjnLqgtticKg6CnyNwgAC8: {
+        name: PROGRAM_NAMES.SWAP,
+    },
+    TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA: {
+        name: PROGRAM_NAMES.TOKEN,
+    },
+    WnFt12ZrnzZrFZkt2xsNsaNWoQribnuQ5B5FrDbwDhD: {
+        name: PROGRAM_NAMES.WORMHOLE_NFT,
+    },
+    WormT3McKhFJ2RkiGpdw9GKvNCrB2aB54gb2uV9MfQC: {
+        name: PROGRAM_NAMES.WORMHOLE,
+    },
+    WvmTNLpGMVbwJVYztYL4Hnsy82cJhQorxjnnXcRm3b6: {
+        name: PROGRAM_NAMES.SERUM_POOL,
+    },
+    auctxRXPeJoc4817jDhf4HbjnhEcr1cCXenosMhK5R8: {
+        name: PROGRAM_NAMES.NFT_AUCTION,
+    },
+    cjg3oHmg9uuPsP8D6g29NWvhySJkdYdAo9D25PRbKXJ: {
+        name: PROGRAM_NAMES.CHAINLINK_ORACLE,
+    },
+    cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK: {
+        name: PROGRAM_NAMES.ACCOUNT_COMPRESSION,
+    },
+    cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ: {
+        name: PROGRAM_NAMES.NFT_CANDY_MACHINE_V2,
+    },
+    cndyAnrLdpjq1Ssp1z8xxDsB8dxe7u4HL5Nxi2K5WXZ: {
+        name: PROGRAM_NAMES.NFT_CANDY_MACHINE,
+    },
+    gSbePebfvPy7tRqimPoVecS2UsBvYv46ynrzWocc92s: {
+        name: PROGRAM_NAMES.PYTH_DEVNET,
+    },
+    metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s: {
+        name: PROGRAM_NAMES.TOKEN_METADATA,
+    },
+    mv3ekLzLbnVPNxjSKvqBpU3ZeZXPQdEC3bp5MDEBG68: {
+        name: PROGRAM_NAMES.MANGO_3,
+    },
+    namesLPneVptA9Z5rqUDD9tMTWEJwofgaYwp8cawRkX: {
+        name: PROGRAM_NAMES.NAME,
+    },
+    p1exdMJcjVao65QdewkaZRUnU6VPSXhus9n2GzWfh98: {
+        name: PROGRAM_NAMES.METAPLEX,
+    },
+    vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn: {
+        name: PROGRAM_NAMES.TOKEN_VAULT,
+    },
+    worm2ZoG2kUd4vFXhvjh93UUH596ayRfgQ2MgjNMTth: {
+        name: PROGRAM_NAMES.WORMHOLE_CORE,
+    },
+    wormDTUJ6AWPNvk59vGQbDvGJmqbDTdgWgAqcLBCgUb: {
+        name: PROGRAM_NAMES.WORMHOLE_TOKEN,
+    },
+};
+
+export type LoaderName = (typeof LOADER_IDS)[keyof typeof LOADER_IDS];
+export const LOADER_IDS = {
+    BPFLoaderUpgradeab1e11111111111111111111111: "BPF Upgradeable Loader",
+    MoveLdr111111111111111111111111111111111111: "Move Loader",
+    [BPF_LOADER_DEPRECATED_PROGRAM_ID.toBase58()]: "BPF Loader",
+    [BPF_LOADER_PROGRAM_ID.toBase58()]: "BPF Loader 2",
+    NativeLoader1111111111111111111111111111111: "Native Loader",
+} as const;
+
+export const SPECIAL_IDS: { [key: string]: string } = {
+    "1nc1nerator11111111111111111111111111111111": "Incinerator",
+    Sysvar1111111111111111111111111111111111111: "SYSVAR",
+};
+
+export const SYSVAR_IDS = {
+    [SYSVAR_CLOCK_PUBKEY.toBase58()]: "Sysvar: Clock",
+    Sysvar1nstructions1111111111111111111111111: "Sysvar: Instructions",
+    SysvarEpochSchedu1e111111111111111111111111: "Sysvar: Epoch Schedule",
+    SysvarFees111111111111111111111111111111111: "Sysvar: Fees",
+    [SYSVAR_RENT_PUBKEY.toBase58()]: "Sysvar: Rent",
+    [SYSVAR_REWARDS_PUBKEY.toBase58()]: "Sysvar: Rewards",
+    SysvarRecentB1ockHashes11111111111111111111: "Sysvar: Recent Blockhashes",
+    SysvarS1otHashes111111111111111111111111111: "Sysvar: Slot Hashes",
+    [SYSVAR_STAKE_HISTORY_PUBKEY.toBase58()]: "Sysvar: Stake History",
+    SysvarS1otHistory11111111111111111111111111: "Sysvar: Slot History",
+};
+
+export function getDefaultProgramName(address: string): string {
+    const label = programLabel(address);
+    if (label) return label;
+    return `Unknown Program (${address})`;
+}
+
+export function programLabel(address: string): string | undefined {
+    const programInfo = PROGRAM_INFO_BY_ID[address];
+    if (programInfo) {
+        return programInfo.name;
+    }
+
+    return LOADER_IDS[address];
+}
+
+export function getProgramName(address: string) {
+    const defaultProgramName = getDefaultProgramName(address);
+
+    return defaultProgramName;
+}
diff --git a/apps/web/src/routes/+page.svelte b/apps/web/src/routes/+page.svelte
index d00eaf14..8d7d3d2c 100644
--- a/apps/web/src/routes/+page.svelte
+++ b/apps/web/src/routes/+page.svelte
@@ -174,133 +174,3 @@
         </div>
     </section>
 </IntersectionObserver>
-
-<IntersectionObserver
-    once={true}
-    rootMargin="10%"
-    element={heliusElement}
-    let:intersecting
->
-    <section
-        bind:this={heliusElement}
-        class="mx-auto max-w-5xl py-10 px-3"
-    >
-        {#if intersecting}
-            <div
-                in:fly={{
-                    duration: 750,
-                    y: 100,
-                }}
-                class="mx-auto max-w-5xl"
-            >
-                <div class="overflow-hidden pb-32">
-                    <div class="mt-10 scale-150 md:mt-0">
-                        {#if browser}
-                            <LottiePlayer
-                                src="/media/animation.json"
-                                autoplay={true}
-                                loop={true}
-                                controls={false}
-                                renderer="svg"
-                                background="transparent"
-                                height="300%"
-                                width="300%"
-                            />
-                        {/if}
-                    </div>
-                </div>
-
-                <div>
-                    <h1 class="scale-100 text-6xl font-bold text-current">
-                        Powered by
-
-                        <span
-                            class="bg-gradient-to-br from-orange-700 to-yellow-400 bg-clip-text text-transparent"
-                        >
-                            Helius
-                        </span>
-                    </h1>
-                    <div class="mt-5 grid grid-cols-12 gap-4">
-                        <div class="col-span-2 flex items-center md:col-span-1">
-                            <div
-                                class="flex h-6 w-6 items-center justify-center rounded-full bg-white"
-                            >
-                                <Icon
-                                    id="check"
-                                    fill="black"
-                                />
-                            </div>
-                        </div>
-                        <div class="col-span-10 md:col-span-11">
-                            <p class="opacity-50">
-                                We provide the most powerful Solana RPC hardware
-                                around. We offer the fastest speeds at the
-                                lowest prices possible. We also provide private
-                                RPCs for serious users.
-                            </p>
-                        </div>
-                        <div class="col-span-2 flex items-center md:col-span-1">
-                            <div
-                                class="flex h-6 w-6 items-center justify-center rounded-full bg-white"
-                            >
-                                <Icon
-                                    id="check"
-                                    fill="black"
-                                />
-                            </div>
-                        </div>
-                        <div class="col-span-10 md:col-span-11">
-                            <p class="opacity-50">
-                                Quickly build bots, analytics, marketplaces,
-                                portfolio or wallet trackers using the most
-                                complete Solana NFT API.
-                            </p>
-                        </div>
-                        <div class="col-span-2 flex items-center md:col-span-1">
-                            <div
-                                class="flex h-6 w-6 items-center justify-center rounded-full bg-white"
-                            >
-                                <Icon
-                                    id="check"
-                                    fill="black"
-                                />
-                            </div>
-                        </div>
-                        <div class="col-span-10 md:col-span-11">
-                            <p class="opacity-50">
-                                We allow you to query historical data by
-                                multiple dimensions including transaction types
-                                (DAO votes, NFT Mints, DeFi Swaps, etc) or
-                                underlying protocols (Jupiter, Magic Eden, etc).
-                            </p>
-                        </div>
-                        <div class="col-span-2 flex items-center md:col-span-1">
-                            <div
-                                class="flex h-6 w-6 items-center justify-center rounded-full bg-white"
-                            >
-                                <Icon
-                                    id="check"
-                                    fill="black"
-                                />
-                            </div>
-                        </div>
-                        <div class="col-span-10 md:col-span-11">
-                            <p class="opacity-50">
-                                Stream on-chain events on up to 100k addresses
-                                for free.
-                            </p>
-                        </div>
-                    </div>
-                </div>
-            </div>
-            <a
-                href="https://helius.xyz"
-                class="btn-primary btn mt-8 text-black"
-                target="_blank"
-                rel="noreferrer"
-            >
-                <span>Get Started</span>
-            </a>
-        {/if}
-    </section>
-</IntersectionObserver>
diff --git a/apps/web/src/routes/account/[account]/+layout.svelte b/apps/web/src/routes/account/[account]/+layout.svelte
index 82e5e4fa..1fb0dfd7 100644
--- a/apps/web/src/routes/account/[account]/+layout.svelte
+++ b/apps/web/src/routes/account/[account]/+layout.svelte
@@ -18,8 +18,13 @@
 
     import AccountHeader from "$lib/components/account-header.svelte";
     import { showModal } from "$lib/state/stores/modals";
+    import { trpcWithQuery } from "$lib/trpc/client";
+    import { PROGRAM_ID as ACCOUNT_COMPRESSION_ID } from "@solana/spl-account-compression";
+
+    const client = trpcWithQuery($page);
 
     const account = $page.params.account;
+    const accountInfo = client.accountInfo.createQuery(account);
 </script>
 
 <div class="relative mx-auto w-full max-w-2xl pb-32">
@@ -34,20 +39,27 @@
         >
             <div class="tabs w-full pt-1 md:w-auto">
                 <div />
-                <button
+                <a
+                    href={`/account/${account}`}
                     class="tab tab-bordered"
-                    on:click={() =>
-                        (window.location.href = `/account/${$page.params.account}`)}
-                    class:tab-active={!$page.url.pathname.endsWith("/tokens")}
-                    >Transactions</button
+                    class:tab-active={$page.url.pathname.endsWith(`${account}`)}
+                    >Transactions</a
                 >
-                <button
+                <a
+                    href={`/account/${account}/tokens`}
                     class="tab tab-bordered"
                     class:tab-active={$page.url.pathname.endsWith("/tokens")}
-                    on:click={() =>
-                        (window.location.href = `/account/${$page.params.account}/tokens`)}
-                    >Tokens</button
+                    >Tokens</a
                 >
+                {#if $accountInfo?.data?.value?.owner === ACCOUNT_COMPRESSION_ID.toBase58()}
+                    <a
+                        href={`/account/${account}/concurrent-merkle-tree`}
+                        class="tab tab-bordered"
+                        class:tab-active={$page.url.pathname.endsWith(
+                            "concurrent-merkle-tree"
+                        )}>Concurrent Merkle Tree</a
+                    >
+                {/if}
             </div>
             {#if !$page.url.pathname.endsWith("/tokens")}
                 <button
diff --git a/apps/web/src/routes/account/[account]/concurrent-merkle-tree/+page.svelte b/apps/web/src/routes/account/[account]/concurrent-merkle-tree/+page.svelte
new file mode 100644
index 00000000..91711e04
--- /dev/null
+++ b/apps/web/src/routes/account/[account]/concurrent-merkle-tree/+page.svelte
@@ -0,0 +1,312 @@
+<script lang="ts">
+    import { page } from "$app/stores";
+    import CopyButton from "$lib/components/copy-button.svelte";
+    import IconCard from "$lib/components/icon-card.svelte";
+    import Icon from "$lib/components/icon.svelte";
+    import { trpcWithQuery } from "$lib/trpc/client";
+    import shortenString from "$lib/util/shorten-string";
+    import { PublicKey } from "@solana/web3.js";
+
+    const client = trpcWithQuery($page);
+    const account = $page.params.account;
+
+    const cmt = client.concurrentMerkleTree.createQuery(account);
+
+    $: currentRoot = new PublicKey($cmt.data?.root.data || []);
+</script>
+
+{#if $cmt.data}
+    <div class="mb-3">
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="key"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">Authority</h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The account authroized to modify the tree's state.
+                    </h3>
+                </div>
+                <div class="flex items-center">
+                    <CopyButton text={$cmt.data?.authority} />
+                    <a
+                        data-sveltekit-reload
+                        href="/account/{$cmt.data?.authority}"
+                        class="pointer-events-auto text-xs hover:link-success md:text-sm"
+                    >
+                        {shortenString($cmt.data?.authority)}
+                    </a>
+                </div>
+            </div>
+        </div>
+        <div>
+            <div
+                class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+            >
+                <div class="col-span-2 p-1 md:col-span-1">
+                    <div
+                        class="center ml-1 h-10 w-10 rounded-full bg-secondary"
+                    >
+                        <Icon
+                            id="box"
+                            size="sm"
+                        />
+                    </div>
+                </div>
+                <div
+                    class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+                >
+                    <div>
+                        <h4 class="text-lg font-semibold md:text-sm">
+                            Slot Created
+                        </h4>
+                        <h3 class="mr-2 text-xs opacity-50">
+                            The slot this tree was created on.
+                        </h3>
+                    </div>
+                    <a
+                        href="/block/{$cmt.data?.creationSlot}"
+                        class="pointer-events-auto text-xs hover:link-success md:text-sm"
+                    >
+                        {$cmt.data?.creationSlot.toLocaleString()}
+                    </a>
+                </div>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="tree"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">Max Depth</h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The maximum number of levels the tree can have.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">{$cmt.data.treeHeight}</p>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="cloudTransfer"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Max Buffer Size
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The maximum number of leaves that can be processed at
+                        once.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">{$cmt.data.maxBufferSize}</p>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="trees"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Canopy Depth
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The subset of the tree that is stored within the tree
+                        account.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">{$cmt.data.canopyDepth}</p>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="cycle"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Current Sequence Number
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The number used to differentiate updates to the tree.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">
+                    {parseInt($cmt.data.seq).toLocaleString()}
+                </p>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="codeFork"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Current Root
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The current root hash of the tree.
+                    </h3>
+                </div>
+                <div class="flex items-center">
+                    <CopyButton text={String(currentRoot)} />
+                    <p class="text-xs md:text-sm">
+                        {shortenString(String(currentRoot))}
+                    </p>
+                </div>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="leaf"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Current Number of Leaves
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The current number of leaves in the tree.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">
+                    {($cmt.data.rightMostIndex - 1).toLocaleString()}
+                </p>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="hourglass"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Remaining Leaves
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The number of leaves that can still be added to the
+                        tree.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">
+                    {(
+                        Math.pow(2, $cmt.data.treeHeight) -
+                        $cmt.data.rightMostIndex +
+                        1
+                    ).toLocaleString()}
+                </p>
+            </div>
+        </div>
+        <div
+            class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
+        >
+            <div class="col-span-2 p-1 md:col-span-1">
+                <div class="center ml-1 h-10 w-10 rounded-full bg-secondary">
+                    <Icon
+                        id="plus"
+                        size="sm"
+                    />
+                </div>
+            </div>
+            <div
+                class="col-span-10 flex items-center justify-between pr-1 md:col-span-11"
+            >
+                <div>
+                    <h4 class="text-lg font-semibold md:text-sm">
+                        Max Possible Leaves
+                    </h4>
+                    <h3 class="mr-2 text-xs opacity-50">
+                        The maximum number of leaves that the tree can
+                        accommodate.
+                    </h3>
+                </div>
+                <p class="text-xs md:text-sm">
+                    {Math.pow(2, $cmt.data.treeHeight).toLocaleString()}
+                </p>
+            </div>
+        </div>
+    </div>
+{:else}
+    {#each Array(3) as _}
+        <div class="py-2">
+            <IconCard />
+        </div>
+    {/each}
+{/if}
diff --git a/apps/web/src/routes/account/[account]/tokens/+page.svelte b/apps/web/src/routes/account/[account]/tokens/+page.svelte
index 1ad61a65..239d3a50 100644
--- a/apps/web/src/routes/account/[account]/tokens/+page.svelte
+++ b/apps/web/src/routes/account/[account]/tokens/+page.svelte
@@ -15,6 +15,8 @@
 
     const balances = client.balances.createQuery(account);
 
+    const token2022 = client.token2022.createQuery(account);
+
     const sol = client.price.createQuery(SOL);
 
     $: sorted = $balances?.data?.tokens
@@ -65,6 +67,49 @@
         </div>
     </a>
 
+    {#if $token2022.data}
+        {#each $token2022.data as token}
+            <TokenProvider
+                address={token.mint}
+                let:metadata
+            >
+                <a
+                    class="mb-4 grid grid-cols-12 items-center gap-3 rounded-lg border px-3 py-2 hover:border-primary"
+                    href="/token/{token.mint}"
+                >
+                    <div class="col-span-2 p-1 md:col-span-1">
+                        <!-- background so that if it doesn't load you dont' get ugly no image icons -->
+                        <div
+                            style="background-image: url('{metadata.image}')"
+                            class="aspect-square w-full rounded-lg bg-cover"
+                        />
+                    </div>
+                    <div
+                        class="col-span-10 flex items-center justify-between text-right md:col-span-11"
+                    >
+                        <div>
+                            <h4 class="font-semibold md:text-sm">
+                                {metadata.name || ""}
+                            </h4>
+                        </div>
+                        <div>
+                            <h4 class="font-semibold md:text-sm">
+                                {token.amount.toLocaleString()}
+                            </h4>
+                            <!-- <h4 class="text-xs opacity-50">
+                            {#if metadata.price}
+                                {formatMoney(
+                                    (metadata.price * token.amount) /
+                                        10 ** token.decimals
+                                )}
+                            {/if}
+                        </h4> -->
+                        </div>
+                    </div>
+                </a>
+            </TokenProvider>
+        {/each}
+    {/if}
     {#if sorted}
         {#each sorted as token (token.mint)}
             {#if token.decimals > 0 && token.mint !== SOL}
diff --git a/apps/web/src/routes/token/[token]/+page.svelte b/apps/web/src/routes/token/[token]/+page.svelte
index f9925176..d781aa87 100644
--- a/apps/web/src/routes/token/[token]/+page.svelte
+++ b/apps/web/src/routes/token/[token]/+page.svelte
@@ -17,6 +17,7 @@
 
 <script lang="ts">
     import { page } from "$app/stores";
+    import basisPointsToPercentage from "$lib/util/percentage";
     import shortenString from "$lib/util/shorten-string";
     import { cubicOut } from "svelte/easing";
     import { fade, fly } from "svelte/transition";
@@ -159,10 +160,115 @@
                     </Collapse>
                 </div>
             {/if}
+
+            {#if metadata.sellerFeeBasisPoints}
+                <div
+                    class="mt-3"
+                    in:fly={{
+                        delay: 300,
+                        easing: cubicOut,
+                        y: 50,
+                    }}
+                >
+                    <Collapse
+                        sectionTitle="Creator Royalties"
+                        sectionAditionalInfo={basisPointsToPercentage(
+                            metadata.sellerFeeBasisPoints
+                        )}
+                        iconId="percentage"
+                    >
+                        <p>
+                            {metadata.name ?? "The"} creator(s) currently expect
+                            to take {basisPointsToPercentage(
+                                metadata.sellerFeeBasisPoints
+                            )} of every secondary sale on this piece.
+                        </p>
+                    </Collapse>
+                </div>
+            {/if}
+            {#if metadata.owner}
+                <div
+                    class="mt-3"
+                    in:fly={{ delay: 300, easing: cubicOut, y: 50 }}
+                >
+                    <Collapse
+                        sectionTitle="Ownership"
+                        iconId="key"
+                    >
+                        <div class="flex flex-wrap gap-2">
+                            <a
+                                class="card p-0"
+                                href="/account/{metadata.owner}"
+                            >
+                                <header
+                                    class="flex items-center justify-between gap-6 text-sm font-medium uppercase text-gray-500"
+                                >
+                                    <h4>Owner</h4>
+                                </header>
+                                <p class="text-sm">
+                                    {shortenString(metadata.owner)}
+                                </p>
+                            </a>
+                            <div class="card p-0">
+                                <h4
+                                    class="text-sm font-medium uppercase text-gray-500"
+                                >
+                                    Mutable
+                                </h4>
+                                <p class="text-sm">
+                                    {metadata.mutable ? "true" : "false"}
+                                </p>
+                            </div>
+                            <div class="card p-0">
+                                <h4
+                                    class="text-sm font-medium uppercase text-gray-500"
+                                >
+                                    Frozen
+                                </h4>
+                                <p class="text-sm">
+                                    {metadata.frozen ? "true" : "false"}
+                                </p>
+                            </div>
+                            {#if metadata.delegate}
+                                <a
+                                    class="card p-0"
+                                    href="/account/{metadata.owner}"
+                                >
+                                    <header
+                                        class="flex items-center justify-between gap-6 text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        <h4>Delegate</h4>
+                                    </header>
+                                    <p class="text-sm">
+                                        {shortenString(metadata.delegate)}
+                                    </p>
+                                </a>
+                            {:else}
+                                <div class="card p-0">
+                                    <h4
+                                        class="text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        Delegate
+                                    </h4>
+                                    <p class="text-sm">false</p>
+                                </div>
+                            {/if}
+                        </div>
+                    </Collapse>
+                </div>
+            {/if}
             {#if metadata.creators && metadata.creators.length > 0}
-                <div class="mt-3">
+                <div
+                    class="mt-3"
+                    in:fly={{
+                        delay: 300,
+                        easing: cubicOut,
+                        y: 50,
+                    }}
+                >
                     <Collapse
                         sectionTitle="Creators"
+                        sectionAditionalInfo={metadata.creators.length}
                         iconId="creator"
                     >
                         <div class="flex flex-wrap gap-2">
@@ -171,11 +277,22 @@
                                     class="card p-0"
                                     href="/account/{creator.address}"
                                 >
-                                    <h4
-                                        class="text-sm font-medium text-gray-500"
+                                    <header
+                                        class="flex items-center justify-between gap-6 text-sm font-medium text-gray-500"
                                     >
-                                        CREATOR {idx + 1}
-                                    </h4>
+                                        <h4>
+                                            CREATOR {idx + 1}
+                                        </h4>
+                                        <abbr
+                                            title={`Creator ${
+                                                idx + 1
+                                            } royalties percentage`}
+                                        >
+                                            <h4>
+                                                {creator.share}%
+                                            </h4>
+                                        </abbr>
+                                    </header>
                                     <p class="text-sm">
                                         {shortenString(creator.address)}
                                     </p>
@@ -185,6 +302,97 @@
                     </Collapse>
                 </div>
             {/if}
+            {#if metadata.compressed}
+                <div
+                    class="mt-3"
+                    in:fly={{
+                        delay: 300,
+                        easing: cubicOut,
+                        y: 50,
+                    }}
+                >
+                    <Collapse
+                        sectionTitle="Compression"
+                        iconId="tree"
+                    >
+                        <div class="flex flex-wrap gap-2">
+                            <a
+                                class="card p-0"
+                                href="/account/{metadata.tree}/concurrent-merkle-tree"
+                            >
+                                <header
+                                    class="flex items-center justify-between gap-6 text-sm font-medium uppercase text-gray-500"
+                                >
+                                    <h4>Tree ID</h4>
+                                </header>
+                                <p class="text-sm">
+                                    {shortenString(metadata.tree)}
+                                </p>
+                            </a>
+                            <div class="flex flex-wrap gap-2">
+                                <div class="card p-0">
+                                    <h4
+                                        class="text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        Sequence
+                                    </h4>
+                                    <p class="text-sm">
+                                        {metadata.seq?.toLocaleString()}
+                                    </p>
+                                </div>
+                            </div>
+                            <div class="flex flex-wrap gap-2">
+                                <div class="card p-0">
+                                    <h4
+                                        class="text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        Leaf ID
+                                    </h4>
+                                    <p class="text-sm">
+                                        {metadata.leafId?.toLocaleString()}
+                                    </p>
+                                </div>
+                            </div>
+                            <div class="flex flex-wrap gap-2">
+                                <div class="card p-0">
+                                    <h4
+                                        class="text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        Data Hash
+                                    </h4>
+                                    <p class="text-sm">
+                                        {metadata.dataHash}
+                                    </p>
+                                </div>
+                            </div>
+                            <div class="flex flex-wrap gap-2">
+                                <div class="card p-0">
+                                    <h4
+                                        class="text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        Asset Hash
+                                    </h4>
+                                    <p class="text-sm">
+                                        {metadata.assetHash}
+                                    </p>
+                                </div>
+                            </div>
+                            <div class="flex flex-wrap gap-2">
+                                <div class="card p-0">
+                                    <h4
+                                        class="text-sm font-medium uppercase text-gray-500"
+                                    >
+                                        Creator Hash
+                                    </h4>
+                                    <p class="text-sm">
+                                        {metadata.creatorHash}
+                                    </p>
+                                </div>
+                            </div>
+                        </div>
+                    </Collapse>
+                </div>
+            {/if}
             <div class="mt-3 pl-2 md:pl-0">
                 <Transactions account={address} />
             </div>
diff --git a/apps/web/src/routes/tx/[tx]/+page.svelte b/apps/web/src/routes/tx/[tx]/+page.svelte
index 1576b5d2..bcf4f364 100644
--- a/apps/web/src/routes/tx/[tx]/+page.svelte
+++ b/apps/web/src/routes/tx/[tx]/+page.svelte
@@ -16,6 +16,7 @@
     import IconCard from "$lib/components/icon-card.svelte";
     import Icon from "$lib/components/icon.svelte";
     import JSON from "$lib/components/json.svelte";
+    import LogMessages from "$lib/components/log-messages.svelte";
     import Transaction from "$lib/components/transaction.svelte";
     import Collapse from "src/lib/components/collapse.svelte";
 
@@ -112,30 +113,57 @@
                 <div
                     class="mt-3 grid grid-cols-12 items-center gap-3 rounded-lg border p-1 py-3"
                 >
-                    <div class="col-span-2 p-1 md:col-span-1">
+                    {#if rawData?.transaction?.meta?.err}
+                        <div class="col-span-2 p-1 md:col-span-1">
+                            <div
+                                class="center ml-1 h-10 w-10 rounded-full bg-error"
+                            >
+                                <Icon
+                                    id="close"
+                                    fill="black"
+                                    size="sm"
+                                />
+                            </div>
+                        </div>
                         <div
-                            class="center ml-1 h-10 w-10 rounded-full bg-success"
+                            class="col-span-10 flex items-center justify-between md:col-span-11"
                         >
-                            <Icon
-                                id="check"
-                                fill="black"
-                                size="sm"
-                            />
+                            <div>
+                                <h4 class="text-lg font-semibold md:text-sm">
+                                    Status
+                                </h4>
+                                <h3 class="mr-2 text-xs opacity-50">
+                                    This transaction has failed.
+                                </h3>
+                            </div>
+                            <div class="badge-error badge mr-1">Error</div>
                         </div>
-                    </div>
-                    <div
-                        class="col-span-10 flex items-center justify-between md:col-span-11"
-                    >
-                        <div>
-                            <h4 class="text-lg font-semibold md:text-sm">
-                                Status
-                            </h4>
-                            <h3 class="mr-2 text-xs opacity-50">
-                                This transaction has successfully processed.
-                            </h3>
+                    {:else}
+                        <div class="col-span-2 p-1 md:col-span-1">
+                            <div
+                                class="center ml-1 h-10 w-10 rounded-full bg-success"
+                            >
+                                <Icon
+                                    id="check"
+                                    fill="black"
+                                    size="sm"
+                                />
+                            </div>
                         </div>
-                        <div class="badge-success badge mr-1">Success</div>
-                    </div>
+                        <div
+                            class="col-span-10 flex items-center justify-between md:col-span-11"
+                        >
+                            <div>
+                                <h4 class="text-lg font-semibold md:text-sm">
+                                    Status
+                                </h4>
+                                <h3 class="mr-2 text-xs opacity-50">
+                                    This transaction has successfully processed.
+                                </h3>
+                            </div>
+                            <div class="badge-success badge mr-1">Success</div>
+                        </div>
+                    {/if}
                 </div>
             </div>
             <div class="mb-3 px-3">
@@ -279,13 +307,7 @@
                         )}
                         hideIcon={true}
                     >
-                        {#each rawData?.transaction?.meta?.logMessages || [] as message}
-                            <p class="px-3 text-xs">
-                                <span class="mr-1 text-success">></span><span
-                                    class="text-neutral">{message}</span
-                                >
-                            </p>
-                        {/each}
+                        <LogMessages logs={rawData?.transaction?.meta?.logMessages || []} />
                     </Collapse>
                 </div>
             {/if}
diff --git a/doc/xray-cover-gh.jpg b/doc/xray-cover-gh.jpg
new file mode 100644
index 00000000..57a475fa
Binary files /dev/null and b/doc/xray-cover-gh.jpg differ
diff --git a/package-lock.json b/package-lock.json
index d3d258a8..4b187192 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,6 +11,9 @@
                 "apps/*",
                 "packages/*"
             ],
+            "dependencies": {
+                "@solana/spl-account-compression": "^0.1.8"
+            },
             "devDependencies": {
                 "@typescript-eslint/eslint-plugin": "^5.52.0",
                 "@typescript-eslint/parser": "^5.52.0",
@@ -37,6 +40,8 @@
                 "eslint-plugin-svelte3": "^4.0.0",
                 "eslint-plugin-this": "^0.2.3",
                 "eslint-plugin-write-good-comments": "^0.1.4",
+                "husky": "^8.0.3",
+                "lint-staged": "^13.2.2",
                 "nodemon": "^2.0.20",
                 "prettier": "^2.8.4",
                 "prettier-plugin-css-order": "^1.3.0",
@@ -106,25 +111,6 @@
                 "vite": "^4.0.0"
             }
         },
-        "apps/web/node_modules/@onsol/tldparser": {
-            "version": "0.5.1",
-            "resolved": "https://registry.npmjs.org/@onsol/tldparser/-/tldparser-0.5.1.tgz",
-            "integrity": "sha512-6AkUguYxyJWVkgkF56sbl2NnLQld0kqQmHEp3Gdgho+byReFUOUVN0A7wasTCMOEnBksl4CrlSzjRrkGOlFKDA==",
-            "license": "MIT",
-            "dependencies": {
-                "@ethersproject/sha2": "^5.7.0",
-                "@metaplex-foundation/beet-solana": "^0.4.0"
-            },
-            "engines": {
-                "node": ">=14"
-            },
-            "peerDependencies": {
-                "@solana/web3.js": "^1.67.0",
-                "bn.js": "^5.2.1",
-                "borsh": "^0.7.0",
-                "buffer": "6.0.1"
-            }
-        },
         "apps/web/node_modules/@sveltejs/adapter-auto": {
             "version": "2.0.0",
             "resolved": "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-2.0.0.tgz",
@@ -1884,32 +1870,24 @@
                 "sha.js": "^2.4.11"
             }
         },
-        "node_modules/@noble/ed25519": {
-            "version": "1.7.3",
-            "resolved": "https://registry.npmjs.org/@noble/ed25519/-/ed25519-1.7.3.tgz",
-            "integrity": "sha512-iR8GBkDt0Q3GyaVcIu7mSsVIqnFbkbRzGLWlvhwunacoLwt4J3swfKhfaM6rN6WY+TBGoYT1GtT1mIh2/jGbRQ==",
+        "node_modules/@noble/curves": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.0.0.tgz",
+            "integrity": "sha512-2upgEu0iLiDVDZkNLeFV2+ht0BAVgQnEmCk6JsOch9Rp8xfkMCbvbAZlA2pBHQc73dbl+vFOXfqkf4uemdn0bw==",
             "funding": [
                 {
                     "type": "individual",
                     "url": "https://paulmillr.com/funding/"
                 }
-            ]
+            ],
+            "dependencies": {
+                "@noble/hashes": "1.3.0"
+            }
         },
         "node_modules/@noble/hashes": {
-            "version": "1.2.0",
-            "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz",
-            "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==",
-            "funding": [
-                {
-                    "type": "individual",
-                    "url": "https://paulmillr.com/funding/"
-                }
-            ]
-        },
-        "node_modules/@noble/secp256k1": {
-            "version": "1.7.1",
-            "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz",
-            "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==",
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.0.tgz",
+            "integrity": "sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg==",
             "funding": [
                 {
                     "type": "individual",
@@ -2277,6 +2255,24 @@
                 "node": ">=8"
             }
         },
+        "node_modules/@onsol/tldparser": {
+            "version": "0.5.3",
+            "resolved": "https://registry.npmjs.org/@onsol/tldparser/-/tldparser-0.5.3.tgz",
+            "integrity": "sha512-rICUDhYPwDuO81wo4HI7QSCf6kQiaM0mSv3HKBJPrRxliIvgwanAoU5H0p54HEdAKeS3pmeLi5wB6ROpGxTZ/A==",
+            "dependencies": {
+                "@ethersproject/sha2": "^5.7.0",
+                "@metaplex-foundation/beet-solana": "^0.4.0"
+            },
+            "engines": {
+                "node": ">=14"
+            },
+            "peerDependencies": {
+                "@solana/web3.js": "^1.67.0",
+                "bn.js": "^5.2.1",
+                "borsh": "^0.7.0",
+                "buffer": "6.0.1"
+            }
+        },
         "node_modules/@particle-network/auth": {
             "version": "0.5.6",
             "resolved": "https://registry.npmjs.org/@particle-network/auth/-/auth-0.5.6.tgz",
@@ -2466,6 +2462,25 @@
                 "ieee754": "^1.2.1"
             }
         },
+        "node_modules/@solana/spl-account-compression": {
+            "version": "0.1.8",
+            "resolved": "https://registry.npmjs.org/@solana/spl-account-compression/-/spl-account-compression-0.1.8.tgz",
+            "integrity": "sha512-vsvsx358pVFPtyNd8zIZy0lezR0NuvOykQ29Zq+8oto+kHfTXMGXXQ1tKHUYke6XkINIWLFVg/jDi+1D9RYaqQ==",
+            "dependencies": {
+                "@metaplex-foundation/beet": "^0.7.1",
+                "@metaplex-foundation/beet-solana": "^0.4.0",
+                "bn.js": "^5.2.1",
+                "borsh": "^0.7.0",
+                "js-sha3": "^0.8.0",
+                "typescript-collections": "^1.3.3"
+            },
+            "engines": {
+                "node": ">=16"
+            },
+            "peerDependencies": {
+                "@solana/web3.js": "^1.50.1"
+            }
+        },
         "node_modules/@solana/spl-token-registry": {
             "version": "0.2.4574",
             "resolved": "https://registry.npmjs.org/@solana/spl-token-registry/-/spl-token-registry-0.2.4574.tgz",
@@ -3273,29 +3288,48 @@
             }
         },
         "node_modules/@solana/web3.js": {
-            "version": "1.73.2",
-            "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.73.2.tgz",
-            "integrity": "sha512-9WACF8W4Nstj7xiDw3Oom22QmrhBh0VyZyZ7JvvG3gOxLWLlX3hvm5nPVJOGcCE/9fFavBbCUb5A6CIuvMGdoA==",
+            "version": "1.77.3",
+            "resolved": "https://registry.npmjs.org/@solana/web3.js/-/web3.js-1.77.3.tgz",
+            "integrity": "sha512-PHaO0BdoiQRPpieC1p31wJsBaxwIOWLh8j2ocXNKX8boCQVldt26Jqm2tZE4KlrvnCIV78owPLv1pEUgqhxZ3w==",
             "dependencies": {
                 "@babel/runtime": "^7.12.5",
-                "@noble/ed25519": "^1.7.0",
-                "@noble/hashes": "^1.1.2",
-                "@noble/secp256k1": "^1.6.3",
+                "@noble/curves": "^1.0.0",
+                "@noble/hashes": "^1.3.0",
                 "@solana/buffer-layout": "^4.0.0",
                 "agentkeepalive": "^4.2.1",
                 "bigint-buffer": "^1.1.5",
                 "bn.js": "^5.0.0",
                 "borsh": "^0.7.0",
                 "bs58": "^4.0.1",
-                "buffer": "6.0.1",
+                "buffer": "6.0.3",
                 "fast-stable-stringify": "^1.0.0",
-                "jayson": "^3.4.4",
-                "node-fetch": "2",
-                "rpc-websockets": "^7.5.0",
+                "jayson": "^4.1.0",
+                "node-fetch": "^2.6.7",
+                "rpc-websockets": "^7.5.1",
                 "superstruct": "^0.14.2"
-            },
-            "engines": {
-                "node": ">=12.20.0"
+            }
+        },
+        "node_modules/@solana/web3.js/node_modules/buffer": {
+            "version": "6.0.3",
+            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+            "funding": [
+                {
+                    "type": "github",
+                    "url": "https://github.com/sponsors/feross"
+                },
+                {
+                    "type": "patreon",
+                    "url": "https://www.patreon.com/feross"
+                },
+                {
+                    "type": "consulting",
+                    "url": "https://feross.org/support"
+                }
+            ],
+            "dependencies": {
+                "base64-js": "^1.3.1",
+                "ieee754": "^1.2.1"
             }
         },
         "node_modules/@solana/web3.js/node_modules/node-fetch": {
@@ -4810,6 +4844,28 @@
                 "node": ">= 8.0.0"
             }
         },
+        "node_modules/aggregate-error": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+            "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+            "dev": true,
+            "dependencies": {
+                "clean-stack": "^2.0.0",
+                "indent-string": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/aggregate-error/node_modules/clean-stack": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+            "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+            "dev": true,
+            "engines": {
+                "node": ">=6"
+            }
+        },
         "node_modules/ajv": {
             "version": "6.12.6",
             "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@@ -5592,6 +5648,7 @@
                     "url": "https://feross.org/support"
                 }
             ],
+            "peer": true,
             "dependencies": {
                 "base64-js": "^1.3.1",
                 "ieee754": "^1.2.1"
@@ -5940,6 +5997,112 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/cli-truncate": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz",
+            "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==",
+            "dev": true,
+            "dependencies": {
+                "slice-ansi": "^5.0.0",
+                "string-width": "^5.0.0"
+            },
+            "engines": {
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/cli-truncate/node_modules/ansi-regex": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
+            "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
+            "dev": true,
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+            }
+        },
+        "node_modules/cli-truncate/node_modules/ansi-styles": {
+            "version": "6.2.1",
+            "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+            "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+            "dev": true,
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+            }
+        },
+        "node_modules/cli-truncate/node_modules/emoji-regex": {
+            "version": "9.2.2",
+            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+            "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+            "dev": true
+        },
+        "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+            "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/cli-truncate/node_modules/slice-ansi": {
+            "version": "5.0.0",
+            "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
+            "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^6.0.0",
+                "is-fullwidth-code-point": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+            }
+        },
+        "node_modules/cli-truncate/node_modules/string-width": {
+            "version": "5.1.2",
+            "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+            "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+            "dev": true,
+            "dependencies": {
+                "eastasianwidth": "^0.2.0",
+                "emoji-regex": "^9.2.2",
+                "strip-ansi": "^7.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/cli-truncate/node_modules/strip-ansi": {
+            "version": "7.0.1",
+            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
+            "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
+            "dev": true,
+            "dependencies": {
+                "ansi-regex": "^6.0.1"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+            }
+        },
         "node_modules/cli-width": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
@@ -6072,6 +6235,12 @@
                 "color-support": "bin.js"
             }
         },
+        "node_modules/colorette": {
+            "version": "2.0.20",
+            "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+            "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+            "dev": true
+        },
         "node_modules/combined-stream": {
             "version": "1.0.8",
             "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -6830,6 +6999,12 @@
             "dev": true,
             "license": "MIT"
         },
+        "node_modules/eastasianwidth": {
+            "version": "0.2.0",
+            "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+            "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+            "dev": true
+        },
         "node_modules/eip1193-provider": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/eip1193-provider/-/eip1193-provider-1.0.1.tgz",
@@ -8552,6 +8727,68 @@
                 "safe-buffer": "^5.1.1"
             }
         },
+        "node_modules/execa": {
+            "version": "7.1.1",
+            "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz",
+            "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==",
+            "dev": true,
+            "dependencies": {
+                "cross-spawn": "^7.0.3",
+                "get-stream": "^6.0.1",
+                "human-signals": "^4.3.0",
+                "is-stream": "^3.0.0",
+                "merge-stream": "^2.0.0",
+                "npm-run-path": "^5.1.0",
+                "onetime": "^6.0.0",
+                "signal-exit": "^3.0.7",
+                "strip-final-newline": "^3.0.0"
+            },
+            "engines": {
+                "node": "^14.18.0 || ^16.14.0 || >=18.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sindresorhus/execa?sponsor=1"
+            }
+        },
+        "node_modules/execa/node_modules/is-stream": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+            "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+            "dev": true,
+            "engines": {
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/execa/node_modules/mimic-fn": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+            "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+            "dev": true,
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/execa/node_modules/onetime": {
+            "version": "6.0.0",
+            "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+            "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+            "dev": true,
+            "dependencies": {
+                "mimic-fn": "^4.0.0"
+            },
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/exenv": {
             "version": "1.2.2",
             "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
@@ -8972,6 +9209,18 @@
                 "url": "https://github.com/sponsors/ljharb"
             }
         },
+        "node_modules/get-stream": {
+            "version": "6.0.1",
+            "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+            "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+            "dev": true,
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/get-symbol-description": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
@@ -9264,6 +9513,15 @@
                 "node": ">= 6"
             }
         },
+        "node_modules/human-signals": {
+            "version": "4.3.1",
+            "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz",
+            "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=14.18.0"
+            }
+        },
         "node_modules/humanize-ms": {
             "version": "1.2.1",
             "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
@@ -9272,6 +9530,21 @@
                 "ms": "^2.0.0"
             }
         },
+        "node_modules/husky": {
+            "version": "8.0.3",
+            "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz",
+            "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==",
+            "dev": true,
+            "bin": {
+                "husky": "lib/bin.js"
+            },
+            "engines": {
+                "node": ">=14"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/typicode"
+            }
+        },
         "node_modules/iconv-lite": {
             "version": "0.4.24",
             "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
@@ -9992,9 +10265,9 @@
             }
         },
         "node_modules/jayson": {
-            "version": "3.7.0",
-            "resolved": "https://registry.npmjs.org/jayson/-/jayson-3.7.0.tgz",
-            "integrity": "sha512-tfy39KJMrrXJ+mFcMpxwBvFDetS8LAID93+rycFglIQM4kl3uNR3W4lBLE/FFhsoUCEox5Dt2adVpDm/XtebbQ==",
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.1.0.tgz",
+            "integrity": "sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==",
             "dependencies": {
                 "@types/connect": "^3.4.33",
                 "@types/node": "^12.12.54",
@@ -10006,7 +10279,6 @@
                 "isomorphic-ws": "^4.0.1",
                 "json-stringify-safe": "^5.0.1",
                 "JSONStream": "^1.3.5",
-                "lodash": "^4.17.20",
                 "uuid": "^8.3.2",
                 "ws": "^7.4.5"
             },
@@ -10395,9 +10667,9 @@
             }
         },
         "node_modules/lilconfig": {
-            "version": "2.0.6",
-            "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
-            "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+            "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
             "engines": {
                 "node": ">=10"
             }
@@ -10411,6 +10683,140 @@
                 "uc.micro": "^1.0.1"
             }
         },
+        "node_modules/lint-staged": {
+            "version": "13.2.2",
+            "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.2.2.tgz",
+            "integrity": "sha512-71gSwXKy649VrSU09s10uAT0rWCcY3aewhMaHyl2N84oBk4Xs9HgxvUp3AYu+bNsK4NrOYYxvSgg7FyGJ+jGcA==",
+            "dev": true,
+            "dependencies": {
+                "chalk": "5.2.0",
+                "cli-truncate": "^3.1.0",
+                "commander": "^10.0.0",
+                "debug": "^4.3.4",
+                "execa": "^7.0.0",
+                "lilconfig": "2.1.0",
+                "listr2": "^5.0.7",
+                "micromatch": "^4.0.5",
+                "normalize-path": "^3.0.0",
+                "object-inspect": "^1.12.3",
+                "pidtree": "^0.6.0",
+                "string-argv": "^0.3.1",
+                "yaml": "^2.2.2"
+            },
+            "bin": {
+                "lint-staged": "bin/lint-staged.js"
+            },
+            "engines": {
+                "node": "^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://opencollective.com/lint-staged"
+            }
+        },
+        "node_modules/lint-staged/node_modules/chalk": {
+            "version": "5.2.0",
+            "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.2.0.tgz",
+            "integrity": "sha512-ree3Gqw/nazQAPuJJEy+avdl7QfZMcUvmHIKgEZkGL+xOBzRvup5Hxo6LHuMceSxOabuJLJm5Yp/92R9eMmMvA==",
+            "dev": true,
+            "engines": {
+                "node": "^12.17.0 || ^14.13 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/chalk?sponsor=1"
+            }
+        },
+        "node_modules/lint-staged/node_modules/commander": {
+            "version": "10.0.1",
+            "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+            "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+            "dev": true,
+            "engines": {
+                "node": ">=14"
+            }
+        },
+        "node_modules/listr2": {
+            "version": "5.0.8",
+            "resolved": "https://registry.npmjs.org/listr2/-/listr2-5.0.8.tgz",
+            "integrity": "sha512-mC73LitKHj9w6v30nLNGPetZIlfpUniNSsxxrbaPcWOjDb92SHPzJPi/t+v1YC/lxKz/AJ9egOjww0qUuFxBpA==",
+            "dev": true,
+            "dependencies": {
+                "cli-truncate": "^2.1.0",
+                "colorette": "^2.0.19",
+                "log-update": "^4.0.0",
+                "p-map": "^4.0.0",
+                "rfdc": "^1.3.0",
+                "rxjs": "^7.8.0",
+                "through": "^2.3.8",
+                "wrap-ansi": "^7.0.0"
+            },
+            "engines": {
+                "node": "^14.13.1 || >=16.0.0"
+            },
+            "peerDependencies": {
+                "enquirer": ">= 2.3.0 < 3"
+            },
+            "peerDependenciesMeta": {
+                "enquirer": {
+                    "optional": true
+                }
+            }
+        },
+        "node_modules/listr2/node_modules/cli-truncate": {
+            "version": "2.1.0",
+            "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+            "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+            "dev": true,
+            "dependencies": {
+                "slice-ansi": "^3.0.0",
+                "string-width": "^4.2.0"
+            },
+            "engines": {
+                "node": ">=8"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/listr2/node_modules/rxjs": {
+            "version": "7.8.1",
+            "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
+            "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
+            "dev": true,
+            "dependencies": {
+                "tslib": "^2.1.0"
+            }
+        },
+        "node_modules/listr2/node_modules/slice-ansi": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+            "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "astral-regex": "^2.0.0",
+                "is-fullwidth-code-point": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
+        "node_modules/listr2/node_modules/wrap-ansi": {
+            "version": "7.0.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+            "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+            }
+        },
         "node_modules/localStorage": {
             "version": "1.0.4",
             "resolved": "https://registry.npmjs.org/localStorage/-/localStorage-1.0.4.tgz",
@@ -10519,6 +10925,38 @@
                 "url": "https://github.com/sponsors/sindresorhus"
             }
         },
+        "node_modules/log-update": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+            "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+            "dev": true,
+            "dependencies": {
+                "ansi-escapes": "^4.3.0",
+                "cli-cursor": "^3.1.0",
+                "slice-ansi": "^4.0.0",
+                "wrap-ansi": "^6.2.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/log-update/node_modules/wrap-ansi": {
+            "version": "6.2.0",
+            "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+            "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+            "dev": true,
+            "dependencies": {
+                "ansi-styles": "^4.0.0",
+                "string-width": "^4.1.0",
+                "strip-ansi": "^6.0.0"
+            },
+            "engines": {
+                "node": ">=8"
+            }
+        },
         "node_modules/loglevel": {
             "version": "1.8.1",
             "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz",
@@ -10724,6 +11162,12 @@
             "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
             "dev": true
         },
+        "node_modules/merge-stream": {
+            "version": "2.0.0",
+            "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+            "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+            "dev": true
+        },
         "node_modules/merge2": {
             "version": "1.4.1",
             "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
@@ -11698,6 +12142,33 @@
                 "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
             }
         },
+        "node_modules/npm-run-path": {
+            "version": "5.1.0",
+            "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
+            "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
+            "dev": true,
+            "dependencies": {
+                "path-key": "^4.0.0"
+            },
+            "engines": {
+                "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
+        "node_modules/npm-run-path/node_modules/path-key": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+            "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+            "dev": true,
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/npm/node_modules/@colors/colors": {
             "version": "1.5.0",
             "dev": true,
@@ -14731,6 +15202,21 @@
                 "node": ">=6"
             }
         },
+        "node_modules/p-map": {
+            "version": "4.0.0",
+            "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+            "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+            "dev": true,
+            "dependencies": {
+                "aggregate-error": "^3.0.0"
+            },
+            "engines": {
+                "node": ">=10"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/p-try": {
             "version": "2.2.0",
             "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
@@ -14868,6 +15354,18 @@
                 "url": "https://github.com/sponsors/jonschlinkert"
             }
         },
+        "node_modules/pidtree": {
+            "version": "0.6.0",
+            "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+            "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+            "dev": true,
+            "bin": {
+                "pidtree": "bin/pidtree.js"
+            },
+            "engines": {
+                "node": ">=0.10"
+            }
+        },
         "node_modules/pify": {
             "version": "2.3.0",
             "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@@ -15877,6 +16375,12 @@
                 "node": ">=0.10.0"
             }
         },
+        "node_modules/rfdc": {
+            "version": "1.3.0",
+            "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
+            "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
+            "dev": true
+        },
         "node_modules/rimraf": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -15980,9 +16484,9 @@
             "license": "MIT"
         },
         "node_modules/rpc-websockets": {
-            "version": "7.5.0",
-            "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.5.0.tgz",
-            "integrity": "sha512-9tIRi1uZGy7YmDjErf1Ax3wtqdSSLIlnmL5OtOzgd5eqPKbsPpwDP5whUDO2LQay3Xp0CcHlcNSGzacNRluBaQ==",
+            "version": "7.5.1",
+            "resolved": "https://registry.npmjs.org/rpc-websockets/-/rpc-websockets-7.5.1.tgz",
+            "integrity": "sha512-kGFkeTsmd37pHPMaHIgN1LVKXMi0JD782v4Ds9ZKtLlwdTKjn+CxM9A9/gLT2LaOuEcEFGL98h1QWQtlOIdW0w==",
             "dependencies": {
                 "@babel/runtime": "^7.17.2",
                 "eventemitter3": "^4.0.7",
@@ -15999,9 +16503,9 @@
             }
         },
         "node_modules/rpc-websockets/node_modules/ws": {
-            "version": "8.12.0",
-            "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
-            "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
+            "version": "8.13.0",
+            "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz",
+            "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==",
             "engines": {
                 "node": ">=10.0.0"
             },
@@ -16647,6 +17151,18 @@
                 "node": ">=4"
             }
         },
+        "node_modules/strip-final-newline": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+            "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+            "dev": true,
+            "engines": {
+                "node": ">=12"
+            },
+            "funding": {
+                "url": "https://github.com/sponsors/sindresorhus"
+            }
+        },
         "node_modules/strip-indent": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -17571,6 +18087,11 @@
                 "node": ">=4.2.0"
             }
         },
+        "node_modules/typescript-collections": {
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/typescript-collections/-/typescript-collections-1.3.3.tgz",
+            "integrity": "sha512-7sI4e/bZijOzyURng88oOFZCISQPTHozfE2sUu5AviFYk5QV7fYGb6YiDl+vKjF/pICA354JImBImL9XJWUvdQ=="
+        },
         "node_modules/uc.micro": {
             "version": "1.0.6",
             "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
@@ -18089,11 +18610,10 @@
             "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
         },
         "node_modules/yaml": {
-            "version": "2.2.1",
-            "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz",
-            "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==",
+            "version": "2.2.2",
+            "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
+            "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
             "dev": true,
-            "license": "ISC",
             "engines": {
                 "node": ">= 14"
             }
@@ -18753,48 +19273,6 @@
                 "eslint-config-custom": "*",
                 "tsconfig": "*"
             }
-        },
-        "packages/xray/node_modules/@onsol/tldparser": {
-            "version": "0.5.1",
-            "resolved": "https://registry.npmjs.org/@onsol/tldparser/-/tldparser-0.5.1.tgz",
-            "integrity": "sha512-6AkUguYxyJWVkgkF56sbl2NnLQld0kqQmHEp3Gdgho+byReFUOUVN0A7wasTCMOEnBksl4CrlSzjRrkGOlFKDA==",
-            "dependencies": {
-                "@ethersproject/sha2": "^5.7.0",
-                "@metaplex-foundation/beet-solana": "^0.4.0"
-            },
-            "engines": {
-                "node": ">=14"
-            },
-            "peerDependencies": {
-                "@solana/web3.js": "^1.67.0",
-                "bn.js": "^5.2.1",
-                "borsh": "^0.7.0",
-                "buffer": "6.0.1"
-            }
-        },
-        "packages/xray/node_modules/buffer": {
-            "version": "6.0.3",
-            "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
-            "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
-            "funding": [
-                {
-                    "type": "github",
-                    "url": "https://github.com/sponsors/feross"
-                },
-                {
-                    "type": "patreon",
-                    "url": "https://www.patreon.com/feross"
-                },
-                {
-                    "type": "consulting",
-                    "url": "https://feross.org/support"
-                }
-            ],
-            "peer": true,
-            "dependencies": {
-                "base64-js": "^1.3.1",
-                "ieee754": "^1.2.1"
-            }
         }
     }
 }
diff --git a/package.json b/package.json
index 893c2f6e..02d920fd 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,15 @@
         "test": "turbo lint",
         "lint": "turbo lint",
         "lint:fix": "eslint . --fix",
-        "format": "prettier --write \"**/*.{ts,tsx,md,svelte}\""
+        "format": "prettier --write \"**/*.{ts,tsx,md,svelte}\"",
+        "prepare": "husky install"
+    },
+    "lint-staged": {
+        "*.{js,jsx,ts,tsx}": [
+            "npm run lint",
+            "npm run format",
+            "git add"
+        ]
     },
     "devDependencies": {
         "@typescript-eslint/eslint-plugin": "^5.52.0",
@@ -51,6 +59,8 @@
         "eslint-plugin-svelte3": "^4.0.0",
         "eslint-plugin-this": "^0.2.3",
         "eslint-plugin-write-good-comments": "^0.1.4",
+        "husky": "^8.0.3",
+        "lint-staged": "^13.2.2",
         "nodemon": "^2.0.20",
         "prettier": "^2.8.4",
         "prettier-plugin-css-order": "^1.3.0",
@@ -69,5 +79,8 @@
     "engines": {
         "node": ">=18.0.0"
     },
-    "packageManager": "npm@8.19.2"
+    "packageManager": "npm@8.19.2",
+    "dependencies": {
+        "@solana/spl-account-compression": "^0.1.8"
+    }
 }
diff --git a/packages/helius-sdk/README.md b/packages/helius-sdk/README.md
index 95f20af2..e809e977 100644
--- a/packages/helius-sdk/README.md
+++ b/packages/helius-sdk/README.md
@@ -48,7 +48,7 @@ import {
     // enums
     Address,
     TransactionType,
-    
+
     // lib
     Helius,
 } from "helius-sdk";
@@ -56,9 +56,9 @@ import {
 const helius = new Helius("<your-api-key-here>");
 
 helius.createWebhook({
-  accountAddresses: [Address.MAGIC_EDEN_V2],
-  transactionTypes: [TransactionType.NFT_LISTING],
-  webhookURL: "my-webhook-handler.com/handle",
+    accountAddresses: [Address.MAGIC_EDEN_V2],
+    transactionTypes: [TransactionType.NFT_LISTING],
+    webhookURL: "my-webhook-handler.com/handle",
 });
 ```
 
@@ -66,22 +66,21 @@ If you'd like to work with the native Solana transaction format instead of Heliu
 
 ```ts
 import {
-  // enums
-  TransactionType,
-  WebhookType,
-  Address,
-
-  Helius
+    // enums
+    TransactionType,
+    WebhookType,
+    Address,
+    Helius,
 } from "helius-sdk";
 
 const helius = new Helius("<your-api-key-here>");
 
 helius.createWebhook({
-  accountAddresses: [Address.MAGIC_EDEN_V2],
-  authHeader: "some auth header",
-  webhookURL: "my-webhook-handler.com/handle",
-  webhookType: WebhookType.RAW,
-  transactionTypes: [TransactionType.ANY],
+    accountAddresses: [Address.MAGIC_EDEN_V2],
+    authHeader: "some auth header",
+    webhookURL: "my-webhook-handler.com/handle",
+    webhookType: WebhookType.RAW,
+    transactionTypes: [TransactionType.ANY],
 });
 ```
 
@@ -97,8 +96,8 @@ import { Helius, Address } from "helius-sdk";
 const helius = new Helius("<your-api-key-here>");
 
 helius.editWebhook(
-  "your-webhook-id-here",
-  { accountAddresses: [Address.SQUADS] } // This will ONLY update accountAddresses, not the other fields on the webhook object
+    "your-webhook-id-here",
+    { accountAddresses: [Address.SQUADS] } // This will ONLY update accountAddresses, not the other fields on the webhook object
 );
 ```
 
@@ -113,8 +112,8 @@ import { Helius, Address } from "helius-sdk";
 const helius = new Helius("<your-api-key-here>");
 
 helius.appendAddressesToWebhook("your-webhook-id-here", [
-  Address.SQUADS,
-  Address.JUPITER_V3,
+    Address.SQUADS,
+    Address.JUPITER_V3,
 ]);
 ```
 
@@ -152,19 +151,18 @@ helius.deleteWebhook("<webhook-id-here>"); // returns a boolean
 
 ```ts
 import {
-  // collections dict
-  Collections,
-
-  Helius,
+    // collections dict
+    Collections,
+    Helius,
 } from "helius-sdk";
 
 const helius = new Helius("<your-api-key-here>");
 
 helius.createCollectionWebhook({
-  collectionQuery: Collections.ABC,
-  transactionTypes: [Types.TransactionType.ANY],
-  webhookType: Types.WebhookType.DISCORD,
-  webhookURL: "https://discord.com/api/webhooks/your-discord-token-here",
+    collectionQuery: Collections.ABC,
+    transactionTypes: [Types.TransactionType.ANY],
+    webhookType: Types.WebhookType.DISCORD,
+    webhookURL: "https://discord.com/api/webhooks/your-discord-token-here",
 });
 ```
 
@@ -191,11 +189,12 @@ const mints = helius.getMintlist({
 });
 ```
 
-
 ## RPC Abstractions
+
 We provide a variety of helper methods to help make Solana RPCs easier to work with.
 
 ### Solana Chain TPS
+
 ```ts
 import { Helius } from "helius-sdk";
 
@@ -205,10 +204,14 @@ const tps = await helius.rpc.getCurrentTPS();
 ```
 
 ### Solana Airdrop
+
 ```ts
 import { Helius } from "helius-sdk";
 
 const helius = new Helius("<your-api-key-here>");
 
-const response = await helius.rpc.airdrop(new PublicKey("<wallet address>"), 1000000000); // 1 sol
+const response = await helius.rpc.airdrop(
+    new PublicKey("<wallet address>"),
+    1000000000
+); // 1 sol
 ```
diff --git a/packages/helius-sdk/src/Helius.ts b/packages/helius-sdk/src/Helius.ts
index 68a2bd73..66199f9e 100644
--- a/packages/helius-sdk/src/Helius.ts
+++ b/packages/helius-sdk/src/Helius.ts
@@ -1,11 +1,11 @@
 import {
-  Webhook,
-  CreateWebhookRequest,
-  EditWebhookRequest,
-  CreateCollectionWebhookRequest,
-  MintlistRequest,
-  MintlistResponse,
-  MintlistItem,
+    Webhook,
+    CreateWebhookRequest,
+    EditWebhookRequest,
+    CreateCollectionWebhookRequest,
+    MintlistRequest,
+    MintlistResponse,
+    MintlistItem,
 } from "./types";
 
 import axios, { type AxiosError } from "axios";
@@ -18,320 +18,358 @@ const API_URL_V1: string = "https://api.helius.xyz/v1";
 
 /**
  * This is the base level class for interfacing with all Helius API methods.
+ *
  * @class
  */
 export class Helius {
-  /**
-   * API key generated at dev.helius.xyz
-   * @private
-   */
-  private apiKey: string;
+    /**
+     * API key generated at dev.helius.xyz
+     *
+     * @private
+     */
+    private apiKey: string;
 
-  /** The cluster in which the connection endpoint belongs to */
-  public readonly cluster: Cluster;
+    /** The cluster in which the connection endpoint belongs to */
+    public readonly cluster: Cluster;
 
-  /** URL to the fullnode JSON RPC endpoint */
-  public readonly endpoint: string;
+    /** URL to the fullnode JSON RPC endpoint */
+    public readonly endpoint: string;
 
-  /** The connection object from Solana's SDK */
-  public readonly connection: Connection;
+    /** The connection object from Solana's SDK */
+    public readonly connection: Connection;
 
-  /** The beefed up rpc client object from Helius SDK */
-  public readonly rpc: RpcClient;
+    /** The beefed up rpc client object from Helius SDK */
+    public readonly rpc: RpcClient;
 
-  /**
-   * Initializes Helius API client with an API key
-   * @constructor
-   * @param apiKey - API key generated at dev.helius.xyz
-   */
-  constructor(apiKey: string, cluster: Cluster = "mainnet-beta") {
-    this.apiKey = apiKey;
-    this.cluster = cluster;
-    this.endpoint = heliusClusterApiUrl(apiKey, cluster);
-    this.connection = new Connection(this.endpoint);
-    this.rpc = new RpcClient(this.connection);
-  }
+    /**
+     * Initializes Helius API client with an API key
+     *
+     * @class
+     * @param apiKey - API key generated at dev.helius.xyz
+     */
+    constructor(apiKey: string, cluster: Cluster = "mainnet-beta") {
+        this.apiKey = apiKey;
+        this.cluster = cluster;
+        this.endpoint = heliusClusterApiUrl(apiKey, cluster);
+        this.connection = new Connection(this.endpoint);
+        this.rpc = new RpcClient(this.connection);
+    }
 
-  /**
-   * Retrieves a list of all webhooks associated with the current API key
-   * @returns {Promise<Webhook[]>} a promise that resolves to an array of webhook objects
-   * @throws {Error} if there is an error calling the webhooks endpoint or if the response contains an error
-   */
-  async getAllWebhooks(): Promise<Webhook[]> {
-    try {
-      const { data } = await axios.get(
-        `${API_URL_V0}/webhooks?api-key=${this.apiKey}`
-      );
-      return data;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error calling getWebhooks: ${err.response?.data.error || err}`
-        );
-      } else {
-        throw new Error(`error calling getWebhooks: ${err}`);
-      }
+    /**
+     * Retrieves a list of all webhooks associated with the current API key
+     *
+     * @returns {Promise<Webhook[]>} A promise that resolves to an array of
+     *   webhook objects
+     * @throws {Error} If there is an error calling the webhooks endpoint or if
+     *   the response contains an error
+     */
+    async getAllWebhooks(): Promise<Webhook[]> {
+        try {
+            const { data } = await axios.get(
+                `${API_URL_V0}/webhooks?api-key=${this.apiKey}`
+            );
+            return data;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error calling getWebhooks: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error calling getWebhooks: ${err}`);
+            }
+        }
     }
-  }
 
-  /**
-   * Retrieves a single webhook by its ID, associated with the current API key
-   * @param {string} webhookID - the ID of the webhook to retrieve
-   * @returns {Promise<Webhook>} a promise that resolves to a webhook object
-   * @throws {Error} if there is an error calling the webhooks endpoint or if the response contains an error
-   */
-  async getWebhookByID(webhookID: string): Promise<Webhook> {
-    try {
-      const { data } = await axios.get(
-        `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`
-      );
-      return data;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during getWebhookByID: ${err.response?.data.error || err}`
-        );
-      } else {
-        throw new Error(`error during getWebhookByID: ${err}`);
-      }
+    /**
+     * Retrieves a single webhook by its ID, associated with the current API key
+     *
+     * @param {string} webhookID - The ID of the webhook to retrieve
+     * @returns {Promise<Webhook>} A promise that resolves to a webhook object
+     * @throws {Error} If there is an error calling the webhooks endpoint or if
+     *   the response contains an error
+     */
+    async getWebhookByID(webhookID: string): Promise<Webhook> {
+        try {
+            const { data } = await axios.get(
+                `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`
+            );
+            return data;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during getWebhookByID: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error during getWebhookByID: ${err}`);
+            }
+        }
     }
-  }
 
-  /**
-   * Creates a new webhook with the provided request
-   * @param {CreateWebhookRequest} createWebhookRequest - the request object containing the webhook information
-   * @returns {Promise<Webhook>} a promise that resolves to the created webhook object
-   * @throws {Error} if there is an error calling the webhooks endpoint or if the response contains an error
-   */
-  async createWebhook(
-    createWebhookRequest: CreateWebhookRequest
-  ): Promise<Webhook> {
-    try {
-      const { data } = await axios.post(
-        `${API_URL_V0}/webhooks?api-key=${this.apiKey}`,
-        { ...createWebhookRequest }
-      );
-      return data;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during createWebhook: ${err.response?.data.error || err}`
-        );
-      } else {
-        throw new Error(`error during createWebhook: ${err}`);
-      }
+    /**
+     * Creates a new webhook with the provided request
+     *
+     * @param {CreateWebhookRequest} createWebhookRequest - The request object
+     *   containing the webhook information
+     * @returns {Promise<Webhook>} A promise that resolves to the created webhook
+     *   object
+     * @throws {Error} If there is an error calling the webhooks endpoint or if
+     *   the response contains an error
+     */
+    async createWebhook(
+        createWebhookRequest: CreateWebhookRequest
+    ): Promise<Webhook> {
+        try {
+            const { data } = await axios.post(
+                `${API_URL_V0}/webhooks?api-key=${this.apiKey}`,
+                { ...createWebhookRequest }
+            );
+            return data;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during createWebhook: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error during createWebhook: ${err}`);
+            }
+        }
     }
-  }
 
-  /**
-   * Deletes a webhook by its ID
-   * @param {string} webhookID - the ID of the webhook to delete
-   * @returns {Promise<boolean>} a promise that resolves to true if the webhook was successfully deleted, or false otherwise
-   * @throws {Error} if there is an error calling the webhooks endpoint or if the response contains an error
-   */
-  async deleteWebhook(webhookID: string): Promise<boolean> {
-    try {
-      await axios.delete(
-        `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`
-      );
-      return true;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during deleteWebhook: ${err.response?.data.error || err}`
-        );
-      } else {
-        throw new Error(`error during deleteWebhook: ${err}`);
-      }
+    /**
+     * Deletes a webhook by its ID
+     *
+     * @param {string} webhookID - The ID of the webhook to delete
+     * @returns {Promise<boolean>} A promise that resolves to true if the webhook
+     *   was successfully deleted, or false otherwise
+     * @throws {Error} If there is an error calling the webhooks endpoint or if
+     *   the response contains an error
+     */
+    async deleteWebhook(webhookID: string): Promise<boolean> {
+        try {
+            await axios.delete(
+                `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`
+            );
+            return true;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during deleteWebhook: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error during deleteWebhook: ${err}`);
+            }
+        }
     }
-  }
 
-  /**
-   * Edits an existing webhook by its ID with the provided request
-   * @param {string} webhookID - the ID of the webhook to edit
-   * @param {EditWebhookRequest} editWebhookRequest - the request object containing the webhook information
-   * @returns {Promise<Webhook>} a promise that resolves to the edited webhook object
-   * @throws {Error} if there is an error calling the webhooks endpoint or if the response contains an error
-   */
-  async editWebhook(
-    webhookID: string,
-    editWebhookRequest: EditWebhookRequest
-  ): Promise<Webhook> {
-    try {
-      const webhook = await this.getWebhookByID(webhookID);
-      const editRequest: Partial<Webhook> = {
-        ...webhook,
-        ...editWebhookRequest,
-      };
-      delete editRequest["webhookID"];
-      delete editRequest["wallet"];
+    /**
+     * Edits an existing webhook by its ID with the provided request
+     *
+     * @param {string} webhookID - The ID of the webhook to edit
+     * @param {EditWebhookRequest} editWebhookRequest - The request object
+     *   containing the webhook information
+     * @returns {Promise<Webhook>} A promise that resolves to the edited webhook
+     *   object
+     * @throws {Error} If there is an error calling the webhooks endpoint or if
+     *   the response contains an error
+     */
+    async editWebhook(
+        webhookID: string,
+        editWebhookRequest: EditWebhookRequest
+    ): Promise<Webhook> {
+        try {
+            const webhook = await this.getWebhookByID(webhookID);
+            const editRequest: Partial<Webhook> = {
+                ...webhook,
+                ...editWebhookRequest,
+            };
+            delete editRequest["webhookID"];
+            delete editRequest["wallet"];
 
-      const { data } = await axios.put(
-        `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`,
-        editRequest
-      );
-      return data;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during editWebhook: ${err.response?.data.error || err}`
-        );
-      } else {
-        throw new Error(`error during editWebhook: ${err}`);
-      }
+            const { data } = await axios.put(
+                `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`,
+                editRequest
+            );
+            return data;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during editWebhook: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error during editWebhook: ${err}`);
+            }
+        }
     }
-  }
 
-  /**
-   * Appends an array of addresses to an existing webhook by its ID
-   * @param {string} webhookID - the ID of the webhook to edit
-   * @param {string[]} newAccountAddresses - the array of addresses to be added to the webhook
-   * @returns {Promise<Webhook>} a promise that resolves to the edited webhook object
-   * @throws {Error} if there is an error calling the webhooks endpoint, if the response contains an error, or if the number of addresses exceeds 10,000
-   */
-  async appendAddressesToWebhook(
-    webhookID: string,
-    newAccountAddresses: string[]
-  ): Promise<Webhook> {
-    try {
-      const webhook = await this.getWebhookByID(webhookID);
-      const accountAddresses =
-        webhook.accountAddresses.concat(newAccountAddresses);
-      webhook.accountAddresses = accountAddresses;
-      if (accountAddresses.length > 100_000) {
-        throw new Error(
-          `a single webhook cannot contain more than 100,000 addresses`
-        );
-      }
-      const editRequest: Partial<Webhook> = {
-        ...webhook,
-      };
-      delete editRequest["webhookID"];
-      delete editRequest["wallet"];
+    /**
+     * Appends an array of addresses to an existing webhook by its ID
+     *
+     * @param {string} webhookID - The ID of the webhook to edit
+     * @param {string[]} newAccountAddresses - The array of addresses to be added
+     *   to the webhook
+     * @returns {Promise<Webhook>} A promise that resolves to the edited webhook
+     *   object
+     * @throws {Error} If there is an error calling the webhooks endpoint, if the
+     *   response contains an error, or if the number of addresses exceeds 10,000
+     */
+    async appendAddressesToWebhook(
+        webhookID: string,
+        newAccountAddresses: string[]
+    ): Promise<Webhook> {
+        try {
+            const webhook = await this.getWebhookByID(webhookID);
+            const accountAddresses =
+                webhook.accountAddresses.concat(newAccountAddresses);
+            webhook.accountAddresses = accountAddresses;
+            if (accountAddresses.length > 100_000) {
+                throw new Error(
+                    `a single webhook cannot contain more than 100,000 addresses`
+                );
+            }
+            const editRequest: Partial<Webhook> = {
+                ...webhook,
+            };
+            delete editRequest["webhookID"];
+            delete editRequest["wallet"];
 
-      const { data } = await axios.put(
-        `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`,
-        editRequest
-      );
-      return data;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during appendAddressesToWebhook: ${
-            err.response?.data.error || err
-          }`
-        );
-      } else {
-        throw new Error(`error during appendAddressesToWebhook: ${err}`);
-      }
+            const { data } = await axios.put(
+                `${API_URL_V0}/webhooks/${webhookID}?api-key=${this.apiKey}`,
+                editRequest
+            );
+            return data;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during appendAddressesToWebhook: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(
+                    `error during appendAddressesToWebhook: ${err}`
+                );
+            }
+        }
     }
-  }
 
-  async createCollectionWebhook(
-    request: CreateCollectionWebhookRequest
-  ): Promise<Webhook> {
-    if (request?.collectionQuery == undefined) {
-      throw new Error(`must provide collectionQuery object.`);
-    }
+    async createCollectionWebhook(
+        request: CreateCollectionWebhookRequest
+    ): Promise<Webhook> {
+        if (request?.collectionQuery == undefined) {
+            throw new Error(`must provide collectionQuery object.`);
+        }
 
-    const { firstVerifiedCreators, verifiedCollectionAddresses } =
-      request.collectionQuery;
-    if (
-      firstVerifiedCreators != undefined &&
-      verifiedCollectionAddresses != undefined
-    ) {
-      throw new Error(
-        `cannot provide both firstVerifiedCreators and verifiedCollectionAddresses. Please only provide one.`
-      );
-    }
+        const { firstVerifiedCreators, verifiedCollectionAddresses } =
+            request.collectionQuery;
+        if (
+            firstVerifiedCreators != undefined &&
+            verifiedCollectionAddresses != undefined
+        ) {
+            throw new Error(
+                `cannot provide both firstVerifiedCreators and verifiedCollectionAddresses. Please only provide one.`
+            );
+        }
 
-    let mintlist: MintlistItem[] = [];
-    let query = {};
+        let mintlist: MintlistItem[] = [];
+        let query = {};
 
-    if (firstVerifiedCreators != undefined) {
-      query = { firstVerifiedCreators };
-    } else {
-      // must have used verifiedCollectionAddresses
-      query = { verifiedCollectionAddresses };
-    }
+        if (firstVerifiedCreators != undefined) {
+            query = { firstVerifiedCreators };
+        } else {
+            // must have used verifiedCollectionAddresses
+            query = { verifiedCollectionAddresses };
+        }
 
-    try {
-      let mints = await this.getMintlist({
-        query,
-        options: {
-          limit: 10000,
-        },
-      });
-      mintlist.push(...mints.result);
+        try {
+            let mints = await this.getMintlist({
+                query,
+                options: {
+                    limit: 10000,
+                },
+            });
+            mintlist.push(...mints.result);
 
-      while (mints.paginationToken) {
-        mints = await this.getMintlist({
-          query,
-          options: {
-            limit: 10000,
-            paginationToken: mints.paginationToken,
-          },
-        });
-        mintlist.push(...mints.result);
-      }
+            while (mints.paginationToken) {
+                mints = await this.getMintlist({
+                    query,
+                    options: {
+                        limit: 10000,
+                        paginationToken: mints.paginationToken,
+                    },
+                });
+                mintlist.push(...mints.result);
+            }
 
-      const { webhookURL, transactionTypes, authHeader, webhookType } = request;
-      const payload: CreateWebhookRequest = {
-        webhookURL,
-        accountAddresses: mintlist.map((x) => x.mint),
-        transactionTypes,
-      };
-      if (authHeader) {
-        payload["authHeader"] = authHeader;
-      }
-      if (webhookType) {
-        payload["webhookType"] = webhookType;
-      }
+            const { webhookURL, transactionTypes, authHeader, webhookType } =
+                request;
+            const payload: CreateWebhookRequest = {
+                webhookURL,
+                accountAddresses: mintlist.map((x) => x.mint),
+                transactionTypes,
+            };
+            if (authHeader) {
+                payload["authHeader"] = authHeader;
+            }
+            if (webhookType) {
+                payload["webhookType"] = webhookType;
+            }
 
-      return await this.createWebhook({ ...payload });
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during createCollectionWebhook: ${
-            err.response?.data.error || err
-          }`
-        );
-      } else {
-        throw new Error(`error during createCollectionWebhook: ${err}`);
-      }
+            return await this.createWebhook({ ...payload });
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during createCollectionWebhook: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error during createCollectionWebhook: ${err}`);
+            }
+        }
     }
-  }
 
-  async getMintlist(request: MintlistRequest): Promise<MintlistResponse> {
-    if (request?.query == undefined) {
-      throw new Error(`must provide query object.`);
-    }
+    async getMintlist(request: MintlistRequest): Promise<MintlistResponse> {
+        if (request?.query == undefined) {
+            throw new Error(`must provide query object.`);
+        }
 
-    const { firstVerifiedCreators, verifiedCollectionAddresses } =
-      request.query;
-    if (
-      firstVerifiedCreators != undefined &&
-      verifiedCollectionAddresses != undefined
-    ) {
-      throw new Error(
-        `cannot provide both firstVerifiedCreators and verifiedCollectionAddresses. Please only provide one.`
-      );
-    }
+        const { firstVerifiedCreators, verifiedCollectionAddresses } =
+            request.query;
+        if (
+            firstVerifiedCreators != undefined &&
+            verifiedCollectionAddresses != undefined
+        ) {
+            throw new Error(
+                `cannot provide both firstVerifiedCreators and verifiedCollectionAddresses. Please only provide one.`
+            );
+        }
 
-    try {
-      const { data } = await axios.post(
-        `${API_URL_V1}/mintlist?api-key=${this.apiKey}`,
-        { ...request }
-      );
-      return data;
-    } catch (err: any | AxiosError) {
-      if (axios.isAxiosError(err)) {
-        throw new Error(
-          `error during getMintlist: ${err.response?.data.error || err}`
-        );
-      } else {
-        throw new Error(`error during getMintlist: ${err}`);
-      }
+        try {
+            const { data } = await axios.post(
+                `${API_URL_V1}/mintlist?api-key=${this.apiKey}`,
+                { ...request }
+            );
+            return data;
+        } catch (err: any | AxiosError) {
+            if (axios.isAxiosError(err)) {
+                throw new Error(
+                    `error during getMintlist: ${
+                        err.response?.data.error || err
+                    }`
+                );
+            } else {
+                throw new Error(`error during getMintlist: ${err}`);
+            }
+        }
     }
-  }
 }
diff --git a/packages/helius-sdk/src/RpcClient.ts b/packages/helius-sdk/src/RpcClient.ts
index add180e3..63344362 100644
--- a/packages/helius-sdk/src/RpcClient.ts
+++ b/packages/helius-sdk/src/RpcClient.ts
@@ -1,70 +1,83 @@
 import {
-  BlockhashWithExpiryBlockHeight,
-  TransactionSignature,
-  Commitment,
-  PublicKey,
-  GetLatestBlockhashConfig,
-  RpcResponseAndContext,
-  SignatureResult,
-  Blockhash,
-  Connection,
+    BlockhashWithExpiryBlockHeight,
+    TransactionSignature,
+    Commitment,
+    PublicKey,
+    GetLatestBlockhashConfig,
+    RpcResponseAndContext,
+    SignatureResult,
+    Blockhash,
+    Connection,
 } from "@solana/web3.js";
 
 export type SendAndConfirmTransactionResponse = {
-  signature: TransactionSignature;
-  confirmResponse: RpcResponseAndContext<SignatureResult>;
-  blockhash: Blockhash;
-  lastValidBlockHeight: number;
+    signature: TransactionSignature;
+    confirmResponse: RpcResponseAndContext<SignatureResult>;
+    blockhash: Blockhash;
+    lastValidBlockHeight: number;
 };
 
 export class RpcClient {
-  constructor(protected readonly connection: Connection) {}
+    constructor(protected readonly connection: Connection) {}
 
-  /**
-   * Request an allocation of lamports to the specified address
-   * @returns {Promise<SendAndConfirmTransactionResponse>}
-   */
-  async airdrop(
-    publicKey: PublicKey,
-    lamports: number,
-    commitment?: Commitment
-  ): Promise<SendAndConfirmTransactionResponse> {
-    const signature = await this.connection.requestAirdrop(publicKey, lamports);
+    /**
+     * Request an allocation of lamports to the specified address
+     *
+     * @returns {Promise<SendAndConfirmTransactionResponse>}
+     */
+    async airdrop(
+        publicKey: PublicKey,
+        lamports: number,
+        commitment?: Commitment
+    ): Promise<SendAndConfirmTransactionResponse> {
+        const signature = await this.connection.requestAirdrop(
+            publicKey,
+            lamports
+        );
 
-    const blockhashWithExpiryBlockHeight = await this.getLatestBlockhash();
-    const confirmResponse = await this.connection.confirmTransaction(
-      {
-        signature,
-        ...blockhashWithExpiryBlockHeight,
-      },
-      commitment
-    );
+        const blockhashWithExpiryBlockHeight = await this.getLatestBlockhash();
+        const confirmResponse = await this.connection.confirmTransaction(
+            {
+                signature,
+                ...blockhashWithExpiryBlockHeight,
+            },
+            commitment
+        );
 
-    return { signature, confirmResponse, ...blockhashWithExpiryBlockHeight };
-  }
+        return {
+            signature,
+            confirmResponse,
+            ...blockhashWithExpiryBlockHeight,
+        };
+    }
 
-  /**
-   * Fetch the latest blockhash from the cluster
-   * @returns {Promise<BlockhashWithExpiryBlockHeight>}
-   */
-  async getLatestBlockhash(
-    commitmentOrConfig: Commitment | GetLatestBlockhashConfig = "finalized"
-  ): Promise<BlockhashWithExpiryBlockHeight> {
-    return this.connection.getLatestBlockhash(commitmentOrConfig);
-  }
+    /**
+     * Fetch the latest blockhash from the cluster
+     *
+     * @returns {Promise<BlockhashWithExpiryBlockHeight>}
+     */
+    async getLatestBlockhash(
+        commitmentOrConfig: Commitment | GetLatestBlockhashConfig = "finalized"
+    ): Promise<BlockhashWithExpiryBlockHeight> {
+        return this.connection.getLatestBlockhash(commitmentOrConfig);
+    }
 
-  /**
-   * Returns the current transactions per second (TPS) rate — including voting transactions.
-   *
-   * @returns {Promise<number>} A promise that resolves to the current TPS rate.
-   * @throws {Error} If there was an error calling the `getRecentPerformanceSamples` method.
-   */
-  async getCurrentTPS(): Promise<number> {
-    try {
-      const samples = await this.connection.getRecentPerformanceSamples(1);
-      return samples[0]?.numTransactions / samples[0]?.samplePeriodSecs;
-    } catch (e) {
-      throw new Error(`error calling getCurrentTPS: ${e}`);
+    /**
+     * Returns the current transactions per second (TPS) rate — including voting
+     * transactions.
+     *
+     * @returns {Promise<number>} A promise that resolves to the current TPS rate.
+     * @throws {Error} If there was an error calling the
+     *   `getRecentPerformanceSamples` method.
+     */
+    async getCurrentTPS(): Promise<number> {
+        try {
+            const samples = await this.connection.getRecentPerformanceSamples(
+                1
+            );
+            return samples[0]?.numTransactions / samples[0]?.samplePeriodSecs;
+        } catch (e) {
+            throw new Error(`error calling getCurrentTPS: ${e}`);
+        }
     }
-  }
 }
diff --git a/packages/helius-sdk/src/types/enums.ts b/packages/helius-sdk/src/types/enums.ts
index fc39a654..71f0c68c 100644
--- a/packages/helius-sdk/src/types/enums.ts
+++ b/packages/helius-sdk/src/types/enums.ts
@@ -4,163 +4,169 @@ export enum WebhookType {
     RAW = "raw",
     RAW_DEVNET = "rawDevnet",
     DISCORD = "discord",
-    DISCORD_DEVNET = "discordDevnet"
+    DISCORD_DEVNET = "discordDevnet",
 }
 
 export enum TransactionType {
-    UNKNOWN = 'UNKNOWN',
-    ANY = 'ANY',
-    NFT_BID = 'NFT_BID',
-    NFT_GLOBAL_BID = 'NFT_GLOBAL_BID',
-    NFT_GLOBAL_BID_CANCELLED = 'NFT_GLOBAL_BID_CANCELLED',
-    NFT_BID_CANCELLED = 'NFT_BID_CANCELLED',
-    NFT_LISTING = 'NFT_LISTING',
-    NFT_CANCEL_LISTING = 'NFT_CANCEL_LISTING',
-    NFT_SALE = 'NFT_SALE',
-    NFT_MINT = 'NFT_MINT',
-    NFT_AUCTION_CREATED = 'NFT_AUCTION_CREATED',
-    NFT_AUCTION_UPDATED = 'NFT_AUCTION_UPDATED',
-    NFT_AUCTION_CANCELLED = 'NFT_AUCTION_CANCELLED',
-    NFT_PARTICIPATION_REWARD = 'NFT_PARTICIPATION_REWARD',
-    NFT_MINT_REJECTED = 'NFT_MINT_REJECTED',
-    CREATE_STORE = 'CREATE_STORE',
-    WHITELIST_CREATOR = 'WHITELIST_CREATOR',
-    ADD_TO_WHITELIST = 'ADD_TO_WHITELIST',
-    REMOVE_FROM_WHITELIST = 'REMOVE_FROM_WHITELIST',
-    AUCTION_MANAGER_CLAIM_BID = 'AUCTION_MANAGER_CLAIM_BID',
-    EMPTY_PAYMENT_ACCOUNT = 'EMPTY_PAYMENT_ACCOUNT',
-    UPDATE_PRIMARY_SALE_METADATA = 'UPDATE_PRIMARY_SALE_METADATA',
-    ADD_TOKEN_TO_VAULT = 'ADD_TOKEN_TO_VAULT',
-    ACTIVATE_VAULT = 'ACTIVATE_VAULT',
-    INIT_VAULT = 'INIT_VAULT',
-    INIT_BANK = 'INIT_BANK',
-    INIT_STAKE = 'INIT_STAKE',
-    MERGE_STAKE = 'MERGE_STAKE',
-    SPLIT_STAKE = 'SPLIT_STAKE',
-    SET_BANK_FLAGS = 'SET_BANK_FLAGS',
-    SET_VAULT_LOCK = 'SET_VAULT_LOCK',
-    UPDATE_VAULT_OWNER = 'UPDATE_VAULT_OWNER',
-    UPDATE_BANK_MANAGER = 'UPDATE_BANK_MANAGER',
-    RECORD_RARITY_POINTS = 'RECORD_RARITY_POINTS',
-    ADD_RARITIES_TO_BANK = 'ADD_RARITIES_TO_BANK',
-    INIT_FARM = 'INIT_FARM',
-    INIT_FARMER = 'INIT_FARMER',
-    REFRESH_FARMER = 'REFRESH_FARMER',
-    UPDATE_FARM = 'UPDATE_FARM',
-    AUTHORIZE_FUNDER = 'AUTHORIZE_FUNDER',
-    DEAUTHORIZE_FUNDER = 'DEAUTHORIZE_FUNDER',
-    FUND_REWARD = 'FUND_REWARD',
-    CANCEL_REWARD = 'CANCEL_REWARD',
-    LOCK_REWARD = 'LOCK_REWARD',
-    PAYOUT = 'PAYOUT',
-    VALIDATE_SAFETY_DEPOSIT_BOX_V2 = 'VALIDATE_SAFETY_DEPOSIT_BOX_V2',
-    SET_AUTHORITY = 'SET_AUTHORITY',
-    INIT_AUCTION_MANAGER_V2 = 'INIT_AUCTION_MANAGER_V2',
-    UPDATE_EXTERNAL_PRICE_ACCOUNT = 'UPDATE_EXTERNAL_PRICE_ACCOUNT',
-    AUCTION_HOUSE_CREATE = 'AUCTION_HOUSE_CREATE',
-    CLOSE_ESCROW_ACCOUNT = 'CLOSE_ESCROW_ACCOUNT',
-    WITHDRAW = 'WITHDRAW',
-    DEPOSIT = 'DEPOSIT',
-    TRANSFER = 'TRANSFER',
-    BURN = 'BURN',
-    BURN_NFT = 'BURN_NFT',
-    PLATFORM_FEE = 'PLATFORM_FEE',
-    LOAN = 'LOAN',
-    RESCIND_LOAN = 'RESCIND_LOAN',
-    OFFER_LOAN = 'OFFER_LOAN',
-    REPAY_LOAN = 'REPAY_LOAN',
-    TAKE_LOAN = 'TAKE_LOAN',
-    FORECLOSE_LOAN = 'FORECLOSE_LOAN',
-    ADD_TO_POOL = 'ADD_TO_POOL',
-    REMOVE_FROM_POOL = 'REMOVE_FROM_POOL',
-    CLOSE_POSITION = 'CLOSE_POSITION',
-    UNLABELED = 'UNLABELED',
-    CLOSE_ACCOUNT = 'CLOSE_ACCOUNT',
-    WITHDRAW_GEM = 'WITHDRAW_GEM',
-    DEPOSIT_GEM = 'DEPOSIT_GEM',
-    STAKE_TOKEN = 'STAKE_TOKEN',
-    UNSTAKE_TOKEN = 'UNSTAKE_TOKEN',
-    STAKE_SOL = 'STAKE_SOL',
-    UNSTAKE_SOL = 'UNSTAKE_SOL',
-    CLAIM_REWARDS = 'CLAIM_REWARDS',
-    BUY_SUBSCRIPTION = 'BUY_SUBSCRIPTION',
-    SWAP = 'SWAP',
-    INIT_SWAP = 'INIT_SWAP',
-    CANCEL_SWAP = 'CANCEL_SWAP',
-    REJECT_SWAP = 'REJECT_SWAP',
-    INITIALIZE_ACCOUNT = 'INITIALIZE_ACCOUNT',
-    TOKEN_MINT = 'TOKEN_MINT',
-    CREATE_APPRAISAL = 'CREATE_APPRAISAL',
-    CANDY_MACHINE_WRAP = 'CANDY_MACHINE_WRAP',
-    CANDY_MACHINE_UNWRAP = 'CANDY_MACHINE_UNWRAP',
-    CANDY_MACHINE_UPDATE = 'CANDY_MACHINE_UPDATE',
-    CANDY_MACHINE_ROUTE = 'CANDY_MACHINE_ROUTE',
-    FRACTIONALIZE = 'FRACTIONALIZE',
-    DEPOSIT_FRACTIONAL_POOL = 'DEPOSIT_FRACTIONAL_POOL',
-    FUSE = 'FUSE',
-    CREATE_RAFFLE = 'CREATE_RAFFLE',
-    BUY_TICKETS = 'BUY_TICKETS',
-    UPDATE_ITEM = 'UPDATE_ITEM',
-    LIST_ITEM = 'LIST_ITEM',
-    DELIST_ITEM = 'DELIST_ITEM',
-    ADD_ITEM = 'ADD_ITEM',
-    CLOSE_ITEM = 'CLOSE_ITEM',
-    BUY_ITEM = 'BUY_ITEM',
-    FILL_ORDER = 'FILL_ORDER',
-    UPDATE_ORDER = 'UPDATE_ORDER',
-    CREATE_ORDER = 'CREATE_ORDER',
-    CLOSE_ORDER = 'CLOSE_ORDER',
-    CANCEL_ORDER = 'CANCEL_ORDER',
-    KICK_ITEM = 'KICK_ITEM',
-    UPGRADE_FOX = 'UPGRADE_FOX',
-    UPGRADE_FOX_REQUEST = 'UPGRADE_FOX_REQUEST',
-    LOAN_FOX = 'LOAN_FOX',
-    BORROW_FOX = 'BORROW_FOX',
-    SWITCH_FOX_REQUEST = 'SWITCH_FOX_REQUEST',
-    SWITCH_FOX = 'SWITCH_FOX',
-    CREATE_ESCROW = 'CREATE_ESCROW',
-    ACCEPT_REQUEST_ARTIST = 'ACCEPT_REQUEST_ARTIST',
-    CANCEL_ESCROW = 'CANCEL_ESCROW',
-    ACCEPT_ESCROW_ARTIST = 'ACCEPT_ESCROW_ARTIST',
-    ACCEPT_ESCROW_USER = 'ACCEPT_ESCROW_USER',
-    PLACE_BET = 'PLACE_BET',
-    PLACE_SOL_BET = 'PLACE_SOL_BET',
-    CREATE_BET = 'CREATE_BET',
-    INIT_RENT = 'INIT_RENT',
-    NFT_RENT_LISTING = 'NFT_RENT_LISTING',
-    NFT_RENT_CANCEL_LISTING = 'NFT_RENT_CANCEL_LISTING',
-    NFT_RENT_UPDATE_LISTING = 'NFT_RENT_UPDATE_LISTING',
-    NFT_RENT_ACTIVATE = 'NFT_RENT_ACTIVATE',
-    NFT_RENT_END = 'NFT_RENT_END',
-    UPGRADE_PROGRAM_INSTRUCTION = 'UPGRADE_PROGRAM_INSTRUCTION',
-    FINALIZE_PROGRAM_INSTRUCTION = 'FINALIZE_PROGRAM_INSTRUCTION',
-    EXECUTE_TRANSACTION = 'EXECUTE_TRANSACTION',
-    APPROVE_TRANSACTION = 'APPROVE_TRANSACTION',
-    ACTIVATE_TRANSACTION = 'ACTIVATE_TRANSACTION',
-    CREATE_TRANSACTION = 'CREATE_TRANSACTION',
-    CANCEL_TRANSACTION = 'CANCEL_TRANSACTION',
-    REJECT_TRANSACTION = 'REJECT_TRANSACTION',
-    ADD_INSTRUCTION = 'ADD_INSTRUCTION',
-    CREATE_MASTER_EDITION = 'CREATE_MASTER_EDITION',
-    ATTACH_METADATA = 'ATTACH_METADATA',
-    REQUEST_PNFT_MIGRATION = 'REQUEST_PNFT_MIGRATION',
-    START_PNFT_MIGRATION = 'START_PNFT_MIGRATION',
-    MIGRATE_TO_PNFT = 'MIGRATE_TO_PNFT',
-    CANCEL_OFFER = 'CANCEL_OFFER',
-    LEND_FOR_NFT = 'LEND_FOR_NFT',
-    REQUEST_LOAN = 'REQUEST_LOAN',
-    CANCEL_LOAN_REQUEST = 'CANCEL_LOAN_REQUEST',
-    BORROW_SOL_FOR_NFT = 'BORROW_SOL_FOR_NFT',
-    CLAIM_NFT = 'CLAIM_NFT',
-    REBORROW_SOL_FOR_NFT = 'REBORROW_SOL_FOR_NFT',
-    UPDATE_OFFER = 'UPDATE_OFFER',
+    UNKNOWN = "UNKNOWN",
+    ANY = "ANY",
+    NFT_BID = "NFT_BID",
+    NFT_GLOBAL_BID = "NFT_GLOBAL_BID",
+    NFT_GLOBAL_BID_CANCELLED = "NFT_GLOBAL_BID_CANCELLED",
+    NFT_BID_CANCELLED = "NFT_BID_CANCELLED",
+    NFT_LISTING = "NFT_LISTING",
+    NFT_CANCEL_LISTING = "NFT_CANCEL_LISTING",
+    NFT_SALE = "NFT_SALE",
+    NFT_MINT = "NFT_MINT",
+    NFT_AUCTION_CREATED = "NFT_AUCTION_CREATED",
+    NFT_AUCTION_UPDATED = "NFT_AUCTION_UPDATED",
+    NFT_AUCTION_CANCELLED = "NFT_AUCTION_CANCELLED",
+    NFT_PARTICIPATION_REWARD = "NFT_PARTICIPATION_REWARD",
+    NFT_MINT_REJECTED = "NFT_MINT_REJECTED",
+    CREATE_STORE = "CREATE_STORE",
+    WHITELIST_CREATOR = "WHITELIST_CREATOR",
+    ADD_TO_WHITELIST = "ADD_TO_WHITELIST",
+    REMOVE_FROM_WHITELIST = "REMOVE_FROM_WHITELIST",
+    AUCTION_MANAGER_CLAIM_BID = "AUCTION_MANAGER_CLAIM_BID",
+    EMPTY_PAYMENT_ACCOUNT = "EMPTY_PAYMENT_ACCOUNT",
+    UPDATE_PRIMARY_SALE_METADATA = "UPDATE_PRIMARY_SALE_METADATA",
+    ADD_TOKEN_TO_VAULT = "ADD_TOKEN_TO_VAULT",
+    ACTIVATE_VAULT = "ACTIVATE_VAULT",
+    INIT_VAULT = "INIT_VAULT",
+    INIT_BANK = "INIT_BANK",
+    INIT_STAKE = "INIT_STAKE",
+    MERGE_STAKE = "MERGE_STAKE",
+    SPLIT_STAKE = "SPLIT_STAKE",
+    SET_BANK_FLAGS = "SET_BANK_FLAGS",
+    SET_VAULT_LOCK = "SET_VAULT_LOCK",
+    UPDATE_VAULT_OWNER = "UPDATE_VAULT_OWNER",
+    UPDATE_BANK_MANAGER = "UPDATE_BANK_MANAGER",
+    RECORD_RARITY_POINTS = "RECORD_RARITY_POINTS",
+    ADD_RARITIES_TO_BANK = "ADD_RARITIES_TO_BANK",
+    INIT_FARM = "INIT_FARM",
+    INIT_FARMER = "INIT_FARMER",
+    REFRESH_FARMER = "REFRESH_FARMER",
+    UPDATE_FARM = "UPDATE_FARM",
+    AUTHORIZE_FUNDER = "AUTHORIZE_FUNDER",
+    DEAUTHORIZE_FUNDER = "DEAUTHORIZE_FUNDER",
+    FUND_REWARD = "FUND_REWARD",
+    CANCEL_REWARD = "CANCEL_REWARD",
+    LOCK_REWARD = "LOCK_REWARD",
+    PAYOUT = "PAYOUT",
+    VALIDATE_SAFETY_DEPOSIT_BOX_V2 = "VALIDATE_SAFETY_DEPOSIT_BOX_V2",
+    SET_AUTHORITY = "SET_AUTHORITY",
+    INIT_AUCTION_MANAGER_V2 = "INIT_AUCTION_MANAGER_V2",
+    UPDATE_EXTERNAL_PRICE_ACCOUNT = "UPDATE_EXTERNAL_PRICE_ACCOUNT",
+    AUCTION_HOUSE_CREATE = "AUCTION_HOUSE_CREATE",
+    CLOSE_ESCROW_ACCOUNT = "CLOSE_ESCROW_ACCOUNT",
+    WITHDRAW = "WITHDRAW",
+    DEPOSIT = "DEPOSIT",
+    TRANSFER = "TRANSFER",
+    BURN = "BURN",
+    BURN_NFT = "BURN_NFT",
+    PLATFORM_FEE = "PLATFORM_FEE",
+    LOAN = "LOAN",
+    RESCIND_LOAN = "RESCIND_LOAN",
+    OFFER_LOAN = "OFFER_LOAN",
+    REPAY_LOAN = "REPAY_LOAN",
+    TAKE_LOAN = "TAKE_LOAN",
+    FORECLOSE_LOAN = "FORECLOSE_LOAN",
+    ADD_TO_POOL = "ADD_TO_POOL",
+    REMOVE_FROM_POOL = "REMOVE_FROM_POOL",
+    CLOSE_POSITION = "CLOSE_POSITION",
+    UNLABELED = "UNLABELED",
+    CLOSE_ACCOUNT = "CLOSE_ACCOUNT",
+    WITHDRAW_GEM = "WITHDRAW_GEM",
+    DEPOSIT_GEM = "DEPOSIT_GEM",
+    STAKE_TOKEN = "STAKE_TOKEN",
+    UNSTAKE_TOKEN = "UNSTAKE_TOKEN",
+    STAKE_SOL = "STAKE_SOL",
+    UNSTAKE_SOL = "UNSTAKE_SOL",
+    CLAIM_REWARDS = "CLAIM_REWARDS",
+    BUY_SUBSCRIPTION = "BUY_SUBSCRIPTION",
+    SWAP = "SWAP",
+    INIT_SWAP = "INIT_SWAP",
+    CANCEL_SWAP = "CANCEL_SWAP",
+    REJECT_SWAP = "REJECT_SWAP",
+    INITIALIZE_ACCOUNT = "INITIALIZE_ACCOUNT",
+    TOKEN_MINT = "TOKEN_MINT",
+    CREATE_APPRAISAL = "CREATE_APPRAISAL",
+    CANDY_MACHINE_WRAP = "CANDY_MACHINE_WRAP",
+    CANDY_MACHINE_UNWRAP = "CANDY_MACHINE_UNWRAP",
+    CANDY_MACHINE_UPDATE = "CANDY_MACHINE_UPDATE",
+    CANDY_MACHINE_ROUTE = "CANDY_MACHINE_ROUTE",
+    FRACTIONALIZE = "FRACTIONALIZE",
+    DEPOSIT_FRACTIONAL_POOL = "DEPOSIT_FRACTIONAL_POOL",
+    FUSE = "FUSE",
+    CREATE_RAFFLE = "CREATE_RAFFLE",
+    BUY_TICKETS = "BUY_TICKETS",
+    UPDATE_ITEM = "UPDATE_ITEM",
+    LIST_ITEM = "LIST_ITEM",
+    DELIST_ITEM = "DELIST_ITEM",
+    ADD_ITEM = "ADD_ITEM",
+    CLOSE_ITEM = "CLOSE_ITEM",
+    BUY_ITEM = "BUY_ITEM",
+    FILL_ORDER = "FILL_ORDER",
+    UPDATE_ORDER = "UPDATE_ORDER",
+    CREATE_ORDER = "CREATE_ORDER",
+    CLOSE_ORDER = "CLOSE_ORDER",
+    CANCEL_ORDER = "CANCEL_ORDER",
+    KICK_ITEM = "KICK_ITEM",
+    UPGRADE_FOX = "UPGRADE_FOX",
+    UPGRADE_FOX_REQUEST = "UPGRADE_FOX_REQUEST",
+    LOAN_FOX = "LOAN_FOX",
+    BORROW_FOX = "BORROW_FOX",
+    SWITCH_FOX_REQUEST = "SWITCH_FOX_REQUEST",
+    SWITCH_FOX = "SWITCH_FOX",
+    CREATE_ESCROW = "CREATE_ESCROW",
+    ACCEPT_REQUEST_ARTIST = "ACCEPT_REQUEST_ARTIST",
+    CANCEL_ESCROW = "CANCEL_ESCROW",
+    ACCEPT_ESCROW_ARTIST = "ACCEPT_ESCROW_ARTIST",
+    ACCEPT_ESCROW_USER = "ACCEPT_ESCROW_USER",
+    PLACE_BET = "PLACE_BET",
+    PLACE_SOL_BET = "PLACE_SOL_BET",
+    CREATE_BET = "CREATE_BET",
+    INIT_RENT = "INIT_RENT",
+    NFT_RENT_LISTING = "NFT_RENT_LISTING",
+    NFT_RENT_CANCEL_LISTING = "NFT_RENT_CANCEL_LISTING",
+    NFT_RENT_UPDATE_LISTING = "NFT_RENT_UPDATE_LISTING",
+    NFT_RENT_ACTIVATE = "NFT_RENT_ACTIVATE",
+    NFT_RENT_END = "NFT_RENT_END",
+    UPGRADE_PROGRAM_INSTRUCTION = "UPGRADE_PROGRAM_INSTRUCTION",
+    FINALIZE_PROGRAM_INSTRUCTION = "FINALIZE_PROGRAM_INSTRUCTION",
+    EXECUTE_TRANSACTION = "EXECUTE_TRANSACTION",
+    APPROVE_TRANSACTION = "APPROVE_TRANSACTION",
+    ACTIVATE_TRANSACTION = "ACTIVATE_TRANSACTION",
+    CREATE_TRANSACTION = "CREATE_TRANSACTION",
+    CANCEL_TRANSACTION = "CANCEL_TRANSACTION",
+    REJECT_TRANSACTION = "REJECT_TRANSACTION",
+    ADD_INSTRUCTION = "ADD_INSTRUCTION",
+    CREATE_MASTER_EDITION = "CREATE_MASTER_EDITION",
+    ATTACH_METADATA = "ATTACH_METADATA",
+    REQUEST_PNFT_MIGRATION = "REQUEST_PNFT_MIGRATION",
+    START_PNFT_MIGRATION = "START_PNFT_MIGRATION",
+    MIGRATE_TO_PNFT = "MIGRATE_TO_PNFT",
+    CANCEL_OFFER = "CANCEL_OFFER",
+    LEND_FOR_NFT = "LEND_FOR_NFT",
+    REQUEST_LOAN = "REQUEST_LOAN",
+    CANCEL_LOAN_REQUEST = "CANCEL_LOAN_REQUEST",
+    BORROW_SOL_FOR_NFT = "BORROW_SOL_FOR_NFT",
+    CLAIM_NFT = "CLAIM_NFT",
+    REBORROW_SOL_FOR_NFT = "REBORROW_SOL_FOR_NFT",
+    UPDATE_OFFER = "UPDATE_OFFER",
 }
 
 // A list of common collections and their collection query
 export const Collections = {
-    ABC: { firstVerifiedCreators: ["GVkb5GuwGKydA4xXLT9PNpx63h7bhFNrDLQSxi6j5NuF"] },
-    DEGODS: { verifiedCollectionAddresses: ["6XxjKYFbcndh2gDcsUrmZgVEsoDxXMnfsaGY6fpTJzNr"] }
-}
+    ABC: {
+        firstVerifiedCreators: ["GVkb5GuwGKydA4xXLT9PNpx63h7bhFNrDLQSxi6j5NuF"],
+    },
+    DEGODS: {
+        verifiedCollectionAddresses: [
+            "6XxjKYFbcndh2gDcsUrmZgVEsoDxXMnfsaGY6fpTJzNr",
+        ],
+    },
+};
 
 export const NftEventTypes = [
     TransactionType.NFT_BID,
@@ -189,267 +195,267 @@ export const NftEventTypes = [
 ];
 
 export enum TransactionContext {
-    AUCTION = 'AUCTION',
-    INSTANT_SALE = 'INSTANT_SALE',
-    OFFER = 'OFFER',
-    GLOBAL_OFFER = 'GLOBAL_OFFER',
-    MINT = 'MINT',
-    UNKNOWN = 'UNKNOWN',
+    AUCTION = "AUCTION",
+    INSTANT_SALE = "INSTANT_SALE",
+    OFFER = "OFFER",
+    GLOBAL_OFFER = "GLOBAL_OFFER",
+    MINT = "MINT",
+    UNKNOWN = "UNKNOWN",
 }
 
 export enum Source {
-    FORM_FUNCTION = 'FORM_FUNCTION',
-    EXCHANGE_ART = 'EXCHANGE_ART',
-    CANDY_MACHINE_V3 = 'CANDY_MACHINE_V3',
-    CANDY_MACHINE_V2 = 'CANDY_MACHINE_V2',
-    CANDY_MACHINE_V1 = 'CANDY_MACHINE_V1',
-    UNKNOWN = 'UNKNOWN',
-    SOLANART = 'SOLANART',
-    SOLSEA = 'SOLSEA',
-    MAGIC_EDEN = 'MAGIC_EDEN',
-    HOLAPLEX = 'HOLAPLEX',
-    METAPLEX = 'METAPLEX',
-    OPENSEA = 'OPENSEA',
-    SOLANA_PROGRAM_LIBRARY = 'SOLANA_PROGRAM_LIBRARY',
-    ANCHOR = 'ANCHOR',
-    PHANTOM = 'PHANTOM',
-    SYSTEM_PROGRAM = 'SYSTEM_PROGRAM',
-    STAKE_PROGRAM = 'STAKE_PROGRAM',
-    COINBASE = 'COINBASE',
-    CORAL_CUBE = 'CORAL_CUBE',
-    HEDGE = 'HEDGE',
-    LAUNCH_MY_NFT = 'LAUNCH_MY_NFT',
-    GEM_BANK = 'GEM_BANK',
-    GEM_FARM = 'GEM_FARM',
-    DEGODS = 'DEGODS',
-    BSL = 'BLOCKSMITH_LABS',
-    YAWWW = 'YAWWW',
-    ATADIA = 'ATADIA',
-    DIGITAL_EYES = 'DIGITAL_EYES',
-    HYPERSPACE = 'HYPERSPACE',
-    TENSOR = 'TENSOR',
-    BIFROST = 'BIFROST',
-    JUPITER = 'JUPITER',
-    MERCURIAL = 'MERCURIAL_STABLE_SWAP',
-    SABER = 'SABER',
-    SERUM = 'SERUM',
-    STEP_FINANCE = 'STEP_FINANCE',
-    CROPPER = 'CROPPER',
-    RAYDIUM = 'RAYDIUM',
-    ALDRIN = 'ALDRIN',
-    CREMA = 'CREMA',
-    LIFINITY = 'LIFINITY',
-    CYKURA = 'CYKURA',
-    ORCA = 'ORCA',
-    MARINADE = 'MARINADE',
-    STEPN = 'STEPN',
-    SENCHA = 'SENCHA_EXCHANGE',
-    SAROS = 'SAROS',
-    ENGLISH_AUCTION = 'ENGLISH_AUCTION',
-    FOXY = 'FOXY',
-    HADESWAP = 'HADESWAP',
-    FOXY_STAKING = 'FOXY_STAKING',
-    FOXY_RAFFLE = 'FOXY_RAFFLE',
-    FOXY_TOKEN_MARKET = 'FOXY_TOKEN_MARKET',
-    FOXY_MISSIONS = 'FOXY_MISSIONS',
-    FOXY_MARMALADE = 'FOXY_MARMALADE',
-    FOXY_COINFLIP = 'FOXY_COINFLIP',
-    FOXY_AUCTION = 'FOXY_AUCTION',
-    CITRUS = 'CITRUS',
-    ZETA = 'ZETA',
-    ELIXIR = 'ELIXIR',
-    ELIXIR_LAUNCHPAD = 'ELIXIR_LAUNCHPAD',
-    CARDINAL_RENT = 'CARDINAL_RENT',
-    CARDINAL_STAKING = 'CARDINAL_STAKING',
-    BPF_LOADER = 'BPF_LOADER',
-    BPF_UPGRADEABLE_LOADER = 'BPF_UPGRADEABLE_LOADER',
-    SQUADS = 'SQUADS',
-    SHARKY_FI = 'SHARKY_FI',
-    OPEN_CREATOR_PROTOCOL = 'OPEN_CREATOR_PROTOCOL',
+    FORM_FUNCTION = "FORM_FUNCTION",
+    EXCHANGE_ART = "EXCHANGE_ART",
+    CANDY_MACHINE_V3 = "CANDY_MACHINE_V3",
+    CANDY_MACHINE_V2 = "CANDY_MACHINE_V2",
+    CANDY_MACHINE_V1 = "CANDY_MACHINE_V1",
+    UNKNOWN = "UNKNOWN",
+    SOLANART = "SOLANART",
+    SOLSEA = "SOLSEA",
+    MAGIC_EDEN = "MAGIC_EDEN",
+    HOLAPLEX = "HOLAPLEX",
+    METAPLEX = "METAPLEX",
+    OPENSEA = "OPENSEA",
+    SOLANA_PROGRAM_LIBRARY = "SOLANA_PROGRAM_LIBRARY",
+    ANCHOR = "ANCHOR",
+    PHANTOM = "PHANTOM",
+    SYSTEM_PROGRAM = "SYSTEM_PROGRAM",
+    STAKE_PROGRAM = "STAKE_PROGRAM",
+    COINBASE = "COINBASE",
+    CORAL_CUBE = "CORAL_CUBE",
+    HEDGE = "HEDGE",
+    LAUNCH_MY_NFT = "LAUNCH_MY_NFT",
+    GEM_BANK = "GEM_BANK",
+    GEM_FARM = "GEM_FARM",
+    DEGODS = "DEGODS",
+    BSL = "BLOCKSMITH_LABS",
+    YAWWW = "YAWWW",
+    ATADIA = "ATADIA",
+    DIGITAL_EYES = "DIGITAL_EYES",
+    HYPERSPACE = "HYPERSPACE",
+    TENSOR = "TENSOR",
+    BIFROST = "BIFROST",
+    JUPITER = "JUPITER",
+    MERCURIAL = "MERCURIAL_STABLE_SWAP",
+    SABER = "SABER",
+    SERUM = "SERUM",
+    STEP_FINANCE = "STEP_FINANCE",
+    CROPPER = "CROPPER",
+    RAYDIUM = "RAYDIUM",
+    ALDRIN = "ALDRIN",
+    CREMA = "CREMA",
+    LIFINITY = "LIFINITY",
+    CYKURA = "CYKURA",
+    ORCA = "ORCA",
+    MARINADE = "MARINADE",
+    STEPN = "STEPN",
+    SENCHA = "SENCHA_EXCHANGE",
+    SAROS = "SAROS",
+    ENGLISH_AUCTION = "ENGLISH_AUCTION",
+    FOXY = "FOXY",
+    HADESWAP = "HADESWAP",
+    FOXY_STAKING = "FOXY_STAKING",
+    FOXY_RAFFLE = "FOXY_RAFFLE",
+    FOXY_TOKEN_MARKET = "FOXY_TOKEN_MARKET",
+    FOXY_MISSIONS = "FOXY_MISSIONS",
+    FOXY_MARMALADE = "FOXY_MARMALADE",
+    FOXY_COINFLIP = "FOXY_COINFLIP",
+    FOXY_AUCTION = "FOXY_AUCTION",
+    CITRUS = "CITRUS",
+    ZETA = "ZETA",
+    ELIXIR = "ELIXIR",
+    ELIXIR_LAUNCHPAD = "ELIXIR_LAUNCHPAD",
+    CARDINAL_RENT = "CARDINAL_RENT",
+    CARDINAL_STAKING = "CARDINAL_STAKING",
+    BPF_LOADER = "BPF_LOADER",
+    BPF_UPGRADEABLE_LOADER = "BPF_UPGRADEABLE_LOADER",
+    SQUADS = "SQUADS",
+    SHARKY_FI = "SHARKY_FI",
+    OPEN_CREATOR_PROTOCOL = "OPEN_CREATOR_PROTOCOL",
 
     // Mints
-    W_SOL = 'W_SOL',
-    DUST = 'DUST',
-    SOLI = 'SOLI',
-    USDC = 'USDC',
-    FLWR = 'FLWR',
-    HDG = 'HDG',
-    MEAN = 'MEAN',
-    UXD = 'UXD',
-    SHDW = 'SHDW',
-    POLIS = 'POLIS',
-    ATLAS = 'ATLAS',
-    USH = 'USH',
-    TRTLS = 'TRTLS',
-    RUNNER = 'RUNNER',
-    INVICTUS = 'INVICTUS',
+    W_SOL = "W_SOL",
+    DUST = "DUST",
+    SOLI = "SOLI",
+    USDC = "USDC",
+    FLWR = "FLWR",
+    HDG = "HDG",
+    MEAN = "MEAN",
+    UXD = "UXD",
+    SHDW = "SHDW",
+    POLIS = "POLIS",
+    ATLAS = "ATLAS",
+    USH = "USH",
+    TRTLS = "TRTLS",
+    RUNNER = "RUNNER",
+    INVICTUS = "INVICTUS",
 }
 
 export enum ProgramName {
-    JUPITER_V1 = 'JUPITER_V1',
-    JUPITER_V2 = 'JUPITER_V2',
-    JUPITER_V3 = 'JUPITER_V3',
-    MERCURIAL_STABLE_SWAP = 'MERCURIAL_STABLE_SWAP',
-    SABER_STABLE_SWAP = 'SABER_STABLE_SWAP',
-    SABER_EXCHANGE = 'SABER_EXCHANGE',
-    SERUM_DEX_V1 = 'SERUM_DEX_V1',
-    SERUM_DEX_V2 = 'SERUM_DEX_V2',
-    SERUM_DEX_V3 = 'SERUM_DEX_V3',
-    SERUM_SWAP = 'SERUM_SWAP',
-    STEP_FINANCE = 'STEP_FINANCE',
-    CROPPER = 'CROPPER',
-    RAYDIUM_LIQUIDITY_POOL_V2 = 'RAYDIUM_LIQUIDITY_POOL_V2',
-    RAYDIUM_LIQUIDITY_POOL_V3 = 'RAYDIUM_LIQUIDITY_POOL_V3',
-    RAYDIUM_LIQUIDITY_POOL_V4 = 'RAYDIUM_LIQUIDITY_POOL_V4',
-    ALDRIN_AMM_V1 = 'ALDRIN_AMM_V1',
-    ALDRIN_AMM_V2 = 'ALDRIN_AMM_V2',
-    CREMA = 'CREMA',
-    LIFINITY = 'LIFINITY',
-    CYKURA = 'CYKURA',
-    ORCA_TOKEN_SWAP_V1 = 'ORCA_TOKEN_SWAP_V1',
-    ORCA_TOKEN_SWAP_V2 = 'ORCA_TOKEN_SWAP_V2',
-    ORCA_WHIRLPOOLS = 'ORCA_WHIRLPOOLS',
-    MARINADE = 'MARINADE',
-    STEPN = 'STEPN',
-    SENCHA_EXCHANGE = 'SENCHA_EXCHANGE',
-    SAROS_AMM = 'SAROS_AMM',
-    FOXY_STAKE = 'FOXY_STAKE',
-    FOXY_SWAP = 'FOXY_SWAP',
-    FOXY_RAFFLE = 'FOXY_RAFFLE',
-    FOXY_TOKEN_MARKET = 'FOXY_TOKEN_MARKET',
-    FOXY_MISSIONS = 'FOXY_MISSIONS',
-    FOXY_MARMALADE = 'FOXY_MARMALADE',
-    FOXY_COINFLIP = 'FOXY_COINFLIP',
-    FOXY_AUCTION = 'FOXY_AUCTION',
-    CITRUS = 'CITRUS',
-    HADE_SWAP = 'HADE_SWAP',
-    ZETA = 'ZETA',
-    CARDINAL_RENT = 'CARDINAL_RENT',
-    CARDINAL_STAKING = 'CARDINAL_STAKING',
-    SHARKY_FI = 'SHARKY_FI',
-    OPEN_CREATOR_PROTOCOL = 'OPEN_CREATOR_PROTOCOL',
+    JUPITER_V1 = "JUPITER_V1",
+    JUPITER_V2 = "JUPITER_V2",
+    JUPITER_V3 = "JUPITER_V3",
+    MERCURIAL_STABLE_SWAP = "MERCURIAL_STABLE_SWAP",
+    SABER_STABLE_SWAP = "SABER_STABLE_SWAP",
+    SABER_EXCHANGE = "SABER_EXCHANGE",
+    SERUM_DEX_V1 = "SERUM_DEX_V1",
+    SERUM_DEX_V2 = "SERUM_DEX_V2",
+    SERUM_DEX_V3 = "SERUM_DEX_V3",
+    SERUM_SWAP = "SERUM_SWAP",
+    STEP_FINANCE = "STEP_FINANCE",
+    CROPPER = "CROPPER",
+    RAYDIUM_LIQUIDITY_POOL_V2 = "RAYDIUM_LIQUIDITY_POOL_V2",
+    RAYDIUM_LIQUIDITY_POOL_V3 = "RAYDIUM_LIQUIDITY_POOL_V3",
+    RAYDIUM_LIQUIDITY_POOL_V4 = "RAYDIUM_LIQUIDITY_POOL_V4",
+    ALDRIN_AMM_V1 = "ALDRIN_AMM_V1",
+    ALDRIN_AMM_V2 = "ALDRIN_AMM_V2",
+    CREMA = "CREMA",
+    LIFINITY = "LIFINITY",
+    CYKURA = "CYKURA",
+    ORCA_TOKEN_SWAP_V1 = "ORCA_TOKEN_SWAP_V1",
+    ORCA_TOKEN_SWAP_V2 = "ORCA_TOKEN_SWAP_V2",
+    ORCA_WHIRLPOOLS = "ORCA_WHIRLPOOLS",
+    MARINADE = "MARINADE",
+    STEPN = "STEPN",
+    SENCHA_EXCHANGE = "SENCHA_EXCHANGE",
+    SAROS_AMM = "SAROS_AMM",
+    FOXY_STAKE = "FOXY_STAKE",
+    FOXY_SWAP = "FOXY_SWAP",
+    FOXY_RAFFLE = "FOXY_RAFFLE",
+    FOXY_TOKEN_MARKET = "FOXY_TOKEN_MARKET",
+    FOXY_MISSIONS = "FOXY_MISSIONS",
+    FOXY_MARMALADE = "FOXY_MARMALADE",
+    FOXY_COINFLIP = "FOXY_COINFLIP",
+    FOXY_AUCTION = "FOXY_AUCTION",
+    CITRUS = "CITRUS",
+    HADE_SWAP = "HADE_SWAP",
+    ZETA = "ZETA",
+    CARDINAL_RENT = "CARDINAL_RENT",
+    CARDINAL_STAKING = "CARDINAL_STAKING",
+    SHARKY_FI = "SHARKY_FI",
+    OPEN_CREATOR_PROTOCOL = "OPEN_CREATOR_PROTOCOL",
 }
 
 export enum Address {
-    NONE = '',
-    METAPLEX = 'p1exdMJcjVao65QdewkaZRUnU6VPSXhus9n2GzWfh98',
-    METAPLEX_AUCTION_HOUSE = 'hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk',
-    EXCHANGE_ART_AUCTION = 'exAuvFHqXXbiLrM4ce9m1icwuSyXytRnfBkajukDFuB',
-    EXCHANGE_ART_OFFER = 'exofLDXJoFji4Qyf9jSAH59J4pp82UT5pmGgR6iT24Z',
-    EXCHANGE_ART_INSTANT_SALE = 'AmK5g2XcyptVLCFESBCJqoSfwV3znGoVYQnqEnaAZKWn',
-    EXCHANGE_ART_MINT = 'EXBuYPNgBUXMTsjCbezENRUtFQzjUNZxvPGTd11Pznk5',
-    FORM_FUNCTION = 'formn3hJtt8gvVKxpCfzCJGuoz6CNUFcULFZW18iTpC',
-    SOLANART = 'CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz',
-    SOLANART_GLOBAL_OFFER = '5ZfZAwP2m93waazg8DkrrVmsupeiPEvaEHowiUP7UAbJ',
-    SOLSEA_MINT = '2669GNmpdcRF2FmpjZmPtnpKD7L9tkFd92XSPEN85i45',
-    SOLSEA_V1 = '617jbWo616ggkDxvW1Le8pV38XLbVSyWY8ae6QUmGBAU',
-    SOLSEA_V2 = 'AARTcKUzLYaWmK7D1otgyAoFn5vQqBiTrxjwrvjvsVJa',
-    CANDY_MACHINE_V3 = 'Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g',
-    CANDY_MACHINE_V2 = 'cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ',
-    CANDY_MACHINE_V1 = 'cndyAnrLdpjq1Ssp1z8xxDsB8dxe7u4HL5Nxi2K5WXZ',
-    METAPLEX_AUCTION = 'auctxRXPeJoc4817jDhf4HbjnhEcr1cCXenosMhK5R8',
-    TOKEN_METADATA = 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s',
-    TOKEN = 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA',
-    TOKEN_VAULT = 'vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn',
-    MAGIC_EDEN_V1 = 'MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8',
-    MAGIC_EDEN_V2 = 'M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K',
-    ENGLISH_AUCTION = 'EA15T2W45BJFm71XmB5VGcsiWGKZTNfnK6aCmE2Hb5eC',
-    PHANTOM = 'DeJBGdMFa1uynnnKiwrVioatTuHmNLpyFKnmB5kaFdzQ',
-    SYSTEM_PROGRAM = '11111111111111111111111111111111',
-    STAKE_PROGRAM = 'Stake11111111111111111111111111111111111111',
-    COINBASE_SHARED_WALLET = 'H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS',
-    MAGIC_EDEN_LAUNCHPAD = 'CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb',
-    HEDGE = 'HedgeEohwU6RqokrvPU4Hb6XKPub8NuKbnPmY7FoMMtN',
-    LAUNCH_MY_NFT = 'ArAA6CZC123yMJLUe4uisBEgvfuw2WEvex9iFmFCYiXv',
-    GEM_BANK = 'bankHHdqMuaaST4qQk6mkzxGeKPHWmqdgor6Gs8r88m',
-    GEM_FARM = 'farmL4xeBFVXJqtfxCzU9b28QACM7E2W2ctT6epAjvE',
-    DEGODS_GEM_BANK = '6VJpeYFy87Wuv4KvwqD5gyFBTkohqZTqs6LgbCJ8tDBA',
-    DEGODS_GEM_FARM = 'FQzYycoqRjmZTgCcTTAkzceH2Ju8nzNLa5d78K3yAhVW',
-    BSL_GEM_BANK = 'BRwUybBWZJEin7HVeWBC7AueG1McDeY6v4esBwgryzKe',
-    BSL_GEM_FARM = 'HUfVysibcL4u6EVoi4GsSDnV993tRX47ntoYH123q9AB',
-    YAWWW = '5SKmrbAxnHV2sgqyDXkGrLrokZYtWWVEEk5Soed7VLVN',
-    ATADIA_TOKEN_MINT_AUTHORITY = 'PassBQMFvYtDmvo7k5S2GVn6quj6RmnLnVfqEZebVMf',
-    DIGITAL_EYES = '7t8zVJtPCFAqog1DcnB6Ku1AVKtWfHkCiPi1cAvcJyVF',
-    HYPERSPACE = 'HYPERfwdTjyJ2SCaKHmpF2MtrXqWxrsotYDsTrshHWq8',
-    TENSOR = 'TSWAPaqyCSx2KABk68Shruf4rp7CxcNi8hAsbdwmHbN',
-    BIFROST_LAUNCHPAD = 'BFCMkgg9eFSv54HKJZFD5RMG8kNR5eMAEWnAtfRTPCjU',
-    FOXY_STAKE = 'FoXpJL1exLBJgHVvdSHNKyKu2xX2uatctH9qp6dLmfpP',
-    FOXY_SWAP = '8guzmt92HbM7yQ69UJg564hRRX6N4nCdxWE5L6ENrA8P',
-    FOXY_RAFFLE = '9ehXDD5bnhSpFVRf99veikjgq8VajtRH7e3D9aVPLqYd',
-    FOXY_TOKEN_MARKET = '8BYmYs3zsBhftNELJdiKsCN2WyCBbrTwXd6WG4AFPr6n',
-    FOXY_MISSIONS = '6NcdQ5WTnrPoMLbP4kvpLYa4YSwKqkNHRRE8XVf5hmv9',
-    FOXY_MARMALADE = 'BbGozDEfDKJbqxkSDjcDLWdQfxeZnnoTgD5VhNXV7epn',
-    FOXY_COINFLIP = '72D3En8GQycjtunxf9mgyR8onzYdPqYFsKp4myUzhaRZ',
-    FOXY_AUCTION = 'FFAUags5SYJEioBUkPtKuArccNzcNgUubhssCH2jSbeH',
-    CITRUS = 'JCFRaPv7852ESRwJJGRy2mysUMydXZgVVhrMLmExvmVp',
-    HADE_SWAP = 'hadeK9DLv9eA7ya5KCTqSvSvRZeJC3JgD5a9Y3CNbvu',
-    ELIXIR = '2qGyiNeWyZxNdkvWHc2jT5qkCnYa1j1gDLSSUmyoWMh8',
-    ELIXIR_LAUNCHPAD = '1NCHWmQ39XfQuRLgGihckNKXcm9LXbq5EnPVwPptLWy',
-    ELIXIR_LAUNCHPAD_V2 = 'PADWBS1VeV1LWsY6nciu6dRZjgSmUH2iPsUpHFVz7Wz',
-    ELIXIR_V2 = 'E1XRkj9fPF2NQUdoq41AHPqwMDHykYfn5PzBXAyDs7Be',
-    CARDINAL_RENT = 'mgr99QFMYByTqGPWmNqunV7vBLmWWXdSrHUfV8Jf3JM',
-    CARDINAL_STAKING = 'stkBL96RZkjY5ine4TvPihGqW8UHJfch2cokjAPzV8i',
-    MAGIC_EDEN_GLOBAL_BID = 'mmm3XBJg5gk8XJxEKBvdgptZz6SgK4tXvn36sodowMc',
-    BPF_UPGRADEABLE_LOADER = 'BPFLoaderUpgradeab1e11111111111111111111111',
-    BPF_LOADER = 'BPFLoader2111111111111111111111111111111111',
-    SQUADS = 'SMPLecH534NA9acpos4G6x7uf3LWbCAwZQE9e8ZekMu',
-    SHARKY_FI = 'SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP',
-    OPEN_CREATOR_PROTOCOL = 'ocp4vWUzA2z2XMYJ3QhM9vWdyoyoQwAFJhRdVTbvo9E',
+    NONE = "",
+    METAPLEX = "p1exdMJcjVao65QdewkaZRUnU6VPSXhus9n2GzWfh98",
+    METAPLEX_AUCTION_HOUSE = "hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk",
+    EXCHANGE_ART_AUCTION = "exAuvFHqXXbiLrM4ce9m1icwuSyXytRnfBkajukDFuB",
+    EXCHANGE_ART_OFFER = "exofLDXJoFji4Qyf9jSAH59J4pp82UT5pmGgR6iT24Z",
+    EXCHANGE_ART_INSTANT_SALE = "AmK5g2XcyptVLCFESBCJqoSfwV3znGoVYQnqEnaAZKWn",
+    EXCHANGE_ART_MINT = "EXBuYPNgBUXMTsjCbezENRUtFQzjUNZxvPGTd11Pznk5",
+    FORM_FUNCTION = "formn3hJtt8gvVKxpCfzCJGuoz6CNUFcULFZW18iTpC",
+    SOLANART = "CJsLwbP1iu5DuUikHEJnLfANgKy6stB2uFgvBBHoyxwz",
+    SOLANART_GLOBAL_OFFER = "5ZfZAwP2m93waazg8DkrrVmsupeiPEvaEHowiUP7UAbJ",
+    SOLSEA_MINT = "2669GNmpdcRF2FmpjZmPtnpKD7L9tkFd92XSPEN85i45",
+    SOLSEA_V1 = "617jbWo616ggkDxvW1Le8pV38XLbVSyWY8ae6QUmGBAU",
+    SOLSEA_V2 = "AARTcKUzLYaWmK7D1otgyAoFn5vQqBiTrxjwrvjvsVJa",
+    CANDY_MACHINE_V3 = "Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g",
+    CANDY_MACHINE_V2 = "cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ",
+    CANDY_MACHINE_V1 = "cndyAnrLdpjq1Ssp1z8xxDsB8dxe7u4HL5Nxi2K5WXZ",
+    METAPLEX_AUCTION = "auctxRXPeJoc4817jDhf4HbjnhEcr1cCXenosMhK5R8",
+    TOKEN_METADATA = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s",
+    TOKEN = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
+    TOKEN_VAULT = "vau1zxA2LbssAUEF7Gpw91zMM1LvXrvpzJtmZ58rPsn",
+    MAGIC_EDEN_V1 = "MEisE1HzehtrDpAAT8PnLHjpSSkRYakotTuJRPjTpo8",
+    MAGIC_EDEN_V2 = "M2mx93ekt1fmXSVkTrUL9xVFHkmME8HTUi5Cyc5aF7K",
+    ENGLISH_AUCTION = "EA15T2W45BJFm71XmB5VGcsiWGKZTNfnK6aCmE2Hb5eC",
+    PHANTOM = "DeJBGdMFa1uynnnKiwrVioatTuHmNLpyFKnmB5kaFdzQ",
+    SYSTEM_PROGRAM = "11111111111111111111111111111111",
+    STAKE_PROGRAM = "Stake11111111111111111111111111111111111111",
+    COINBASE_SHARED_WALLET = "H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS",
+    MAGIC_EDEN_LAUNCHPAD = "CMZYPASGWeTz7RNGHaRJfCq2XQ5pYK6nDvVQxzkH51zb",
+    HEDGE = "HedgeEohwU6RqokrvPU4Hb6XKPub8NuKbnPmY7FoMMtN",
+    LAUNCH_MY_NFT = "ArAA6CZC123yMJLUe4uisBEgvfuw2WEvex9iFmFCYiXv",
+    GEM_BANK = "bankHHdqMuaaST4qQk6mkzxGeKPHWmqdgor6Gs8r88m",
+    GEM_FARM = "farmL4xeBFVXJqtfxCzU9b28QACM7E2W2ctT6epAjvE",
+    DEGODS_GEM_BANK = "6VJpeYFy87Wuv4KvwqD5gyFBTkohqZTqs6LgbCJ8tDBA",
+    DEGODS_GEM_FARM = "FQzYycoqRjmZTgCcTTAkzceH2Ju8nzNLa5d78K3yAhVW",
+    BSL_GEM_BANK = "BRwUybBWZJEin7HVeWBC7AueG1McDeY6v4esBwgryzKe",
+    BSL_GEM_FARM = "HUfVysibcL4u6EVoi4GsSDnV993tRX47ntoYH123q9AB",
+    YAWWW = "5SKmrbAxnHV2sgqyDXkGrLrokZYtWWVEEk5Soed7VLVN",
+    ATADIA_TOKEN_MINT_AUTHORITY = "PassBQMFvYtDmvo7k5S2GVn6quj6RmnLnVfqEZebVMf",
+    DIGITAL_EYES = "7t8zVJtPCFAqog1DcnB6Ku1AVKtWfHkCiPi1cAvcJyVF",
+    HYPERSPACE = "HYPERfwdTjyJ2SCaKHmpF2MtrXqWxrsotYDsTrshHWq8",
+    TENSOR = "TSWAPaqyCSx2KABk68Shruf4rp7CxcNi8hAsbdwmHbN",
+    BIFROST_LAUNCHPAD = "BFCMkgg9eFSv54HKJZFD5RMG8kNR5eMAEWnAtfRTPCjU",
+    FOXY_STAKE = "FoXpJL1exLBJgHVvdSHNKyKu2xX2uatctH9qp6dLmfpP",
+    FOXY_SWAP = "8guzmt92HbM7yQ69UJg564hRRX6N4nCdxWE5L6ENrA8P",
+    FOXY_RAFFLE = "9ehXDD5bnhSpFVRf99veikjgq8VajtRH7e3D9aVPLqYd",
+    FOXY_TOKEN_MARKET = "8BYmYs3zsBhftNELJdiKsCN2WyCBbrTwXd6WG4AFPr6n",
+    FOXY_MISSIONS = "6NcdQ5WTnrPoMLbP4kvpLYa4YSwKqkNHRRE8XVf5hmv9",
+    FOXY_MARMALADE = "BbGozDEfDKJbqxkSDjcDLWdQfxeZnnoTgD5VhNXV7epn",
+    FOXY_COINFLIP = "72D3En8GQycjtunxf9mgyR8onzYdPqYFsKp4myUzhaRZ",
+    FOXY_AUCTION = "FFAUags5SYJEioBUkPtKuArccNzcNgUubhssCH2jSbeH",
+    CITRUS = "JCFRaPv7852ESRwJJGRy2mysUMydXZgVVhrMLmExvmVp",
+    HADE_SWAP = "hadeK9DLv9eA7ya5KCTqSvSvRZeJC3JgD5a9Y3CNbvu",
+    ELIXIR = "2qGyiNeWyZxNdkvWHc2jT5qkCnYa1j1gDLSSUmyoWMh8",
+    ELIXIR_LAUNCHPAD = "1NCHWmQ39XfQuRLgGihckNKXcm9LXbq5EnPVwPptLWy",
+    ELIXIR_LAUNCHPAD_V2 = "PADWBS1VeV1LWsY6nciu6dRZjgSmUH2iPsUpHFVz7Wz",
+    ELIXIR_V2 = "E1XRkj9fPF2NQUdoq41AHPqwMDHykYfn5PzBXAyDs7Be",
+    CARDINAL_RENT = "mgr99QFMYByTqGPWmNqunV7vBLmWWXdSrHUfV8Jf3JM",
+    CARDINAL_STAKING = "stkBL96RZkjY5ine4TvPihGqW8UHJfch2cokjAPzV8i",
+    MAGIC_EDEN_GLOBAL_BID = "mmm3XBJg5gk8XJxEKBvdgptZz6SgK4tXvn36sodowMc",
+    BPF_UPGRADEABLE_LOADER = "BPFLoaderUpgradeab1e11111111111111111111111",
+    BPF_LOADER = "BPFLoader2111111111111111111111111111111111",
+    SQUADS = "SMPLecH534NA9acpos4G6x7uf3LWbCAwZQE9e8ZekMu",
+    SHARKY_FI = "SHARKobtfF1bHhxD2eqftjHBdVSCbKo9JtgK71FhELP",
+    OPEN_CREATOR_PROTOCOL = "ocp4vWUzA2z2XMYJ3QhM9vWdyoyoQwAFJhRdVTbvo9E",
 
     // Defi programs - most pulled from here - https://dune.com/queries/665628/1240465
-    JUPITER_V1 = 'JUP6i4ozu5ydDCnLiMogSckDPpbtr7BJ4FtzYWkb5Rk',
-    JUPITER_V2 = 'JUP2jxvXaqu7NQY1GmNF4m1vodw12LVXYxbFL2uJvfo',
-    JUPITER_V3 = 'JUP3c2Uh3WA4Ng34tw6kPd2G4C5BB21Xo36Je1s32Ph',
-    SERUM_DEX_V3 = '9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin',
-    SERUM_DEX_V2 = 'EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o',
-    SERUM_DEX_V1 = 'BJ3jrUzddfuSrZHXSCxMUUQsjKEyLmuuyZebkcaFp2fg',
-    SERUM_DEX_ALT_V1 = '4ckmDgGdxQoPDLUkDT3vHgSAkzA3QRdNq5ywwY4sUSJn',
-    SERUM_SWAP = '22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD',
-    ALDRIN_AMM_V1 = 'AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6',
-    ALDRIN_AMM_V2 = 'CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4',
-    RAYDIUM_LIQUIDITY_POOL_V2 = 'RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr',
-    RAYDIUM_LIQUIDITY_POOL_V3 = '27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv',
-    RAYDIUM_LIQUIDITY_POOL_V4 = '675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8',
-    SABER_STABLE_SWAP = 'SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ',
-    SABER_EXCHANGE = 'YAkoNb6HKmSxQN9L8hiBE5tPJRsniSSMzND1boHmZxe',
-    MERCURIAL_STABLE_SWAP = 'MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky',
-    ORCA_TOKEN_SWAP_V1 = 'DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1',
-    ORCA_TOKEN_SWAP_V2 = '9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP',
-    ORCA_WHIRLPOOLS = 'whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc',
-    STEP_FINANCE_SWAP_PROGRAM = 'SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1',
-    CYKURA = 'cysPXAjehMpVKUapzbMCCnpFxUFFryEWEaLgnb9NrR8',
-    CREMA_FINANCE = '6MLxLqiXaaSUpkgMnWDTuejNZEz3kE7k2woyHGVFw319',
-    LIFINITY = 'EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S',
-    STEPN = 'Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j',
-    SENCHA_EXCHANGE = 'SCHAtsf8mbjyjiv4LkhLKutTf6JnZAbdJKFkXQNMFHZ',
-    CROPPER = 'CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh',
-    SAROS_AMM = 'SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr',
-    ZETA = 'ZETAx4NhMsyop6gVwH2E2RrAcDiuPs9ABkhLBEvBsb6',
+    JUPITER_V1 = "JUP6i4ozu5ydDCnLiMogSckDPpbtr7BJ4FtzYWkb5Rk",
+    JUPITER_V2 = "JUP2jxvXaqu7NQY1GmNF4m1vodw12LVXYxbFL2uJvfo",
+    JUPITER_V3 = "JUP3c2Uh3WA4Ng34tw6kPd2G4C5BB21Xo36Je1s32Ph",
+    SERUM_DEX_V3 = "9xQeWvG816bUx9EPjHmaT23yvVM2ZWbrrpZb9PusVFin",
+    SERUM_DEX_V2 = "EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o",
+    SERUM_DEX_V1 = "BJ3jrUzddfuSrZHXSCxMUUQsjKEyLmuuyZebkcaFp2fg",
+    SERUM_DEX_ALT_V1 = "4ckmDgGdxQoPDLUkDT3vHgSAkzA3QRdNq5ywwY4sUSJn",
+    SERUM_SWAP = "22Y43yTVxuUkoRKdm9thyRhQ3SdgQS7c7kB6UNCiaczD",
+    ALDRIN_AMM_V1 = "AMM55ShdkoGRB5jVYPjWziwk8m5MpwyDgsMWHaMSQWH6",
+    ALDRIN_AMM_V2 = "CURVGoZn8zycx6FXwwevgBTB2gVvdbGTEpvMJDbgs2t4",
+    RAYDIUM_LIQUIDITY_POOL_V2 = "RVKd61ztZW9GUwhRbbLoYVRE5Xf1B2tVscKqwZqXgEr",
+    RAYDIUM_LIQUIDITY_POOL_V3 = "27haf8L6oxUeXrHrgEgsexjSY5hbVUWEmvv9Nyxg8vQv",
+    RAYDIUM_LIQUIDITY_POOL_V4 = "675kPX9MHTjS2zt1qfr1NYHuzeLXfQM9H24wFSUt1Mp8",
+    SABER_STABLE_SWAP = "SSwpkEEcbUqx4vtoEByFjSkhKdCT862DNVb52nZg1UZ",
+    SABER_EXCHANGE = "YAkoNb6HKmSxQN9L8hiBE5tPJRsniSSMzND1boHmZxe",
+    MERCURIAL_STABLE_SWAP = "MERLuDFBMmsHnsBPZw2sDQZHvXFMwp8EdjudcU2HKky",
+    ORCA_TOKEN_SWAP_V1 = "DjVE6JNiYqPL2QXyCUUh8rNjHrbz9hXHNYt99MQ59qw1",
+    ORCA_TOKEN_SWAP_V2 = "9W959DqEETiGZocYWCQPaJ6sBmUzgfxXfqGeTEdp3aQP",
+    ORCA_WHIRLPOOLS = "whirLbMiicVdio4qvUfM5KAg6Ct8VwpYzGff3uctyCc",
+    STEP_FINANCE_SWAP_PROGRAM = "SSwpMgqNDsyV7mAgN9ady4bDVu5ySjmmXejXvy2vLt1",
+    CYKURA = "cysPXAjehMpVKUapzbMCCnpFxUFFryEWEaLgnb9NrR8",
+    CREMA_FINANCE = "6MLxLqiXaaSUpkgMnWDTuejNZEz3kE7k2woyHGVFw319",
+    LIFINITY = "EewxydAPCCVuNEyrVN68PuSYdQ7wKn27V9Gjeoi8dy3S",
+    STEPN = "Dooar9JkhdZ7J3LHN3A7YCuoGRUggXhQaG4kijfLGU2j",
+    SENCHA_EXCHANGE = "SCHAtsf8mbjyjiv4LkhLKutTf6JnZAbdJKFkXQNMFHZ",
+    CROPPER = "CTMAxxk34HjKWxQ3QLZK1HpaLXmBveao3ESePXbiyfzh",
+    SAROS_AMM = "SSwapUtytfBdBn1b9NUGG6foMVPtcWgpRU32HToDUZr",
+    ZETA = "ZETAx4NhMsyop6gVwH2E2RrAcDiuPs9ABkhLBEvBsb6",
 
     // Mints
-    W_SOL_TOKEN = 'So11111111111111111111111111111111111111112',
-    DUST_TOKEN = 'DUSTawucrTsGU8hcqRdHDCbuYhCPADMLM2VcCb8VnFnQ',
-    SOLI_TOKEN = '8JnNWJ46yfdq8sKgT1Lk4G7VWkAA8Rhh7LhqgJ6WY41G',
-    USDC_TOKEN = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
-    FLWR_TOKEN = 'FLWRna1gxehQ9pSyZMzxfp4UhewvLPwuKfdUTgdZuMBY',
-    HDG_TOKEN = '5PmpMzWjraf3kSsGEKtqdUsCoLhptg4yriZ17LKKdBBy',
-    MEAN_TOKEN = 'MEANeD3XDdUmNMsRGjASkSWdC8prLYsoRJ61pPeHctD',
-    UXD_TOKEN = '7kbnvuGBxxj8AG9qp8Scn56muWGaRaFqxg1FsRp3PaFT',
-    SHDW_TOKEN = 'SHDWyBxihqiCj6YekG2GUr7wqKLeLAMK1gHZck9pL6y',
-    POLIS_TOKEN = 'poLisWXnNRwC6oBu1vHiuKQzFjGL4XDSu4g9qjz9qVk',
-    ATLAS_TOKEN = 'ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx',
-    USH_TOKEN = '9iLH8T7zoWhY7sBmj1WK9ENbWdS1nL8n9wAxaeRitTa6',
-    TRTLS_TOKEN = 'q4bpaRKw3fJB1AJBeeBaKv3TjYzWsmntLgnSB275YUb',
-    FOXY_TOKEN = 'FoXyMu5xwXre7zEoSvzViRk3nGawHUp9kUh97y2NDhcq',
-    RUNNER_TOKEN = '6Rqtt2h8dS6pHPGzqrmGtyhjCk3zpk795QcEwXJLfeLn',
-    INVICTUS_TOKEN = 'inL8PMVd6iiW3RCBJnr5AsrRN6nqr4BTrcNuQWQSkvY',
+    W_SOL_TOKEN = "So11111111111111111111111111111111111111112",
+    DUST_TOKEN = "DUSTawucrTsGU8hcqRdHDCbuYhCPADMLM2VcCb8VnFnQ",
+    SOLI_TOKEN = "8JnNWJ46yfdq8sKgT1Lk4G7VWkAA8Rhh7LhqgJ6WY41G",
+    USDC_TOKEN = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
+    FLWR_TOKEN = "FLWRna1gxehQ9pSyZMzxfp4UhewvLPwuKfdUTgdZuMBY",
+    HDG_TOKEN = "5PmpMzWjraf3kSsGEKtqdUsCoLhptg4yriZ17LKKdBBy",
+    MEAN_TOKEN = "MEANeD3XDdUmNMsRGjASkSWdC8prLYsoRJ61pPeHctD",
+    UXD_TOKEN = "7kbnvuGBxxj8AG9qp8Scn56muWGaRaFqxg1FsRp3PaFT",
+    SHDW_TOKEN = "SHDWyBxihqiCj6YekG2GUr7wqKLeLAMK1gHZck9pL6y",
+    POLIS_TOKEN = "poLisWXnNRwC6oBu1vHiuKQzFjGL4XDSu4g9qjz9qVk",
+    ATLAS_TOKEN = "ATLASXmbPQxBUYbxPsV97usA3fPQYEqzQBUHgiFCUsXx",
+    USH_TOKEN = "9iLH8T7zoWhY7sBmj1WK9ENbWdS1nL8n9wAxaeRitTa6",
+    TRTLS_TOKEN = "q4bpaRKw3fJB1AJBeeBaKv3TjYzWsmntLgnSB275YUb",
+    FOXY_TOKEN = "FoXyMu5xwXre7zEoSvzViRk3nGawHUp9kUh97y2NDhcq",
+    RUNNER_TOKEN = "6Rqtt2h8dS6pHPGzqrmGtyhjCk3zpk795QcEwXJLfeLn",
+    INVICTUS_TOKEN = "inL8PMVd6iiW3RCBJnr5AsrRN6nqr4BTrcNuQWQSkvY",
 }
 
 export enum TokenStandard {
     PROGRAMMABLE_NON_FUNGIBLE = "ProgrammableNonFungible",
-    NON_FUNGIBLE = 'NonFungible',
-    FUNGIBLE = 'Fungible',
-    FUNGIBLE_ASSET = 'FungibleAsset',
-    NON_FUNGIBLE_EDITION = 'NonFungibleEdition',
-    UNKNOWN_STANDARD = 'UnknownStandard',
+    NON_FUNGIBLE = "NonFungible",
+    FUNGIBLE = "Fungible",
+    FUNGIBLE_ASSET = "FungibleAsset",
+    NON_FUNGIBLE_EDITION = "NonFungibleEdition",
+    UNKNOWN_STANDARD = "UnknownStandard",
 }
diff --git a/packages/helius-sdk/src/types/index.ts b/packages/helius-sdk/src/types/index.ts
index e15f9f27..13e1105d 100644
--- a/packages/helius-sdk/src/types/index.ts
+++ b/packages/helius-sdk/src/types/index.ts
@@ -1,2 +1,2 @@
 export * from "./enums";
-export * from "./types";
\ No newline at end of file
+export * from "./types";
diff --git a/packages/helius-sdk/src/types/types.ts b/packages/helius-sdk/src/types/types.ts
index 6daef853..82eb1562 100644
--- a/packages/helius-sdk/src/types/types.ts
+++ b/packages/helius-sdk/src/types/types.ts
@@ -141,7 +141,7 @@ export interface NFTEvent {
     buyer: string;
     timestamp: number;
     amount: number;
-    fee:number;
+    fee: number;
     signature: string;
     source: Source;
     type: TransactionType;
diff --git a/packages/helius-sdk/src/utils/cluster.ts b/packages/helius-sdk/src/utils/cluster.ts
index ef187d4c..cb9aef40 100644
--- a/packages/helius-sdk/src/utils/cluster.ts
+++ b/packages/helius-sdk/src/utils/cluster.ts
@@ -1,8 +1,6 @@
 import { Cluster } from "@solana/web3.js";
 
-/**
- * Retrieves the Helius RPC API URL for the specified cluster
- */
+/** Retrieves the Helius RPC API URL for the specified cluster */
 export function heliusClusterApiUrl(
     apiKey: string,
     cluster: Cluster = "devnet"
@@ -11,7 +9,7 @@ export function heliusClusterApiUrl(
         case "devnet":
             return `https://rpc-devnet.helius.xyz/?api-key=${apiKey}`;
         case "mainnet-beta":
-            return `https://mainnet-beta.solanarpc.network/?api-key=${apiKey}`;
+            return `https://rpc.helius.xyz/?api-key=${apiKey}`;
         default:
             return "";
     }
diff --git a/packages/xray/src/lib/parser/parsers/nft.ts b/packages/xray/src/lib/parser/parsers/nft.ts
index a7841854..6e9483c2 100644
--- a/packages/xray/src/lib/parser/parsers/nft.ts
+++ b/packages/xray/src/lib/parser/parsers/nft.ts
@@ -400,29 +400,30 @@ export const parseCompressedNftMint: ProtonParser = (transaction, address) => {
     traverseAccountData(accountData, accounts);
 
     for (let i = 0; i < nftEvent.length; i++) {
+        const nftEventAction = nftEvent[i];
         if (!address) {
             actions.push({
                 actionType: "TRANSFER",
                 amount: 1,
                 from: "",
-                sent: nftEvent[i].assetId,
-                to: nftEvent[i].newLeafOwner,
+                sent: nftEventAction.assetId,
+                to: nftEventAction.newLeafOwner,
             });
-        } else if (address === nftEvent[i].newLeafOwner) {
+        } else if (address === nftEventAction.newLeafOwner) {
             actions.push({
                 actionType: "AIRDROP",
                 amount: 1,
                 from: "",
-                received: nftEvent[i].assetId,
-                to: nftEvent[i].newLeafOwner,
+                received: nftEventAction.assetId,
+                to: nftEventAction.newLeafOwner,
             });
         } else {
             actions.push({
                 actionType: "RECEIVED",
                 amount: 1,
                 from: "",
-                received: nftEvent[i].assetId,
-                to: nftEvent[i].newLeafOwner,
+                received: nftEventAction.assetId,
+                to: nftEventAction.newLeafOwner,
             });
         }
     }
@@ -459,31 +460,34 @@ export const parseCompressedNftTransfer: ProtonParser = (
 
     traverseAccountData(accountData, accounts);
 
-    if (!address) {
-        actions.push({
-            actionType: "TRANSFER",
-            amount: 1,
-            from: nftEvent[0].oldLeafOwner,
-            sent: nftEvent[0].assetId,
-            to: nftEvent[0].newLeafOwner,
-        });
-    } else {
-        if ((address = nftEvent[0].oldLeafOwner)) {
-            actions.push({
-                actionType: "TRANSFER_SENT",
-                amount: 1,
-                from: nftEvent[0].oldLeafOwner,
-                sent: nftEvent[0].assetId,
-                to: nftEvent[0].newLeafOwner,
-            });
-        } else if (address === nftEvent[0].newLeafOwner) {
+    for (let i = 0; i < nftEvent.length; i++) {
+        const nftEventAction = nftEvent[i];
+        if (!address) {
             actions.push({
-                actionType: "TRANSFER_RECEIVED",
+                actionType: "TRANSFER",
                 amount: 1,
-                from: nftEvent[0].oldLeafOwner,
-                received: nftEvent[0].assetId,
-                to: nftEvent[0].newLeafOwner,
+                from: nftEventAction.oldLeafOwner,
+                sent: nftEventAction.assetId,
+                to: nftEventAction.newLeafOwner,
             });
+        } else {
+            if (address === nftEventAction.oldLeafOwner) {
+                actions.push({
+                    actionType: "TRANSFER_SENT",
+                    amount: 1,
+                    from: nftEventAction.oldLeafOwner,
+                    sent: nftEventAction.assetId,
+                    to: nftEventAction.newLeafOwner,
+                });
+            } else if (address === nftEventAction.newLeafOwner) {
+                actions.push({
+                    actionType: "TRANSFER_RECEIVED",
+                    amount: 1,
+                    from: nftEventAction.oldLeafOwner,
+                    received: nftEventAction.assetId,
+                    to: nftEventAction.newLeafOwner,
+                });
+            }
         }
     }
 
@@ -498,3 +502,43 @@ export const parseCompressedNftTransfer: ProtonParser = (
         type,
     };
 };
+
+export const parseCompressedNftBurn: ProtonParser = (transaction, address) => {
+    // @ts-ignore
+    const nftEvent = transaction.events.compressed;
+    const { signature, timestamp, accountData, type, source } = transaction;
+
+    const fee = transaction.fee / LAMPORTS_PER_SOL;
+    const primaryUser = transaction.feePayer;
+
+    if (!nftEvent) {
+        return generateDefaultTransaction(transaction.type);
+    }
+
+    const actions: ProtonTransactionAction[] = [];
+    const accounts: ProtonAccount[] = [];
+
+    traverseAccountData(accountData, accounts);
+
+    for (let i = 0; i < nftEvent.length; i++) {
+        const nftEventAction = nftEvent[i];
+        actions.push({
+            actionType: "BURN_NFT",
+            amount: 1,
+            from: nftEventAction.oldLeafOwner,
+            sent: nftEventAction.assetId,
+            to: "",
+        });
+    }
+
+    return {
+        accounts,
+        actions,
+        fee,
+        primaryUser,
+        signature,
+        source,
+        timestamp,
+        type,
+    };
+};
diff --git a/packages/xray/src/lib/parser/types.ts b/packages/xray/src/lib/parser/types.ts
index 81cb84cb..d31a7a7b 100644
--- a/packages/xray/src/lib/parser/types.ts
+++ b/packages/xray/src/lib/parser/types.ts
@@ -29,6 +29,8 @@ export enum ProtonSupportedType {
     RESCIND_LOAN,
     TAKE_LOAN,
     REPAY_LOAN,
+    ADD_ITEM,
+    UPDATE_ITEM,
     CANCEL_OFFER,
     LEND_FOR_NFT,
     REQUEST_LOAN,
@@ -40,6 +42,18 @@ export enum ProtonSupportedType {
     FORECLOSE_LOAN,
     STAKE_TOKEN,
     UNSTAKE_TOKEN,
+    BUY_ITEM,
+    CLOSE_ITEM,
+    CLOSE_ORDER,
+    DELIST_ITEM,
+    LIST_ITEM,
+    CANCEL_ORDER,
+    CREATE_ORDER,
+    UPDATE_ORDER,
+    FILL_ORDER,
+    UPGRADE_FOX_REQUEST,
+    MIGRATE_TO_PNFT,
+    COMPRESSED_NFT_BURN,
 }
 
 export enum ProtonSupportedActionType {
@@ -80,6 +94,8 @@ export enum ProtonSupportedActionType {
     "RESCIND_LOAN",
     "TAKE_LOAN",
     "REPAY_LOAN",
+    "ADD_ITEM",
+    "UPDATE_ITEM",
     "CANCEL_OFFER",
     "LEND_FOR_NFT",
     "REQUEST_LOAN",
@@ -91,12 +107,25 @@ export enum ProtonSupportedActionType {
     "FORECLOSE_LOAN",
     "STAKE_TOKEN",
     "UNSTAKE_TOKEN",
+    "BUY_ITEM",
+    "CLOSE_ITEM",
+    "CLOSE_ORDER",
+    "DELIST_ITEM",
+    "LIST_ITEM",
+    "CANCEL_ORDER",
+    "CREATE_ORDER",
+    "UPDATE_ORDER",
+    "FILL_ORDER",
+    "UPGRADE_FOX_REQUEST",
+    "MIGRATE_TO_PNFT",
+    "COMPRESSED_NFT_BURN",
 }
 
 export const ProtonCustomActionLabelTypes = {
     AIRDROP: "Airdropped",
     BURN: "Burned",
     BURN_NFT: "Burned NFT",
+    COMPRESSED_NFT_BURN: "Burned NFT",
     FREEZE: "Frozen",
     XNFT_INSTALL: "xNFT Install",
     XNFT_UNINSTALL: "xNFT Uninstall",
@@ -155,6 +184,7 @@ export const protonParsers = {
     BORROW_FOX: parser.parseBorrowFox,
     BURN: parser.parseBurn,
     BURN_NFT: parser.parseBurn,
+    COMPRESSED_NFT_BURN: parser.parseCompressedNftBurn,
     COMPRESSED_NFT_MINT: parser.parseCompressedNftMint,
     COMPRESSED_NFT_TRANSFER: parser.parseCompressedNftTransfer,
     EXECUTE_TRANSACTION: parser.parseTransfer,
diff --git a/packages/xray/src/lib/search.ts b/packages/xray/src/lib/search.ts
index 61e22104..a94c92e8 100644
--- a/packages/xray/src/lib/search.ts
+++ b/packages/xray/src/lib/search.ts
@@ -50,9 +50,16 @@ export const search = async (
         const account = await connection.getParsedAccountInfo(pubkey);
 
         // TODO Property 'program' does not exist on type 'Buffer | ParsedAccountData'.
+        /*
+         * spl-token      -> spl token
+         * spl-token-2022 -> token 2022
+         * null           -> compressed nft
+         */
         const isToken =
             // @ts-ignore
             account?.value?.data?.program === "spl-token" ||
+            // @ts-ignore
+            account?.value?.data?.program === "spl-token-2022" ||
             account?.value === null;
 
         const addressType = isToken ? "token" : "account";