From e5ac1d60700285b2df45d2cfb676d8be16b2a154 Mon Sep 17 00:00:00 2001 From: 0xIchigo <0xIchigo@protonmail.com> Date: Sun, 31 Dec 2023 02:58:37 -0500 Subject: [PATCH 1/8] Try Implementing IDL Fetch --- package-lock.json | 150 +++++++++++++++++- package.json | 1 + src/lib/util/stores/idl.ts | 4 + src/lib/util/stores/idlStore.ts | 64 ++++++++ src/routes/account/[account]/+layout.svelte | 33 +++- src/routes/account/[account]/idl/+page.svelte | 27 ++++ 6 files changed, 274 insertions(+), 5 deletions(-) create mode 100644 src/lib/util/stores/idl.ts create mode 100644 src/lib/util/stores/idlStore.ts create mode 100644 src/routes/account/[account]/idl/+page.svelte diff --git a/package-lock.json b/package-lock.json index 93f9a1f5..ddb200a2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "xray", "version": "1.0.0", "dependencies": { + "@coral-xyz/anchor": "^0.29.0", "@lottiefiles/svelte-lottie-player": "^0.3.0", "@onsol/tldparser": "^0.5.3", "@solana/spl-account-compression": "^0.1.8", @@ -728,6 +729,85 @@ "@chainsafe/persistent-merkle-tree": "^0.6.1" } }, + "node_modules/@coral-xyz/anchor": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@coral-xyz/anchor/-/anchor-0.29.0.tgz", + "integrity": "sha512-eny6QNG0WOwqV0zQ7cs/b1tIuzZGmP7U7EcH+ogt4Gdbl8HDmIYVMh/9aTmYZPaFWjtUaI8qSn73uYEXWfATdA==", + "dependencies": { + "@coral-xyz/borsh": "^0.29.0", + "@noble/hashes": "^1.3.1", + "@solana/web3.js": "^1.68.0", + "bn.js": "^5.1.2", + "bs58": "^4.0.1", + "buffer-layout": "^1.2.2", + "camelcase": "^6.3.0", + "cross-fetch": "^3.1.5", + "crypto-hash": "^1.3.0", + "eventemitter3": "^4.0.7", + "pako": "^2.0.3", + "snake-case": "^3.0.4", + "superstruct": "^0.15.4", + "toml": "^3.0.0" + }, + "engines": { + "node": ">=11" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/base-x": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", + "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/bs58": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", + "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/@coral-xyz/anchor/node_modules/superstruct": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/superstruct/-/superstruct-0.15.5.tgz", + "integrity": "sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ==" + }, + "node_modules/@coral-xyz/borsh": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@coral-xyz/borsh/-/borsh-0.29.0.tgz", + "integrity": "sha512-s7VFVa3a0oqpkuRloWVPdCK7hMbAMY270geZOGfCnaqexrP5dTIpbEHL33req6IYPPJ0hYa71cdvJ1h6V55/oQ==", + "dependencies": { + "bn.js": "^5.1.2", + "buffer-layout": "^1.2.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@solana/web3.js": "^1.68.0" + } + }, "node_modules/@esbuild-plugins/node-globals-polyfill": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@esbuild-plugins/node-globals-polyfill/-/node-globals-polyfill-0.2.3.tgz", @@ -5728,6 +5808,14 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, + "node_modules/buffer-layout": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/buffer-layout/-/buffer-layout-1.2.2.tgz", + "integrity": "sha512-kWSuLN694+KTk8SrYvCqwP2WcgQjoRCiF5b4QDvkkz8EmgD+aWAIceGFKMIAdmF/pH+vpgNV3d3kAKorcdAmWA==", + "engines": { + "node": ">=4.5" + } + }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", @@ -6410,6 +6498,17 @@ "node": "*" } }, + "node_modules/crypto-hash": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/crypto-hash/-/crypto-hash-1.3.0.tgz", + "integrity": "sha512-lyAZ0EMyjDkVvz8WOeVnuCPvKVBXcMv1l5SVqO1yC7PzTwrD/pPje/BIRbWhMoPe436U+Y2nD7f5bFx0kt+Sbg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/crypto-js": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", @@ -6792,6 +6891,15 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", @@ -10133,6 +10241,14 @@ "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.12.2.tgz", "integrity": "sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg==" }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -10912,6 +11028,15 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/no-cliches": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/no-cliches/-/no-cliches-0.3.4.tgz", @@ -10934,9 +11059,9 @@ "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -11292,6 +11417,11 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -12824,6 +12954,15 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/socket.io-client": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz", @@ -13655,6 +13794,11 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==" + }, "node_modules/too-wordy": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/too-wordy/-/too-wordy-0.3.4.tgz", diff --git a/package.json b/package.json index ce6a6f9b..72ef996c 100644 --- a/package.json +++ b/package.json @@ -78,6 +78,7 @@ "vite": "^4.3.9" }, "dependencies": { + "@coral-xyz/anchor": "^0.29.0", "@lottiefiles/svelte-lottie-player": "^0.3.0", "@onsol/tldparser": "^0.5.3", "@solana/spl-account-compression": "^0.1.8", diff --git a/src/lib/util/stores/idl.ts b/src/lib/util/stores/idl.ts new file mode 100644 index 00000000..588c50f2 --- /dev/null +++ b/src/lib/util/stores/idl.ts @@ -0,0 +1,4 @@ +import { writable } from "svelte/store"; +import type { Idl } from "@coral-xyz/anchor"; + +export const idlStore = writable(null); diff --git a/src/lib/util/stores/idlStore.ts b/src/lib/util/stores/idlStore.ts new file mode 100644 index 00000000..b6e66c4b --- /dev/null +++ b/src/lib/util/stores/idlStore.ts @@ -0,0 +1,64 @@ +/* eslint-disable no-console */ +/* eslint-disable this/no-this */ +import { writable, type Writable } from "svelte/store"; +import { PublicKey, Keypair, Connection } from "@solana/web3.js"; +import * as anchor from "@coral-xyz/anchor"; +import { getRPCUrl } from "../get-rpc-url"; + +// Define the internal state type +type IdlState = anchor.Idl | null; + +class IdlStore { + private store: Writable; + + constructor() { + this.store = writable(null); + } + + // Method to get the store's subscription method + subscribe(run: (value: IdlState) => void) { + return this.store.subscribe(run); + } + + // Method to manually set the store's state + set(idl: IdlState) { + this.store.set(idl); + } + + // Method to update the store's state + update(updater: (value: IdlState) => IdlState) { + this.store.update(updater); + } +} + +// Create an instance of the custom store +export const idlStore = new IdlStore(); + +// Function to fetch IDL and update the store +export async function grabIdl( + accountAddress: string, + isMainnetValue: boolean, + apiKey: string +) { + try { + const connection = new Connection( + getRPCUrl(`?api-key=${apiKey}`, isMainnetValue), + "confirmed" + ); + const aWallet = new anchor.Wallet(Keypair.generate()); + const provider = new anchor.AnchorProvider( + connection, + aWallet, + anchor.AnchorProvider.defaultOptions() + ); + + const accountPubkey = new PublicKey(accountAddress); + const idl = await anchor.Program.fetchIdl(accountPubkey, provider); + + // Directly use the idlStore instance to set the IDL + idlStore.set(idl); + } catch (error) { + console.error("Error fetching IDL:", error); + idlStore.set(null); + } +} diff --git a/src/routes/account/[account]/+layout.svelte b/src/routes/account/[account]/+layout.svelte index 75e2b3c6..7f5b0935 100644 --- a/src/routes/account/[account]/+layout.svelte +++ b/src/routes/account/[account]/+layout.svelte @@ -1,12 +1,22 @@
@@ -75,6 +97,13 @@ {/if} + {#if programIDL} + IDL + {/if}
diff --git a/src/routes/account/[account]/idl/+page.svelte b/src/routes/account/[account]/idl/+page.svelte new file mode 100644 index 00000000..5e593173 --- /dev/null +++ b/src/routes/account/[account]/idl/+page.svelte @@ -0,0 +1,27 @@ + + +
+
+ {#if idlData} +
+
{@html idl}
+
+ {/if} +
+
\ No newline at end of file From 5ac86ad978856f6d84e90f07d464bb3b16a6c90d Mon Sep 17 00:00:00 2001 From: 0xIchigo <0xIchigo@protonmail.com> Date: Mon, 8 Jan 2024 17:54:14 -0500 Subject: [PATCH 2/8] Fix Fetching IDL and Display It Properly --- src/lib/util/grab-idl.ts | 63 ++++++++++++++++++ src/lib/util/stores/idlStore.ts | 64 ------------------- src/routes/account/[account]/+layout.svelte | 20 +++--- .../account/[account]/assets/+page.svelte | 3 +- src/routes/account/[account]/idl/+page.svelte | 24 ++++--- 5 files changed, 84 insertions(+), 90 deletions(-) create mode 100644 src/lib/util/grab-idl.ts delete mode 100644 src/lib/util/stores/idlStore.ts diff --git a/src/lib/util/grab-idl.ts b/src/lib/util/grab-idl.ts new file mode 100644 index 00000000..d0873207 --- /dev/null +++ b/src/lib/util/grab-idl.ts @@ -0,0 +1,63 @@ +/* eslint-disable no-console */ +/* eslint-disable this/no-this */ +import { + PublicKey, + Keypair, + Connection, + Transaction, + VersionedTransaction, +} from "@solana/web3.js"; +import { AnchorProvider, Program, type Idl } from "@coral-xyz/anchor"; +import { getRPCUrl } from "./get-rpc-url"; +import { idlStore } from "./stores/idl"; + +type DummyTransaction = { dummy: true }; + +// Function to fetch IDL and update the store +export async function grabIdl( + accountAddress: string, + isMainnetValue: boolean, + apiKey: string +) { + try { + const connection = new Connection( + getRPCUrl(`?api-key=${apiKey}`, isMainnetValue), + "confirmed" + ); + + // In the future, look into ambiguous export errors for Anchor's Wallet class + // For now, we create a dummy wallet and use it with the provider + // This is enough since we aren't actually using the wallet to sign anything + const dummyKeypair = Keypair.generate(); + const dummyWallet = { + publicKey: dummyKeypair.publicKey, + signAllTransactions: ( + txs: T[] + ): Promise => Promise.resolve(txs), + signTransaction: ( + tx: T + ): Promise => Promise.resolve(tx), + }; + + const provider = new AnchorProvider( + connection, + dummyWallet, + AnchorProvider.defaultOptions() + ); + + const accountPubkey = new PublicKey(accountAddress); + const idl = (await Program.fetchIdl( + accountPubkey, + provider + )) as Idl | null; + + // Directly use the idlStore instance to set the IDL + idlStore.set(idl); + idlStore.subscribe((value) => { + console.log("Store updated:", value); + }); + } catch (error) { + console.error("Error fetching IDL:", error); + idlStore.set(null); + } +} diff --git a/src/lib/util/stores/idlStore.ts b/src/lib/util/stores/idlStore.ts deleted file mode 100644 index b6e66c4b..00000000 --- a/src/lib/util/stores/idlStore.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable no-console */ -/* eslint-disable this/no-this */ -import { writable, type Writable } from "svelte/store"; -import { PublicKey, Keypair, Connection } from "@solana/web3.js"; -import * as anchor from "@coral-xyz/anchor"; -import { getRPCUrl } from "../get-rpc-url"; - -// Define the internal state type -type IdlState = anchor.Idl | null; - -class IdlStore { - private store: Writable; - - constructor() { - this.store = writable(null); - } - - // Method to get the store's subscription method - subscribe(run: (value: IdlState) => void) { - return this.store.subscribe(run); - } - - // Method to manually set the store's state - set(idl: IdlState) { - this.store.set(idl); - } - - // Method to update the store's state - update(updater: (value: IdlState) => IdlState) { - this.store.update(updater); - } -} - -// Create an instance of the custom store -export const idlStore = new IdlStore(); - -// Function to fetch IDL and update the store -export async function grabIdl( - accountAddress: string, - isMainnetValue: boolean, - apiKey: string -) { - try { - const connection = new Connection( - getRPCUrl(`?api-key=${apiKey}`, isMainnetValue), - "confirmed" - ); - const aWallet = new anchor.Wallet(Keypair.generate()); - const provider = new anchor.AnchorProvider( - connection, - aWallet, - anchor.AnchorProvider.defaultOptions() - ); - - const accountPubkey = new PublicKey(accountAddress); - const idl = await anchor.Program.fetchIdl(accountPubkey, provider); - - // Directly use the idlStore instance to set the IDL - idlStore.set(idl); - } catch (error) { - console.error("Error fetching IDL:", error); - idlStore.set(null); - } -} diff --git a/src/routes/account/[account]/+layout.svelte b/src/routes/account/[account]/+layout.svelte index 7f5b0935..354db2a5 100644 --- a/src/routes/account/[account]/+layout.svelte +++ b/src/routes/account/[account]/+layout.svelte @@ -1,15 +1,13 @@
@@ -57,7 +56,7 @@ {/each}
-{#if $assets.hasNextPage && lastPageHadAssets &&!isOnePage} +{#if $assets.hasNextPage && lastPageHadAssets && !isOnePage}
- {#if !endsWith("/tokens") && !endsWith("/assets")} + {#if !endsWith("/tokens") && !endsWith("/assets") && !endsWith("/idl")}