123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
- import BN from "bn.js";
- import fetch from "cross-fetch";
- import * as borsh from "@project-serum/borsh";
- import { Connection, PublicKey } from "@solana/web3.js";
- /**
- * Returns a verified build from the anchor registry. null if no such
- * verified build exists, e.g., if the program has been upgraded since the
- * last verified build.
- */
- export async function verifiedBuild(
- connection: Connection,
- programId: PublicKey,
- limit: number = 5
- ): Promise<Build | null> {
- const url = `https://anchor.projectserum.com/api/v0/program/${programId.toString()}/latest?limit=${limit}`;
- const [programData, latestBuildsResp] = await Promise.all([
- fetchData(connection, programId),
- fetch(url),
- ]);
- // Filter out all non successful builds.
- const latestBuilds = (await latestBuildsResp.json()).filter(
- (b: Build) => !b.aborted && b.state === "Built" && b.verified === "Verified"
- );
- if (latestBuilds.length === 0) {
- return null;
- }
- // Get the latest build.
- const build = latestBuilds[0];
- // Has the program been upgraded since the last build?
- if (programData.slot.toNumber() !== build.verified_slot) {
- return null;
- }
- // Success.
- return build;
- }
- /**
- * Returns the program data account for this program, containing the
- * metadata for this program, e.g., the upgrade authority.
- */
- export async function fetchData(
- connection: Connection,
- programId: PublicKey
- ): Promise<ProgramData> {
- const accountInfo = await connection.getAccountInfo(programId);
- if (accountInfo === null) {
- throw new Error("program account not found");
- }
- const { program } = decodeUpgradeableLoaderState(accountInfo.data);
- const programdataAccountInfo = await connection.getAccountInfo(
- program.programdataAddress
- );
- if (programdataAccountInfo === null) {
- throw new Error("program data account not found");
- }
- const { programData } = decodeUpgradeableLoaderState(
- programdataAccountInfo.data
- );
- return programData;
- }
- const UPGRADEABLE_LOADER_STATE_LAYOUT = borsh.rustEnum(
- [
- borsh.struct([], "uninitialized"),
- borsh.struct(
- [borsh.option(borsh.publicKey(), "authorityAddress")],
- "buffer"
- ),
- borsh.struct([borsh.publicKey("programdataAddress")], "program"),
- borsh.struct(
- [
- borsh.u64("slot"),
- borsh.option(borsh.publicKey(), "upgradeAuthorityAddress"),
- ],
- "programData"
- ),
- ],
- undefined,
- borsh.u32()
- );
- export function decodeUpgradeableLoaderState(data: Buffer): any {
- return UPGRADEABLE_LOADER_STATE_LAYOUT.decode(data);
- }
- export type ProgramData = {
- slot: BN;
- upgradeAuthorityAddress: PublicKey | null;
- };
- export type Build = {
- aborted: boolean;
- address: string;
- created_at: string;
- updated_at: string;
- descriptor: string[];
- docker: string;
- id: number;
- name: string;
- sha256: string;
- upgrade_authority: string;
- verified: string;
- verified_slot: number;
- state: string;
- };
|