import fs from "fs" ; import path from "path" ; import rimraf from "rimraf" ; import axios from "axios" ; import tar from "tar" ; import stream from "stream" ; import { promisify } from "util" ; import retry from "async-retry" ; export type TestToDownload = "general" | "mainnet" | "minimal" ; export const defaultTestsToDownload = [ "general" , "mainnet" , "minimal" ] ; export const defaultSpecTestsRepoUrl = "https://github.com/ethereum/consensus-spec-tests" ; const logEmpty = ( ) : void => { } ; export interface IDownloadTestsOptions { specVersion : string ; outputDir : string ; specTestsRepoUrl ? : string ; testsToDownload ? : TestToDownload [ ] ; } export interface IDownloadGenericTestsOptions < TestNames extends string > { specVersion : string ; outputDir : string ; specTestsRepoUrl : string ; testsToDownload : TestNames [ ] ; } /**
 * Download spec tests
 */ export async function downloadTests ( { specVersion , specTestsRepoUrl , outputDir , testsToDownload } , log = logEmpty ) { await downloadGenericSpecTests ( { specVersion , outputDir , specTestsRepoUrl : specTestsRepoUrl ?? defaultSpecTestsRepoUrl , testsToDownload : testsToDownload ?? defaultTestsToDownload , } , log ) ; } /**
 * Generic Github release downloader.
 * Used by spec tests and SlashingProtectionInterchangeTest
 */ export async function downloadGenericSpecTests < TestNames extends string > ( { specVersion , specTestsRepoUrl , outputDir , testsToDownload } , log = logEmpty ) { log ( `outputDir = ${ outputDir }` ) ; const versionFile = path . join ( outputDir , "version.txt" ) ; const existingVersion = fs . existsSync ( versionFile ) && fs . readFileSync ( versionFile , "utf8" ) . trim ( ) ; if ( existingVersion === specVersion ) { return log ( `version ${ specVersion } already downloaded` ) ; } else { log ( `Downloading new version ${ specVersion }` ) ; } if ( fs . existsSync ( outputDir ) ) { log ( `Cleaning existing version ${ existingVersion } at ${ outputDir }` ) ; rimraf . sync ( outputDir ) ; } fs . mkdirSync ( outputDir , { recursive : true } ) ; await Promise . all ( testsToDownload . map ( async ( test ) => { const url = `${ specTestsRepoUrl ?? defaultSpecTestsRepoUrl }/releases/download/${ specVersion }/${ test }.tar.gz` ; await retry ( async ( ) => { const { data , headers } = await axios ( { method : "get" , url , responseType : "stream" , timeout : 30 * 60 * 1000 , } ) ; const totalSize = headers [ "content-length" ] ; log ( `Downloading ${ url } - ${ totalSize } bytes` ) ; await promisify ( stream . pipeline ) ( data , tar . x ( { cwd : outputDir } ) ) ; log ( `Downloaded  ${ url }` ) ; } , { retries : 3 , onRetry : ( e , attempt ) => { log ( `Download attempt ${ attempt } for ${ url } failed: ${ e . message }` ) ; } , } ) ; } ) ) ; fs . writeFileSync ( versionFile , specVersion ) ; }