Эх сурвалжийг харах

Add support for external accounts

febo 1 жил өмнө
parent
commit
5fd818addc

+ 14 - 8
template/base/scripts/program/dump.mjs

@@ -10,11 +10,17 @@ const rpc = process.env.RPC ?? 'https://api.mainnet-beta.solana.com';
 const outputDir = getExternalProgramOutputDir();
 await dump();
 
-/** Dump external programs binaries if needed. */
+/** Dump external programs binaries and accounts if needed. */
 async function dump() {
-  // Ensure we have some external programs to dump.
-  const addresses = getExternalProgramAddresses();
-  if (addresses.length === 0) return;
+  // Ensure we have some external accounts to dump.
+  const programs = getExternalProgramAddresses();
+  const accounts = getExternalAccountAddresses();
+  const binaries = [
+    ...programs.map((program) => `${program}.so`),
+    ...accounts.map((account) => `${account}.json`),
+  ].flat();
+
+  if (binaries.length === 0) return;
   echo(`Dumping external accounts to '${outputDir}':`);
 
   // Create the output directory if needed.
@@ -22,8 +28,8 @@ async function dump() {
 
   // Copy the binaries from the chain or warn if they are different.
   await Promise.all(
-    addresses.map(async (address) => {
-      const binary = `${address}.so`;
+    binaries.map(async (binary) => {
+      const address = binaries.split('.')[0];
       const hasBinary = await fs.exists(`${outputDir}/${binary}`);
 
       if (!hasBinary) {
@@ -79,8 +85,8 @@ async function dump() {
 /** Helper function to copy external programs or accounts binaries from the chain. */
 async function copyFromChain(address, binary) {
   switch (binary.split('.').pop()) {
-    case 'bin':
-      return $`solana account -u ${rpc} ${address} -o ${outputDir}/${binary} >/dev/null`.quiet();
+    case 'json':
+      return $`solana account -u ${rpc} ${address} -o ${outputDir}/${binary} --output json >/dev/null`.quiet();
     case 'so':
       return $`solana program dump -u ${rpc} ${address} ${outputDir}/${binary} >/dev/null`.quiet();
     default:

+ 8 - 0
template/base/scripts/utils.mjs

@@ -26,6 +26,14 @@ export function getExternalProgramAddresses() {
   return Array.from(new Set(addresses));
 }
 
+export function getExternalAccountAddresses() {
+  const addresses = getProgramFolders().flatMap(
+    (folder) =>
+      getCargo(folder).package?.metadata?.solana?.["account-dependencies"] ?? []
+  );
+  return Array.from(new Set(addresses));
+}
+
 let didWarnAboutMissingPrograms = false;
 export function getProgramFolders() {
   let programs;

+ 23 - 1
template/clients/base/scripts/start-validator.mjs

@@ -4,6 +4,7 @@ import fs from 'node:fs';
 import 'zx/globals';
 import {
   getCargo,
+  getExternalAccountAddresses,
   getExternalProgramAddresses,
   getExternalProgramOutputDir,
   getProgramFolders,
@@ -21,10 +22,18 @@ if (!restart && isValidatorRunning) {
 
 // Initial message.
 const verb = isValidatorRunning ? 'Restarting' : 'Starting';
+
+// Get programs and accounts.
 const programs = [...getPrograms(), ...getExternalPrograms()];
 const programPluralized = programs.length === 1 ? 'program' : 'programs';
+const accounts = [...getExternalAccounts()];
+const accountsPluralized = accounts.length === 1 ? 'account' : 'accounts';
+
 echo(
-  `${verb} local validator with ${programs.length} custom ${programPluralized}...`
+  `${verb} local validator with ${programs.length} custom ${programPluralized}` +
+    (accounts.length > 0
+      ? ` and ${accounts.length} external ${accountsPluralized}...`
+      : `...`)
 );
 
 // Kill the validator if it's already running.
@@ -41,6 +50,11 @@ programs.forEach(({ programId, deployPath }) => {
   args.push(/* Load BPF program */ '--bpf-program', programId, deployPath);
 });
 
+// Load accounts.
+accounts.forEach(({ account, deployPath }) => {
+  args.push(/* Load account */ '--account', account, deployPath);
+});
+
 // Start the validator in detached mode.
 const cliLogs = path.join(os.tmpdir(), 'validator-cli.log');
 fs.writeFileSync(cliLogs, '', () => {});
@@ -98,3 +112,11 @@ function getExternalPrograms() {
     deployPath: path.join(binaryDir, `${address}.so`),
   }));
 }
+
+function getExternalAccounts() {
+  const binaryDir = getExternalProgramOutputDir();
+  return getExternalAccountAddresses().map((address) => ({
+    account: address,
+    deployPath: path.join(binaryDir, `${address}.json`),
+  }));
+}