-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e6333e3
commit 4672295
Showing
5 changed files
with
150 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -855,10 +855,10 @@ | |
"@nodelib/fs.scandir" "2.1.4" | ||
fastq "^1.6.0" | ||
|
||
"@project-serum/borsh@^0.2.2": | ||
version "0.2.2" | ||
resolved "https://registry.npmjs.org/@project-serum/borsh/-/borsh-0.2.2.tgz" | ||
integrity sha512-Ms+aWmGVW6bWd3b0+MWwoaYig2QD0F90h0uhr7AzY3dpCb5e2S6RsRW02vFTfa085pY2VLB7nTZNbFECQ1liTg== | ||
"@project-serum/borsh@^0.2.4": | ||
version "0.2.4" | ||
resolved "https://registry.yarnpkg.com/@project-serum/borsh/-/borsh-0.2.4.tgz#8884c3a759984a39d54bf5b7390bd1ee0b579f16" | ||
integrity sha512-tQPc1ktAp1Jtn9D72DmObAfhAic9ivfYBOS5b+T4H7MvkQ84uML88LY1LfvGep30mCy+ua5rf+X9ocPfg6u9MA== | ||
dependencies: | ||
bn.js "^5.1.2" | ||
buffer-layout "^1.2.0" | ||
|
@@ -1836,6 +1836,13 @@ create-require@^1.1.0: | |
resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" | ||
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== | ||
|
||
cross-fetch@^3.1.5: | ||
version "3.1.5" | ||
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" | ||
integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== | ||
dependencies: | ||
node-fetch "2.6.7" | ||
|
||
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: | ||
version "7.0.3" | ||
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" | ||
|
@@ -3744,6 +3751,13 @@ node-addon-api@^2.0.0: | |
resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz" | ||
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== | ||
|
||
[email protected]: | ||
version "2.6.7" | ||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" | ||
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== | ||
dependencies: | ||
whatwg-url "^5.0.0" | ||
|
||
node-fetch@^2.6.1: | ||
version "2.6.1" | ||
resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz" | ||
|
@@ -4695,6 +4709,11 @@ tr46@^2.1.0: | |
dependencies: | ||
punycode "^2.1.1" | ||
|
||
tr46@~0.0.3: | ||
version "0.0.3" | ||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" | ||
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= | ||
|
||
traverse-chain@~0.1.0: | ||
version "0.1.0" | ||
resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" | ||
|
@@ -4929,6 +4948,11 @@ walker@^1.0.7: | |
dependencies: | ||
makeerror "1.0.x" | ||
|
||
webidl-conversions@^3.0.0: | ||
version "3.0.1" | ||
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" | ||
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= | ||
|
||
webidl-conversions@^5.0.0: | ||
version "5.0.0" | ||
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz" | ||
|
@@ -4951,6 +4975,14 @@ whatwg-mimetype@^2.3.0: | |
resolved "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz" | ||
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== | ||
|
||
whatwg-url@^5.0.0: | ||
version "5.0.0" | ||
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" | ||
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= | ||
dependencies: | ||
tr46 "~0.0.3" | ||
webidl-conversions "^3.0.0" | ||
|
||
whatwg-url@^8.0.0: | ||
version "8.4.0" | ||
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz" | ||
|