From c9eeb88a189dcf8e7c7c0aa509f5cde469cb5db5 Mon Sep 17 00:00:00 2001 From: eteen12 Date: Mon, 11 May 2026 17:35:46 -0700 Subject: [PATCH 1/5] feat(ts): re-implement verifiedBuild using OtterSec registry Replaces the defunct apr.dev API with verify.osec.io. Exports a VerifiedBuild type matching the /status/{programId} response shape. Closes #4435 --- CHANGELOG.md | 1 + ts/packages/anchor/src/utils/registry.ts | 26 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f625621b2..252731fa0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The minor version will be incremented upon a breaking change and the patch versi ### Features +- ts: Re-implement `verifiedBuild` using the OtterSec registry (`verify.osec.io`), replacing the defunct `apr.dev` API ([#4435](https://github.com/solana-foundation/anchor/issues/4435)). - ts: Add `decodeIdlAccountRaw` ([#4375](https://github.com/solana-foundation/anchor/pull/4375)). - cli: Add `--stdout` flag to the `expand` command ([#4400](https://github.com/solana-foundation/anchor/pull/4400)). - client: Add versioned tx support ([#4207](https://github.com/solana-foundation/anchor/pull/4207)). diff --git a/ts/packages/anchor/src/utils/registry.ts b/ts/packages/anchor/src/utils/registry.ts index 6e389f541d..d450c7aa57 100644 --- a/ts/packages/anchor/src/utils/registry.ts +++ b/ts/packages/anchor/src/utils/registry.ts @@ -1,7 +1,33 @@ import BN from "bn.js"; +import fetch from "cross-fetch"; import * as borsh from "@anchor-lang/borsh"; import { Connection, PublicKey } from "@solana/web3.js"; +const OSEC_REGISTRY_URL = "https://verify.osec.io"; + +export type VerifiedBuild = { + is_verified: boolean; + on_chain_hash: string; + executable_hash: string; + repo_url: string; + commit: string; + last_verified_at: string; + signer: string; + is_frozen: boolean; +}; + +/** Returns verified build info from the OtterSec registry, or null if unverified. */ +export async function verifiedBuild( + programId: PublicKey +): Promise { + const resp = await fetch( + `${OSEC_REGISTRY_URL}/status/${programId.toString()}` + ); + if (!resp.ok) return null; + const build = (await resp.json()) as VerifiedBuild; + return build.is_verified ? build : null; +} + /** * Returns the program data account for this program, containing the * metadata for this program, e.g., the upgrade authority. From 5b233e427349efd8c70ad7d0a633c3eaabd0df34 Mon Sep 17 00:00:00 2001 From: eteen12 Date: Tue, 12 May 2026 10:40:12 -0700 Subject: [PATCH 2/5] =?UTF-8?q?fix(ts):=20address=20bot=20review=20on=20ve?= =?UTF-8?q?rifiedBuild=20=E2=80=94=20optional=20fields=20+=20try/catch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ts/packages/anchor/src/utils/registry.ts | 26 +++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/ts/packages/anchor/src/utils/registry.ts b/ts/packages/anchor/src/utils/registry.ts index d450c7aa57..94f1bcfa2c 100644 --- a/ts/packages/anchor/src/utils/registry.ts +++ b/ts/packages/anchor/src/utils/registry.ts @@ -7,25 +7,31 @@ const OSEC_REGISTRY_URL = "https://verify.osec.io"; export type VerifiedBuild = { is_verified: boolean; + message?: string; on_chain_hash: string; executable_hash: string; repo_url: string; - commit: string; last_verified_at: string; - signer: string; - is_frozen: boolean; + // present in some registry responses but not guaranteed by the documented API + commit?: string; + signer?: string; + is_frozen?: boolean; }; -/** Returns verified build info from the OtterSec registry, or null if unverified. */ +/** Returns verified build info from the OtterSec registry, or null if unverified or the request fails. */ export async function verifiedBuild( programId: PublicKey ): Promise { - const resp = await fetch( - `${OSEC_REGISTRY_URL}/status/${programId.toString()}` - ); - if (!resp.ok) return null; - const build = (await resp.json()) as VerifiedBuild; - return build.is_verified ? build : null; + try { + const resp = await fetch( + `${OSEC_REGISTRY_URL}/status/${programId.toString()}` + ); + if (!resp.ok) return null; + const build = (await resp.json()) as VerifiedBuild; + return build.is_verified ? build : null; + } catch { + return null; + } } /** From 3c97d98529a4ae3d5d9a298d9c4248ab1badda7c Mon Sep 17 00:00:00 2001 From: swaroop-osec Date: Fri, 15 May 2026 18:58:26 +0530 Subject: [PATCH 3/5] refactor(ts): update VerifiedBuild type --- ts/packages/anchor/src/utils/registry.ts | 27 ++++++++++++------------ 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/ts/packages/anchor/src/utils/registry.ts b/ts/packages/anchor/src/utils/registry.ts index 94f1bcfa2c..86ed5676fe 100644 --- a/ts/packages/anchor/src/utils/registry.ts +++ b/ts/packages/anchor/src/utils/registry.ts @@ -7,24 +7,23 @@ const OSEC_REGISTRY_URL = "https://verify.osec.io"; export type VerifiedBuild = { is_verified: boolean; - message?: string; + message: string; on_chain_hash: string; executable_hash: string; repo_url: string; - last_verified_at: string; - // present in some registry responses but not guaranteed by the documented API - commit?: string; - signer?: string; - is_frozen?: boolean; + commit: string; + last_verified_at: string | null; + is_frozen: boolean; + is_closed: boolean; }; /** Returns verified build info from the OtterSec registry, or null if unverified or the request fails. */ export async function verifiedBuild( - programId: PublicKey + programId: PublicKey, ): Promise { try { const resp = await fetch( - `${OSEC_REGISTRY_URL}/status/${programId.toString()}` + `${OSEC_REGISTRY_URL}/status/${programId.toString()}`, ); if (!resp.ok) return null; const build = (await resp.json()) as VerifiedBuild; @@ -40,7 +39,7 @@ export async function verifiedBuild( */ export async function fetchData( connection: Connection, - programId: PublicKey + programId: PublicKey, ): Promise { const accountInfo = await connection.getAccountInfo(programId); if (accountInfo === null) { @@ -48,13 +47,13 @@ export async function fetchData( } const { program } = decodeUpgradeableLoaderState(accountInfo.data); const programdataAccountInfo = await connection.getAccountInfo( - program.programdataAddress + program.programdataAddress, ); if (programdataAccountInfo === null) { throw new Error("program data account not found"); } const { programData } = decodeUpgradeableLoaderState( - programdataAccountInfo.data + programdataAccountInfo.data, ); return programData; } @@ -64,7 +63,7 @@ const UPGRADEABLE_LOADER_STATE_LAYOUT = borsh.rustEnum( borsh.struct([], "uninitialized"), borsh.struct( [borsh.option(borsh.publicKey(), "authorityAddress")], - "buffer" + "buffer", ), borsh.struct([borsh.publicKey("programdataAddress")], "program"), borsh.struct( @@ -72,11 +71,11 @@ const UPGRADEABLE_LOADER_STATE_LAYOUT = borsh.rustEnum( borsh.u64("slot"), borsh.option(borsh.publicKey(), "upgradeAuthorityAddress"), ], - "programData" + "programData", ), ], undefined, - borsh.u32() + borsh.u32(), ); export function decodeUpgradeableLoaderState(data: Buffer): any { From d11ebf3433d0ec21726bfe2c1a9741d685f7647c Mon Sep 17 00:00:00 2001 From: swaroop-osec Date: Fri, 15 May 2026 19:02:50 +0530 Subject: [PATCH 4/5] chore: update CHANGELOG --- CHANGELOG.md | 10 +++++----- Untitled | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 Untitled diff --git a/CHANGELOG.md b/CHANGELOG.md index 252731fa0d..5621d908c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,7 @@ The minor version will be incremented upon a breaking change and the patch versi ### Features -- ts: Re-implement `verifiedBuild` using the OtterSec registry (`verify.osec.io`), replacing the defunct `apr.dev` API ([#4435](https://github.com/solana-foundation/anchor/issues/4435)). +- ts: Re-implement `verifiedBuild` using the OtterSec registry (`verify.osec.io`), replacing the defunct `apr.dev` API ([#4522](https://github.com/solana-foundation/anchor/pull/4522)). - ts: Add `decodeIdlAccountRaw` ([#4375](https://github.com/solana-foundation/anchor/pull/4375)). - cli: Add `--stdout` flag to the `expand` command ([#4400](https://github.com/solana-foundation/anchor/pull/4400)). - client: Add versioned tx support ([#4207](https://github.com/solana-foundation/anchor/pull/4207)). @@ -186,7 +186,7 @@ The minor version will be incremented upon a breaking change and the patch versi - spl: Update SPL dependencies to latest compatible versions ([#3860](https://github.com/solana-foundation/anchor/pull/3860)). - cli: Replace `anchor verify` to use `solana-verify` under the hood, adding automatic installation via AVM, local path support, and future-proof argument passing ([#3768](https://github.com/solana-foundation/anchor/pull/3768)). -- cli: Upload IDL by default with an option to skip ((#3863)[https://github.com/solana-foundation/anchor/pull/3863]). +- cli: Upload IDL by default with an option to skip ([#3863](https://github.com/solana-foundation/anchor/pull/3863)). - lang: remove Solang ([#3824](https://github.com/solana-foundation/anchor/pull/3824)). - cli: remove `anchor publish` command ([#3795](https://github.com/solana-foundation/anchor/pull/3795)). @@ -478,7 +478,7 @@ See the [Anchor 0.30 release notes](https://www.anchor-lang.com/release-notes/0. - spl: Fix not being able to deserialize newer token 2022 extensions ([#2876](https://github.com/solana-foundation/anchor/pull/2876)). - client: Fix erroneous Cluster websocket ports ([#2690](https://github.com/solana-foundation/anchor/pull/2690)). - spl: Remove `solana-program` dependency ([#2900](https://github.com/solana-foundation/anchor/pull/2900)). -- spl: Make `TokenAccount` and ` Mint` `Copy` ([#2904](https://github.com/solana-foundation/anchor/pull/2904)). +- spl: Make `TokenAccount` and `Mint` `Copy` ([#2904](https://github.com/solana-foundation/anchor/pull/2904)). - ts: Add missing errors ([#2906](https://github.com/solana-foundation/anchor/pull/2906)). ### Breaking @@ -823,9 +823,9 @@ See the [Anchor 0.29 release notes](https://www.anchor-lang.com/release-notes/0. - lang: Require doc comments when using AccountInfo or UncheckedAccount types ([#1452](https://github.com/solana-foundation/anchor/pull/1452)). - lang: add [`error!`](https://docs.rs/anchor-lang/latest/anchor_lang/prelude/macro.error.html) and [`err!`](https://docs.rs/anchor-lang/latest/anchor_lang/prelude/macro.err.html) macro and `Result` type ([#1462](https://github.com/solana-foundation/anchor/pull/1462)). This change will break most programs. Do the following to upgrade: - _ change all `ProgramResult`'s to `Result<()>` + _change all `ProgramResult`'s to `Result<()>` _ change `#[error]` to `#[error_code]` - _ change all `Err(MyError::SomeError.into())` to `Err(error!(MyError::SomeError))` and all `Err(ProgramError::SomeProgramError)` to `Err(ProgramError::SomeProgramError.into())` or `Err(Error::from(ProgramError::SomeProgramError).with_source(source!()))` to provide file and line source of the error (`with_source` is most useful with `ProgramError`s. `error!` already adds source information for custom and anchor internal errors). + _change all `Err(MyError::SomeError.into())` to `Err(error!(MyError::SomeError))` and all `Err(ProgramError::SomeProgramError)` to `Err(ProgramError::SomeProgramError.into())` or `Err(Error::from(ProgramError::SomeProgramError).with_source(source!()))` to provide file and line source of the error (`with_source` is most useful with `ProgramError`s. `error!` already adds source information for custom and anchor internal errors). _ change all `solana_program::program::invoke()` to `solana_program::program::invoke().map_err(Into::into)` and `solana_program::program::invoke_signed()` to `solana_program::program::invoke_signed().map_err(Into::into)` ## [0.21.0] - 2022-02-07 diff --git a/Untitled b/Untitled new file mode 100644 index 0000000000..379fa987e5 --- /dev/null +++ b/Untitled @@ -0,0 +1 @@ +ts: Re-implement \ No newline at end of file From 7c33d0818ff3f7c48e9606d7dbaeed3bcf74855c Mon Sep 17 00:00:00 2001 From: swaroop-osec Date: Tue, 19 May 2026 14:36:44 +0530 Subject: [PATCH 5/5] chore: remove unused Untitled file --- Untitled | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Untitled diff --git a/Untitled b/Untitled deleted file mode 100644 index 379fa987e5..0000000000 --- a/Untitled +++ /dev/null @@ -1 +0,0 @@ -ts: Re-implement \ No newline at end of file