From 238250f35d6e1a5492a392d48eb5da984ada3138 Mon Sep 17 00:00:00 2001
From: Alex Barnsley <8069294+alexbarnsley@users.noreply.github.com>
Date: Wed, 22 Sep 2021 10:21:12 +0100
Subject: [PATCH] refactor: core v3 upgrades (#705)

---
 .github/workflows/test.yml                    | 20 ------
 config.xml                                    |  5 +-
 package-lock.json                             | 22 ++++++-
 package.json                                  |  7 ++-
 src/app/app.module.ts                         |  2 +
 .../custom-network-create.ts                  | 13 ++--
 src/app/models/market.ts                      |  6 +-
 src/app/services/ark-api/ark-api.ts           |  8 +--
 src/app/services/neo-api/neo-api.ts           |  2 +-
 src/app/utils/ark-client.ts                   | 30 ++++++---
 src/app/utils/ark-http-client.ts              | 61 +++++++++++++++++++
 src/app/utils/ark-peer-discovery.ts           | 16 ++---
 12 files changed, 137 insertions(+), 55 deletions(-)
 create mode 100644 src/app/utils/ark-http-client.ts

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index deeeea21c..4bd28f73d 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -29,23 +29,3 @@ jobs:
         run: npm run build -- --prod
       - name: Codecov
         run: ./node_modules/.bin/codecov --token=${{ secrets.CODECOV_TOKEN }}
-
-  e2e:
-    runs-on: ubuntu-latest
-
-    strategy:
-      matrix:
-        node-version: [12.x]
-
-    steps:
-      - uses: actions/checkout@v1
-      - name: Use Node.js ${{ matrix.node-version }}
-        uses: actions/setup-node@v1
-        with:
-          node-version: ${{ matrix.node-version }}
-      - name: Install
-        run: npm install --ignore-scripts
-      - name: Pre Test
-        run: npx webdriver-manager update --versions.chrome=85.0.4183.83
-      - name: Test
-        run: npm run test:e2e -- --prod --webdriver-update false
diff --git a/config.xml b/config.xml
index a498ed79f..c822636ec 100644
--- a/config.xml
+++ b/config.xml
@@ -1,5 +1,5 @@
 <?xml version='1.0' encoding='utf-8'?>
-<widget id="io.ark.wallet.mobile" version="1.8.6" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
+<widget id="io.ark.wallet.mobile" version="1.9.2" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
     <name>Ark Mobile</name>
     <description>ARK</description>
     <author email="mobile@ark.io" href="http://ark.io/">Ark Ecosystem</author>
@@ -30,6 +30,8 @@
     <preference name="Orientation" value="portrait" />
     <preference name="target-device" value="handset" />
     <preference name="DisableDeploy" value="true" />
+    <preference name="WKWebViewOnly" value="true" />
+    <preference name="AndroidPersistentFileLocation" value="Compatibility" />
     <platform name="android">
         <edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application" xmlns:android="http://schemas.android.com/apk/res/android">
             <application android:networkSecurityConfig="@xml/network_security_config" />
@@ -114,6 +116,7 @@
         <splash height="2436" src="resources/ios/splash/Default-2436h.png" width="1125" />
         <splash height="2732" src="resources/ios/splash/Default@2x~universal~anyany.png" width="2732" />
     </platform>
+    <plugin name="cordova-plugin-advanced-http" spec="^3.2.0" />
     <plugin name="cordova-plugin-whitelist" spec="1.3.3" />
     <plugin name="cordova-plugin-statusbar" spec="2.4.2" />
     <plugin name="cordova-plugin-device" spec="2.0.2" />
diff --git a/package-lock.json b/package-lock.json
index 8acc6d4ee..e577a8455 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
 	"name": "ark-mobile",
-	"version": "1.8.1",
+	"version": "1.9.2",
 	"lockfileVersion": 1,
 	"requires": true,
 	"dependencies": {
@@ -3445,6 +3445,21 @@
 				"@types/cordova": "^0.0.34"
 			}
 		},
+		"@ionic-native/http": {
+			"version": "5.36.0",
+			"resolved": "https://registry.npmjs.org/@ionic-native/http/-/http-5.36.0.tgz",
+			"integrity": "sha512-3t7UhcqNxZuIX+HXuydlaDfA9AwDXiRFGs9GsHpJnXMTfbeKUcwzp0amqblrLslDA9tNfqSmJyFZFaMX6CRrog==",
+			"requires": {
+				"@types/cordova": "^0.0.34"
+			},
+			"dependencies": {
+				"@types/cordova": {
+					"version": "0.0.34",
+					"resolved": "https://registry.npmjs.org/@types/cordova/-/cordova-0.0.34.tgz",
+					"integrity": "sha1-6nrd907Ow9dimCegw54smt3HPQQ="
+				}
+			}
+		},
 		"@ionic-native/in-app-browser": {
 			"version": "5.22.0",
 			"resolved": "https://registry.npmjs.org/@ionic-native/in-app-browser/-/in-app-browser-5.22.0.tgz",
@@ -9049,6 +9064,11 @@
 				}
 			}
 		},
+		"cordova-plugin-advanced-http": {
+			"version": "3.2.1",
+			"resolved": "https://registry.npmjs.org/cordova-plugin-advanced-http/-/cordova-plugin-advanced-http-3.2.1.tgz",
+			"integrity": "sha512-puQfmvGguo43Jf0dVtOjlNTpvdTA5NSCfnI+85LFzzcrZk/zpqawRQZbPS7c1A1Nmu+i+PWo3pP/YVOt586Ttw=="
+		},
 		"cordova-plugin-device": {
 			"version": "2.0.3",
 			"resolved": "https://registry.npmjs.org/cordova-plugin-device/-/cordova-plugin-device-2.0.3.tgz",
diff --git a/package.json b/package.json
index 46bd86535..3e8b98aa5 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "ark-mobile",
-	"version": "1.8.6",
+	"version": "1.9.2",
 	"author": "Ark Ecosystem <mobile@ark.io>",
 	"homepage": "https://github.com/ArkEcosystem/mobile-wallet#readme",
 	"scripts": {
@@ -36,6 +36,7 @@
 		"@ionic-native/background-mode": "^5.22.0",
 		"@ionic-native/clipboard": "^5.22.0",
 		"@ionic-native/core": "^5.22.0",
+		"@ionic-native/http": "^5.36.0",
 		"@ionic-native/in-app-browser": "^5.22.0",
 		"@ionic-native/keyboard": "^5.22.0",
 		"@ionic-native/local-notifications": "^5.22.0",
@@ -63,6 +64,7 @@
 		"cordova-custom-config": "^5.1.0",
 		"cordova-ios": "5.1.1",
 		"cordova-plugin-add-swift-support": "^2.0.2",
+		"cordova-plugin-advanced-http": "^3.2.1",
 		"cordova-plugin-device": "^2.0.3",
 		"cordova-plugin-inappbrowser": "^3.2.0",
 		"cordova-plugin-ionic": "^5.4.6",
@@ -170,6 +172,9 @@
 			"cordova-plugin-ionic-webview": {
 				"ANDROID_SUPPORT_ANNOTATIONS_VERSION": "27.+"
 			},
+			"cordova-plugin-advanced-http": {
+				"ANDROIDBLACKLISTSECURESOCKETPROTOCOLS": "SSLv3,TLSv1"
+			},
 			"cordova-plugin-ionic-keyboard": {},
 			"cordova-plugin-ionic": {
 				"APP_ID": "efb289f2",
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index a1af03175..0ef585ea9 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -3,6 +3,7 @@ import { ErrorHandler, NgModule } from "@angular/core";
 import { BrowserModule, HammerModule } from "@angular/platform-browser";
 import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
 import { RouteReuseStrategy } from "@angular/router";
+import { HTTP } from "@ionic-native/http/ngx";
 import { Keyboard } from "@ionic-native/keyboard/ngx";
 import { Network } from "@ionic-native/network/ngx";
 import { QRScanner } from "@ionic-native/qr-scanner/ngx";
@@ -54,6 +55,7 @@ export function createTranslateLoader(http: HttpClient) {
 		Network,
 		ScreenOrientation,
 		GlobalErrorHandlerService,
+		HTTP,
 		{ provide: UserDataService, useClass: UserDataServiceImpl },
 		{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
 		{ provide: ErrorHandler, useClass: GlobalErrorHandlerService },
diff --git a/src/app/modals/custom-network-create/custom-network-create.ts b/src/app/modals/custom-network-create/custom-network-create.ts
index f2ccaebe3..e6d18324a 100644
--- a/src/app/modals/custom-network-create/custom-network-create.ts
+++ b/src/app/modals/custom-network-create/custom-network-create.ts
@@ -1,13 +1,12 @@
-import { HttpClient } from "@angular/common/http";
 import { Component } from "@angular/core";
 import { LoadingController, ModalController } from "@ionic/angular";
 import { Network, Peer } from "ark-ts";
-import lodash from "lodash";
 import { finalize } from "rxjs/operators";
 
 import { LoggerService } from "@/services/logger/logger.service";
 import { ToastProvider } from "@/services/toast/toast";
 import ArkClient from "@/utils/ark-client";
+import { HttpClient } from "@/utils/ark-http-client";
 
 @Component({
 	selector: "customNetworkCreate",
@@ -50,19 +49,15 @@ export class CustomNetworkCreateModal {
 					this.network.version = response.version;
 					this.network.type = null;
 
-					const apiConfig: any = lodash.find(
-						response.ports,
-						(_, key) => key.split("/").reverse()[0] === "core-api",
-					);
-					if (!response.ports || !apiConfig) {
+					if (!response.ports || !seedServerUrl.port) {
 						this.configureError();
 						return;
 					}
-					this.network.apiPort = apiConfig;
+					this.network.apiPort = parseInt(seedServerUrl.port);
 
 					this.network.activePeer = new Peer();
 					this.network.activePeer.ip = seedServerUrl.hostname;
-					this.network.activePeer.port = apiConfig;
+					this.network.activePeer.port = parseInt(seedServerUrl.port);
 
 					if (seedServerUrl.protocol === "https:") {
 						this.network.activePeer.port = 443;
diff --git a/src/app/models/market.ts b/src/app/models/market.ts
index 07a78f5cd..d7e497cd9 100644
--- a/src/app/models/market.ts
+++ b/src/app/models/market.ts
@@ -221,7 +221,11 @@ export class MarketHistory {
 	getPriceByDate(currencyCode: string, date: Date): number {
 		const timestampDate = date.setHours(0, 0, 0, 0);
 
-		return this.history[currencyCode.toUpperCase()][timestampDate];
+		if (this.history[currencyCode.toUpperCase()]) {
+			return this.history[currencyCode.toUpperCase()][timestampDate];
+		}
+
+		return 0;
 	}
 
 	getLastWeekPrice(currencyCode: string): any {
diff --git a/src/app/services/ark-api/ark-api.ts b/src/app/services/ark-api/ark-api.ts
index 549768ef5..55e1a4bc6 100644
--- a/src/app/services/ark-api/ark-api.ts
+++ b/src/app/services/ark-api/ark-api.ts
@@ -1,4 +1,3 @@
-import { HttpClient } from "@angular/common/http";
 import { Injectable } from "@angular/core";
 import * as ArkCrypto from "@arkecosystem/crypto";
 import * as arkts from "ark-ts";
@@ -25,11 +24,12 @@ import { FeeStatistic, StoredNetwork } from "@/models/stored-network";
 import { StorageProvider } from "@/services/storage/storage";
 import { ToastProvider } from "@/services/toast/toast";
 import { UserDataService } from "@/services/user-data/user-data.interface";
+import ArkClient, { WalletResponse } from "@/utils/ark-client";
+import { HttpClient } from "@/utils/ark-http-client";
 import { PeerDiscovery } from "@/utils/ark-peer-discovery";
+import { ArkUtility } from "@/utils/ark-utility";
 import { SafeBigNumber as BigNumber } from "@/utils/bignumber";
 
-import ArkClient, { WalletResponse } from "../../utils/ark-client";
-import { ArkUtility } from "../../utils/ark-utility";
 import { LoggerService } from "../logger/logger.service";
 
 interface NodeFees {
@@ -574,7 +574,7 @@ export class ArkApiProvider {
 
 		return new Observable((observer) => {
 			this.httpClient
-				.get(`${this._network.getPeerAPIUrl()}/api/v2/node/fees?days=7`)
+				.get(`${this._network.getPeerAPIUrl()}/api/node/fees?days=7`)
 				.subscribe(
 					(response: NodeFeesResponse) => {
 						const data = response.data;
diff --git a/src/app/services/neo-api/neo-api.ts b/src/app/services/neo-api/neo-api.ts
index c819ea14a..b53adf421 100644
--- a/src/app/services/neo-api/neo-api.ts
+++ b/src/app/services/neo-api/neo-api.ts
@@ -1,9 +1,9 @@
-import { HttpClient } from "@angular/common/http";
 import { Injectable } from "@angular/core";
 import { Observable, of } from "rxjs";
 import { map } from "rxjs/operators";
 
 import { NetworkProvider } from "@/services/network/network";
+import { HttpClient } from "@/utils/ark-http-client";
 
 @Injectable({ providedIn: "root" })
 export class NeoApiProvider {
diff --git a/src/app/utils/ark-client.ts b/src/app/utils/ark-client.ts
index 00170474b..d8f1c05c8 100644
--- a/src/app/utils/ark-client.ts
+++ b/src/app/utils/ark-client.ts
@@ -1,4 +1,3 @@
-import { HttpClient } from "@angular/common/http";
 import {
 	AccountResponse,
 	AccountVotesResponse,
@@ -17,6 +16,7 @@ import { tap, timeout } from "rxjs/operators";
 import { TRANSACTION_GROUPS } from "@/app/app.constants";
 import { INodeConfiguration } from "@/models/node";
 import { LoggerService } from "@/services/logger/logger.service";
+import { HttpClient } from "@/utils/ark-http-client";
 
 export interface PeerApiResponse extends Peer {
 	latency?: number;
@@ -70,7 +70,8 @@ export default class ApiClient {
 					const data = response.data;
 
 					if (data.length) {
-						const lastVote = data[0].asset.votes[0];
+						const lastVote =
+							data[0].asset.votes[data[0].asset.votes.length - 1];
 
 						if (lastVote.charAt(0) === "-") {
 							observer.next({
@@ -80,9 +81,7 @@ export default class ApiClient {
 							observer.complete();
 						}
 
-						const delegatePublicKey = data[0].asset.votes[0].substring(
-							1,
-						);
+						const delegatePublicKey = lastVote.substring(1);
 						this.getDelegateByPublicKey(
 							delegatePublicKey,
 						).subscribe(
@@ -284,7 +283,24 @@ export default class ApiClient {
 					observer.next(this.__formatDelegateResponse(data));
 					observer.complete();
 				},
-				(error) => observer.error(error),
+				(error) => {
+					const response =
+						typeof error.error === "string"
+							? JSON.parse(error.error)
+							: error.error;
+					if (
+						response &&
+						error.status === 404 &&
+						response.message === "Delegate not found"
+					) {
+						observer.next(null);
+						observer.complete();
+
+						return;
+					}
+
+					observer.error(error);
+				},
 			);
 		});
 	}
@@ -322,7 +338,7 @@ export default class ApiClient {
 	) {
 		const url = `${host}/api/${path}`;
 		return this.httpClient
-			.request("GET", url, {
+			.get(url, {
 				...options,
 				headers: this.defaultHeaders,
 			})
diff --git a/src/app/utils/ark-http-client.ts b/src/app/utils/ark-http-client.ts
new file mode 100644
index 000000000..f39ab0eb8
--- /dev/null
+++ b/src/app/utils/ark-http-client.ts
@@ -0,0 +1,61 @@
+import { Injectable } from "@angular/core";
+import { HTTP } from "@ionic-native/http/ngx";
+import { from, Observable } from "rxjs";
+import { map } from "rxjs/operators";
+
+@Injectable({
+	providedIn: "root",
+})
+export class HttpClient {
+	private defaultHeaders: any = {
+		"Content-Type": "application/json",
+	};
+
+	constructor(private http: HTTP) {}
+
+	get<T>(url: string, options: any = {}): Observable<any> {
+		this.http.setDataSerializer("json");
+
+		return from(
+			this.http.get(
+				url,
+				{},
+				{ ...this.defaultHeaders, ...(options.headers || {}) },
+			),
+		).pipe(
+			map(function (result): any {
+				return JSON.parse(result.data);
+			}),
+		);
+	}
+
+	post<T>(url: string, body: any = {}, options: any = {}): Observable<any> {
+		this.http.setDataSerializer("json");
+
+		return from(
+			this.http.post(url, body, {
+				...this.defaultHeaders,
+				...(options.headers || {}),
+			}),
+		).pipe(
+			map(function (result): any {
+				return JSON.parse(result.data);
+			}),
+		);
+	}
+
+	put<T>(url: string, body: any = {}, options: any = {}): Observable<any> {
+		this.http.setDataSerializer("json");
+
+		return from(
+			this.http.put(url, body, {
+				...this.defaultHeaders,
+				...(options.headers || {}),
+			}),
+		).pipe(
+			map(function (result): any {
+				return JSON.parse(result.data);
+			}),
+		);
+	}
+}
diff --git a/src/app/utils/ark-peer-discovery.ts b/src/app/utils/ark-peer-discovery.ts
index 79a897a46..30306c416 100644
--- a/src/app/utils/ark-peer-discovery.ts
+++ b/src/app/utils/ark-peer-discovery.ts
@@ -1,10 +1,10 @@
-import { HttpClient } from "@angular/common/http";
 import isUrl from "is-url";
 import orderBy from "lodash/orderBy";
 import { Observable } from "rxjs/Observable";
 import semver from "semver";
 
-import { PeerApiResponse } from "./ark-client";
+import { PeerApiResponse } from "@/utils/ark-client";
+import { HttpClient } from "@/utils/ark-http-client";
 
 export class PeerDiscovery {
 	private version: string | undefined;
@@ -99,15 +99,11 @@ export class PeerDiscovery {
 				];
 
 				this.httpClient
-					.request(
-						"GET",
-						`http://${seed.ip}:${seed.port}/api/peers`,
-						{
-							headers: {
-								"API-Version": "2",
-							},
+					.get(`http://${seed.ip}:${seed.port}/api/peers`, {
+						headers: {
+							"API-Version": "2",
 						},
-					)
+					})
 					.subscribe(
 						(body: any) => {
 							let peers = body.data;