fetchParity.js 3.37 KiB
Newer Older
Amaury Martiny's avatar
Amaury Martiny committed
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
//
Amaury Martiny's avatar
Amaury Martiny committed
// SPDX-License-Identifier: BSD-3-Clause
import { app } from 'electron';
import axios from 'axios';
import cs from 'checksum';
import { download } from 'electron-dl';
import fs from 'fs';
import { promisify } from 'util';
import retry from 'async-retry';
Amaury Martiny's avatar
Amaury Martiny committed
import debug from './utils/debug';
import { defaultParityPath, getParityPath } from './getParityPath';
import parityChannel from './utils/parityChannel';
const checksum = promisify(cs.file);
Amaury Martiny's avatar
Amaury Martiny committed
const fsChmod = promisify(fs.chmod);
const fsStat = promisify(fs.stat);
const fsUnlink = promisify(fs.unlink);
const VANITY_URL = 'https://vanity-service.parity.io/parity-binaries';

Amaury Martiny's avatar
Amaury Martiny committed
const getArch = () => {
  switch (process.platform) {
    case 'darwin':
    case 'win32':
      return 'x86_64';
    default: {
      switch (process.arch) {
        case 'arm':
          return 'arm';
        case 'arm64':
          return 'aarch64';
        case 'x32':
          return 'i686';
        default:
          return 'x86_64';
      }
    }
  }
};

const getOs = () => {
  switch (process.platform) {
    case 'darwin':
      return 'darwin';
    case 'win32':
      return 'windows';
    default:
      return 'linux';
  }
};

/**
 * Remove parity binary in the userData folder
 */
export const deleteParity = async () => {
  try {
    const parityPath = await defaultParityPath();
    await fsStat(parityPath);
    await fsUnlink(parityPath);
  } catch (e) {}
// Fetch parity from https://vanity-service.parity.io/parity-binaries
export const fetchParity = (mainWindow, onProgress) => {
  try {
    return retry(
      async (_, attempt) => {
        if (attempt > 1) {
Amaury Martiny's avatar
Amaury Martiny committed
          debug('main')('Retrying.');
Amaury Martiny's avatar
Amaury Martiny committed
        // Delete any old Parity if it exists
        await deleteParity();

        // Fetch the metadata of the correct version of parity
Amaury Martiny's avatar
Amaury Martiny committed
        const metadataUrl = `${VANITY_URL}?version=${parityChannel()}&os=${getOs()}&architecture=${getArch()}`;
        debug('main')(`Downloading from ${metadataUrl}.`);
        const { data } = await axios.get(metadataUrl);

        // Get the binary's url
        const { downloadUrl, checksum: expectedChecksum } = data[0].files.find(
          ({ name }) => name === 'parity' || name === 'parity.exe'
        );

        // Start downloading. This will install parity into defaultParityPath.
        const downloadItem = await download(mainWindow, downloadUrl, {
          directory: app.getPath('userData'),
          onProgress
        const downloadPath = downloadItem.getSavePath(); // Equal to defaultParityPath

        // Once downloaded, we check the sha256 checksum
        // Calculate the actual checksum
        const actualChecksum = await checksum(downloadPath, {
          algorithm: 'sha256'
        });
        // The 2 checksums should of course match
        if (expectedChecksum !== actualChecksum) {
          throw new Error(
            `Checksum mismatch, expecting ${expectedChecksum}, got ${actualChecksum}.`
          );
        }

        // Set a+x permissions on the downloaded binary
        await fsChmod(downloadPath, '755');

        // Double-check that Parity exists now.
        const parityPath = await getParityPath();
        return parityPath;
      },
      {
        retries: 3
      }
    );
  } catch (err) {
    return deleteParity().then(() => {
      Promise.reject(err);
    });