Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// https://vanity-service.parity.io/parity-binaries?version=stable&os=linux&architecture=x86_64
// https://vanity-service.parity.io/parity-binaries?version=beta&os=windows&architecture=x86_64
// https://vanity-service.parity.io/parity-binaries?version=beta&os=darwin&architecture=x86_64
const crypto = require('crypto');
const { chmod, existsSync, writeFile } = require('fs');
const download = require('download');
const fetch = require('node-fetch');
const { promisify } = require('util');
const semver = require('semver');
const {
parity: { version: versionRequirement }
} = require('../packages/fether-electron/package.json');
const exec = promisify(require('child_process').exec);
const fsChmod = promisify(chmod);
const fsWriteFile = promisify(writeFile);
let os;
switch (process.platform) {
case 'win32':
os = 'windows';
break;
case 'darwin':
os = 'darwin';
break;
default:
os = 'linux';
}
const ENDPOINT = `https://vanity-service.parity.io/parity-binaries?os=${os}&architecture=x86_64`;
const STATIC_DIRECTORY = '../packages/fether-electron/static/';
const foundPath = [
`${STATIC_DIRECTORY}/parity`,
`${STATIC_DIRECTORY}/parity.exe`
].find(existsSync);
if (foundPath) {
// Bundled Parity was found, we check if the version matches the minimum requirements
getBinaryVersion(foundPath)
.then(version => {
if (!semver.satisfies(version, versionRequirement)) {
console.log(
'Bundled Parity Ethereum %s is older than required version %s',
version,
versionRequirement
);
return downloadParity();
} else {
console.log(
'Bundled Parity Ethereum %s matches required version %s',
version,
versionRequirement
);
}
})
.catch(e => {
console.error(e);
process.exit(1);
});
} else {
// Bundled Parity wasn't found, we download the latest version
downloadParity().catch(e => {
console.error(e);
process.exit(1);
});
}
function downloadParity () {
return (
fetch(ENDPOINT)
.then(r => r.json())
// Find the latest version matching the version requirement
//
// We use this method rather than downloading the latest beta, because if
// somebody checks out a year-old commit, then the latest beta of Parity would
// be downloaded, which would most likely not be compatible with the version
// requirement (e.g. ~2.4.1)
.then(resp => {
const latestCompatibleItem = resp
.filter(({ version }) => semver.valid(version))
.reduce(
(bestItem, item) =>
semver.gt(item.version, bestItem.version) &&
semver.satisfies(item.version, versionRequirement)
? item
: bestItem,
{ version: '0.0.0' }
);
if (latestCompatibleItem.version === '0.0.0') {
throw new Error(
`Couldn't find a Parity Ethereum version compatible with ${versionRequirement}`
);
}
return latestCompatibleItem;
})
.then(({ files, version }) => ({
...files.find(({ name }) => ['parity', 'parity.exe'].includes(name)),
version
}))
.then(({ name, downloadUrl, checksum: expectedChecksum, version }) => {
console.log(
'Downloading Parity Ethereum %s... (%s)',
version,
downloadUrl
);
return download(downloadUrl).then(data => {
const actualChecksum = crypto
.createHash('sha256')
.update(data)
.digest('hex');
if (expectedChecksum !== actualChecksum) {
throw new Error(
`Parity Ethereum checksum mismatch: expecting ${expectedChecksum}, got ${actualChecksum}.`
);
}
// Write to file and set a+x permissions
const destinationPath = `${STATIC_DIRECTORY}/${name}`;
return fsWriteFile(destinationPath, data)
.then(() => fsChmod(destinationPath, 0o755)) // https://nodejs.org/api/fs.html#fs_fs_chmod_path_mode_callback
.then(() => destinationPath);
});
})
.then(getBinaryVersion)
.then(bundledVersion =>
console.log(`Success: bundled Parity Ethereum ${bundledVersion}`)
)
);
}
function getBinaryVersion (binaryPath) {
return exec(`${binaryPath} --version`).then(({ stdout, stderr }) => {
if (stderr) throw new Error(stderr);
return stdout.match(/v\d+\.\d+\.\d+/)[0];
});
}