diff --git a/ios/TempleWallet/Debug-Info.plist b/ios/TempleWallet/Debug-Info.plist
index f8e7827d3..78aa682a3 100644
--- a/ios/TempleWallet/Debug-Info.plist
+++ b/ios/TempleWallet/Debug-Info.plist
@@ -52,6 +52,14 @@
com.madfish.temple-wallet
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.14863818751-1seoo2foi73kbog7okgo6joffpacrp8q
+
+
CFBundleVersion
$(CURRENT_PROJECT_VERSION)
diff --git a/package.json b/package.json
index a10cb1619..5854f376e 100644
--- a/package.json
+++ b/package.json
@@ -49,6 +49,7 @@
"@react-navigation/native": "6.1.8",
"@react-navigation/stack": "6.3.18",
"@reduxjs/toolkit": "^1.8.5",
+ "@robinbobin/react-native-google-drive-api-wrapper": "^1.2.3",
"@sentry/react-native": "5.9.1",
"@shopify/flash-list": "^1.6.1",
"@taquito/local-forging": "17.1.1",
diff --git a/src/utils/cloud-backup/google-drive.ts b/src/utils/cloud-backup/google-drive.ts
index 6c4a74cc4..5debd29c0 100644
--- a/src/utils/cloud-backup/google-drive.ts
+++ b/src/utils/cloud-backup/google-drive.ts
@@ -3,18 +3,15 @@
* See: https://github.com/react-native-google-signin/google-signin/blob/master/docs/android-guide.md
*/
import { GoogleSignin, statusCodes, NativeModuleError } from '@react-native-google-signin/google-signin';
-import RNCloudFs from 'react-native-cloud-fs';
-import * as RNFS from 'react-native-fs';
+import { GDrive, MimeTypes } from '@robinbobin/react-native-google-drive-api-wrapper';
import { isString } from 'src/utils/is-string';
-import { rejectOnTimeout } from 'src/utils/timeouts.util';
import { CLOUD_REQUEST_TIMEOUT, EncryptedBackupObject, buildAndEncryptBackup, parseBackup } from './common';
-const scope = 'hidden';
const filename = 'wallet-backup.json';
-export const isCloudAvailable = async () => Boolean(RNCloudFs);
+export const isCloudAvailable = async () => true;
export const requestSignInToCloud = async () => {
await ensureGooglePlayServicesAvailable();
@@ -50,10 +47,11 @@ export const requestSignInToCloud = async () => {
}
try {
- /* Syncing signed-in state to RNCloudFS */
- return await RNCloudFs.loginIfNeeded();
+ await buildGDrive();
+
+ return true;
} catch (error) {
- console.error('RNCloudFs.loginIfNeeded() error:', { error });
+ console.error(error);
throw new Error('Failed to sync sign-in status');
}
@@ -68,15 +66,18 @@ export const fetchCloudBackup = async (): Promise {
- console.error('RNCloudFs.getGoogleDriveDocument() error:', error);
+ const gDrive = await buildGDrive();
+ gDrive.fetchTimeout = CLOUD_REQUEST_TIMEOUT;
- throw new Error("Failed to read cloud. See if it's enabled");
- }),
- CLOUD_REQUEST_TIMEOUT,
- new Error('Reading cloud took too long')
- );
+ const encryptedBackup = await gDrive.files.getText(details.id).catch(error => {
+ console.error(error);
+
+ if (error?.name === 'AbortError') {
+ throw new Error('Reading cloud took too long');
+ }
+
+ throw new Error("Failed to read cloud. See if it's enabled");
+ });
return parseBackup(encryptedBackup);
};
@@ -84,24 +85,23 @@ export const fetchCloudBackup = async (): Promise {
const encryptedData = await buildAndEncryptBackup(mnemonic, password);
- const localPath = `${RNFS.DocumentDirectoryPath}/${filename}`;
+ const gDrive = await buildGDrive();
- await RNFS.writeFile(localPath, encryptedData, 'utf8');
+ const uploader = gDrive.files
+ .newMultipartUploader()
+ .setRequestBody({
+ name: filename,
+ parents: ['appDataFolder']
+ })
+ .setData(encryptedData, MimeTypes.JSON);
- const fileId = await RNCloudFs.copyToCloud({
- scope,
- targetPath: filename,
- mimeType: 'application/json',
- sourcePath: { path: localPath }
- })
- .catch(error => {
- console.error('RNCloudFs.copyToCloud() error:', error);
+ const details: FileDetails = await uploader.execute().catch(error => {
+ console.error(error);
- throw new Error('Failed to upload to cloud');
- })
- .finally(() => RNFS.unlink(localPath).catch(console.error));
+ throw new Error('Failed to upload to cloud');
+ });
- const fileExists = await checkIfBackupExists(fileId);
+ const fileExists = await checkIfBackupExists(details.id);
if (fileExists === false) {
throw new Error('File not found after saving');
@@ -117,11 +117,20 @@ const checkIfBackupExists = async (fileId?: string) => {
return false;
}
- return await RNCloudFs.fileExists({ scope, fileId }).catch(error => {
- console.error('RNCloudFs.fileExists() error:', error);
+ const gDrive = await buildGDrive();
- return false;
- });
+ return await gDrive.files.getMetadata(fileId).then(
+ info => {
+ console.log('Backup file metadata:', info);
+
+ return true;
+ },
+ error => {
+ console.error(error);
+
+ return false;
+ }
+ );
};
const ensureGooglePlayServicesAvailable = async () => {
@@ -139,8 +148,6 @@ const ensureGooglePlayServicesAvailable = async () => {
const preLogOut = async () => {
try {
await GoogleSignin.signOut();
- /* Syncing signed-in state to RNCloudFS */
- await RNCloudFs.logout();
} catch (error) {
console.error('preLogOut() error:', { error });
@@ -148,15 +155,33 @@ const preLogOut = async () => {
}
};
+interface FileDetails {
+ id: string;
+ name: string;
+ mimeType: string;
+ kind: string;
+}
+
const fetchCloudBackupDetails = async () => {
- const data = await RNCloudFs.listFiles<'Android'>({
- scope,
- targetPath: ''
- }).catch(error => {
- console.error("NCloudFs.listFiles<'Android'> error:", error);
+ const gDrive = await buildGDrive();
- throw error;
+ const data: { files: FileDetails[]; incompleteSearch: boolean } = await gDrive.files.list({
+ spaces: 'appDataFolder'
});
return data.files?.find(file => file.name.endsWith(filename));
};
+
+const buildGDrive = async () => {
+ const gDrive = new GDrive();
+
+ const accessInfo = await GoogleSignin.getTokens().catch(error => {
+ console.error(error);
+
+ throw new Error('First, sign-in to Google account');
+ });
+
+ gDrive.accessToken = accessInfo.accessToken;
+
+ return gDrive;
+};
diff --git a/src/utils/cloud-backup/index.ts b/src/utils/cloud-backup/index.ts
index 569392d2f..9e885a7bf 100644
--- a/src/utils/cloud-backup/index.ts
+++ b/src/utils/cloud-backup/index.ts
@@ -11,6 +11,7 @@ export { keepRestoredCloudBackup, useRestoredCloudBackup } from './keeper';
export const cloudTitle = isIOS ? 'iCloud' : 'Google Drive';
export const FAILED_TO_LOGIN_ERR_TITLE = isIOS ? 'Failed to sync cloud' : 'Failed to log-in';
+/** Keep it async for possible future needs */
export const isCloudAvailable = (): Promise =>
isIOS ? ICloudAPI.isCloudAvailable() : GoogleDriveAPI.isCloudAvailable();
diff --git a/yarn.lock b/yarn.lock
index c1ed049d1..8742bef42 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2962,6 +2962,15 @@
redux-thunk "^2.4.1"
reselect "^4.1.5"
+"@robinbobin/react-native-google-drive-api-wrapper@^1.2.3":
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/@robinbobin/react-native-google-drive-api-wrapper/-/react-native-google-drive-api-wrapper-1.2.3.tgz#c4cfbfb027785589d53841ab667078f69266988c"
+ integrity sha512-WCbkb9zzKIR4Wg5xmX33eDGkfDH6wS1LUhnGET/FNRpJiRC+Lnofnrk7JrrmXg7cLjjJ3J/HkW15bsp2CwbjjQ==
+ dependencies:
+ base64-js "^1.5.1"
+ simple-common-utils "^2.3.0"
+ utf8 "^3.0.0"
+
"@sentry-internal/tracing@7.63.0":
version "7.63.0"
resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.63.0.tgz#58903b2205456034611cc5bc1b5b2479275f89c7"
@@ -4859,7 +4868,7 @@ base16@^1.0.0:
resolved "https://registry.npmjs.org/base16/-/base16-1.0.0.tgz"
integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=
-base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.1:
+base64-js@^1.0.2, base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
@@ -10931,6 +10940,11 @@ signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+simple-common-utils@^2.3.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/simple-common-utils/-/simple-common-utils-2.6.0.tgz#457f126c20c82ba10212427886f4c8ebe86cc6d7"
+ integrity sha512-K0gtyfMQ1+iDQvZKgdY2L+pbaG0MHp1ke6ho7IL6UKR8f59st+QJgw27FADF+3Hut19C3WUb7IhgENdY/OJG8w==
+
simple-concat@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"