Skip to content

Commit

Permalink
Merge pull request #685 from nos/develop
Browse files Browse the repository at this point in the history
[Release] 0.4.3
  • Loading branch information
mhuggins authored Oct 30, 2018
2 parents df5112b + b5c0897 commit 504b815
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 10 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "nOS",
"description": "nOS: NEO Operating System",
"author": "nOS",
"version": "0.4.2",
"version": "0.4.3",
"private": true,
"main": "dist/main/main.js",
"license": "MIT",
Expand Down
73 changes: 73 additions & 0 deletions src/common/util/getRPCEndpoint.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import fetch from 'node-fetch';
import { rpc, settings } from '@cityofzion/neon-js';

let cachedRPC = null;

function getAPIEndpoint(net) {
if (settings.networks[net]) {
return settings.networks[net].extra.neoscan;
}

return net;
}

function isUnreliableNode(url) {
return url.match(/redpulse\.com/i) ||
url.match(/ddns\.net/i) ||
url.match(/neeeo\.org/i) ||
url.match(/otcgo\.cn/i) ||
url.match(/seed1\.aphelion-neo\.com/i);
}

function raceToSuccess(promises) {
return Promise.all(
promises.map((p) => (
// If a request fails, count that as a resolution so it will keep
// waiting for other possible successes. If a request succeeds,
// treat it as a rejection so Promise.all immediately bails out.
p.then((val) => Promise.reject(val), (err) => err)
))
).then(
// If '.all' resolved, we've just got an array of errors.
(errors) => Promise.reject(errors),
// If '.all' rejected, we've got the result we wanted.
(val) => val
);
}

export default async function getRPCEndpoint(net) {
const apiEndpoint = getAPIEndpoint(net);
const response = await fetch(`${apiEndpoint}/v1/get_all_nodes`);
const data = await response.json();
let nodes = data.sort((a, b) => b.height - a.height);

if (settings.httpsOnly) {
nodes = nodes.filter((n) => n.url.includes('https://'));
}

if (nodes.length === 0) {
throw new Error('No eligible nodes found!');
}

const heightThreshold = nodes[0].height - 1;
const goodNodes = nodes.filter((n) => n.height >= heightThreshold);
const urls = goodNodes.map((n) => n.url).filter((url) => !isUnreliableNode(url));

if (urls.length === 0) {
throw new Error('No eligible nodes found!');
}

if (urls.includes(cachedRPC)) {
return new rpc.RPCClient(cachedRPC).ping().then((num) => {
if (num <= settings.timeout.ping) return cachedRPC;
cachedRPC = null;
return getRPCEndpoint(net);
});
}

const clients = urls.map((u) => new rpc.RPCClient(u));

const fastestUrl = await raceToSuccess(clients.map((c) => c.ping().then(() => c.net)));
cachedRPC = fastestUrl;
return fastestUrl;
}
5 changes: 3 additions & 2 deletions src/main/util/resolve.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import isDev from 'electron-is-dev';
import path from 'path';
import { resolve as resolveURL, format as formatURL } from 'url';
import { api, rpc, u } from '@cityofzion/neon-js';
import { rpc, u } from '@cityofzion/neon-js';

import updateNetworks from 'util/updateNetworks';
import getRPCEndpoint from 'util/getRPCEndpoint';

// TODO: Configurable network
import { NOS_TESTNET } from 'values/networks';
Expand Down Expand Up @@ -46,7 +47,7 @@ function resolveLocal(url) {
async function resolveNameService(url) {
const { host, pathname } = url;

const endpoint = await api.getRPCEndpointFrom({ net: NOS_TESTNET }, api.neoscan);
const endpoint = await getRPCEndpoint(NOS_TESTNET);
const client = new rpc.RPCClient(endpoint);
const storageKey = u.str2hexstring(`${host}.target`);
const response = await client.getStorage(NS_SCRIPT_HASH, storageKey);
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/browser/actions/makeTestInvokeActions.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { createActions } from 'spunky';
import { api, rpc, wallet } from '@cityofzion/neon-js';
import { rpc, wallet } from '@cityofzion/neon-js';
import { isArray } from 'lodash';

import getRPCEndpoint from 'util/getRPCEndpoint';

import createScript from 'shared/util/createScript';

import generateDAppActionId from './generateDAppActionId';
Expand All @@ -21,7 +23,7 @@ const testInvoke = async ({ net, scriptHash, operation, args, encodeArgs }) => {
throw new Error(`Invalid arguments: "${args}"`);
}

const endpoint = await api.getRPCEndpointFrom({ net }, api.neoscan);
const endpoint = await getRPCEndpoint(net);
const script = createScript(scriptHash, operation, args, encodeArgs);
const { result } = await rpc.Query.invokeScript(script).execute(endpoint);

Expand Down
6 changes: 4 additions & 2 deletions src/renderer/shared/actions/blockActions.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { api, rpc } from '@cityofzion/neon-js';
import { rpc } from '@cityofzion/neon-js';
import { createActions } from 'spunky';

import getRPCEndpoint from 'util/getRPCEndpoint';

export const ID = 'block';

export default createActions(ID, ({ net }) => async () => {
const endpoint = await api.getRPCEndpointFrom({ net }, api.neoscan);
const endpoint = await getRPCEndpoint(net);
const client = new rpc.RPCClient(endpoint);
const height = await client.getBlockCount();
return client.getBlock(height - 1);
Expand Down
4 changes: 3 additions & 1 deletion src/renderer/shared/util/getBalances.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { extend, get, find } from 'lodash';
import { api, rpc, wallet } from '@cityofzion/neon-js';

import getRPCEndpoint from 'util/getRPCEndpoint';

import getTokens from './getTokens';
import { GAS, NEO, ASSETS } from '../values/assets';

Expand Down Expand Up @@ -32,7 +34,7 @@ async function getAssetBalances(endpoint, address) {
}

export default async function getBalances({ net, address }) {
const endpoint = await api.getRPCEndpointFrom({ net }, api.neoscan);
const endpoint = await getRPCEndpoint(net);

if (!wallet.isAddress(address)) {
throw new Error(`Invalid address: "${address}"`);
Expand Down
6 changes: 4 additions & 2 deletions src/renderer/shared/util/getStorage.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { wallet, api, rpc, u } from '@cityofzion/neon-js';
import { wallet, rpc, u } from '@cityofzion/neon-js';

import getRPCEndpoint from 'util/getRPCEndpoint';

export const encode = (value) => u.str2hexstring(value);
export const decode = (value) => u.hexstring2str(value);
Expand All @@ -12,7 +14,7 @@ export default async function getStorage({ net, scriptHash, key, encodeInput, de
throw new Error(`Invalid key: "${key}"`);
}

const endpoint = await api.getRPCEndpointFrom({ net }, api.neoscan);
const endpoint = await getRPCEndpoint(net);
const input = encodeInput ? encode(key) : key;
const { result } = await rpc.Query.getStorage(scriptHash, input).execute(endpoint);

Expand Down

0 comments on commit 504b815

Please sign in to comment.