@dynamic-labs-wallet/browser 0.0.239 → 0.0.241
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.cjs.js +224 -204
- package/index.esm.js +220 -201
- package/package.json +2 -2
- package/src/backup/providers/iCloud.d.ts +0 -1
- package/src/backup/providers/iCloud.d.ts.map +1 -1
- package/src/client.d.ts +39 -12
- package/src/client.d.ts.map +1 -1
- package/src/types.d.ts +36 -15
- package/src/types.d.ts.map +1 -1
package/index.cjs.js
CHANGED
|
@@ -658,16 +658,6 @@ const downloadStringAsFile = ({ filename, content, mimeType = 'application/json'
|
|
|
658
658
|
URL.revokeObjectURL(url);
|
|
659
659
|
};
|
|
660
660
|
|
|
661
|
-
// CloudKit Web Services API token for public operations
|
|
662
|
-
// This token only allows access to the iCloud.KeyShareBackup container
|
|
663
|
-
// and is safe to include in client-side code
|
|
664
|
-
const DEFAULT_CONFIG = {
|
|
665
|
-
containerIdentifier: 'iCloud.KeyShareBackup',
|
|
666
|
-
// apiToken: '1221c5ccdf2ddb9abdb035befe7c197b07102972b30bbcbe363f6d722f3127a1', // prod
|
|
667
|
-
apiToken: '332a46c457183332f8d2a3d94d2ac87e9e9ae2af81d8a6d1ea89c27bb2fc0e97',
|
|
668
|
-
// environment: 'production',
|
|
669
|
-
environment: 'development'
|
|
670
|
-
};
|
|
671
661
|
const CLOUDKIT_CDN_URL = 'https://cdn.apple-cloudkit.com/ck/2/cloudkit.js';
|
|
672
662
|
const BACKUP_RECORD_TYPE = 'Backup';
|
|
673
663
|
let cloudKitLoaded = false;
|
|
@@ -703,7 +693,6 @@ const loadCloudKit = ()=>{
|
|
|
703
693
|
script.src = CLOUDKIT_CDN_URL;
|
|
704
694
|
script.onload = ()=>{
|
|
705
695
|
cloudKitLoaded = true;
|
|
706
|
-
logger.debug('[iCloud] CloudKit JS loaded successfully');
|
|
707
696
|
resolve();
|
|
708
697
|
};
|
|
709
698
|
script.onerror = (error)=>{
|
|
@@ -717,17 +706,16 @@ const configureCloudKit = (config, signInButtonId)=>{
|
|
|
717
706
|
if (cloudKitConfigured && currentSignInButtonId === signInButtonId) {
|
|
718
707
|
return;
|
|
719
708
|
}
|
|
720
|
-
|
|
709
|
+
if (!(config == null ? void 0 : config.containerIdentifier) || !(config == null ? void 0 : config.apiToken) || !(config == null ? void 0 : config.environment)) {
|
|
710
|
+
throw new Error('iCloud configuration is incomplete. Please configure iCloud settings in the dashboard.');
|
|
711
|
+
}
|
|
721
712
|
const containerConfig = {
|
|
722
|
-
containerIdentifier:
|
|
723
|
-
environment:
|
|
713
|
+
containerIdentifier: config.containerIdentifier,
|
|
714
|
+
environment: config.environment,
|
|
724
715
|
apiTokenAuth: {
|
|
725
|
-
apiToken:
|
|
716
|
+
apiToken: config.apiToken,
|
|
726
717
|
persist: true,
|
|
727
|
-
signInButton:
|
|
728
|
-
id: signInButtonId,
|
|
729
|
-
theme: 'black'
|
|
730
|
-
} : undefined
|
|
718
|
+
signInButton: undefined
|
|
731
719
|
}
|
|
732
720
|
};
|
|
733
721
|
CloudKit.configure({
|
|
@@ -736,16 +724,7 @@ const configureCloudKit = (config, signInButtonId)=>{
|
|
|
736
724
|
]
|
|
737
725
|
});
|
|
738
726
|
cloudKitConfigured = true;
|
|
739
|
-
currentSignInButtonId = signInButtonId || null;
|
|
740
|
-
logger.debug('[iCloud] CloudKit configured', {
|
|
741
|
-
containerIdentifier: mergedConfig.containerIdentifier,
|
|
742
|
-
environment: mergedConfig.environment
|
|
743
|
-
});
|
|
744
|
-
};
|
|
745
|
-
const resetCloudKitConfig = ()=>{
|
|
746
|
-
cloudKitConfigured = false;
|
|
747
727
|
currentSignInButtonId = null;
|
|
748
|
-
logger.debug('[iCloud] CloudKit config reset');
|
|
749
728
|
};
|
|
750
729
|
/**
|
|
751
730
|
* Check if user is already authenticated using fetchCurrentUserIdentity.
|
|
@@ -765,7 +744,6 @@ const resetCloudKitConfig = ()=>{
|
|
|
765
744
|
if (authenticationAbortController) {
|
|
766
745
|
authenticationAbortController.abort();
|
|
767
746
|
authenticationAbortController = null;
|
|
768
|
-
logger.info('[iCloud] Authentication cancelled by user');
|
|
769
747
|
}
|
|
770
748
|
};
|
|
771
749
|
const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatusUpdate, options)=>{
|
|
@@ -784,7 +762,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
784
762
|
// First, check if user is already authenticated (more reliable than setUpAuth)
|
|
785
763
|
const alreadyAuthenticated = await isUserAuthenticated(container);
|
|
786
764
|
if (alreadyAuthenticated) {
|
|
787
|
-
logger.info('[iCloud] User already authenticated');
|
|
788
765
|
onAuthStatusUpdate == null ? void 0 : onAuthStatusUpdate('Authenticated');
|
|
789
766
|
return;
|
|
790
767
|
}
|
|
@@ -793,12 +770,10 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
793
770
|
await container.setUpAuth();
|
|
794
771
|
// Double-check authentication after setUpAuth
|
|
795
772
|
if (await isUserAuthenticated(container)) {
|
|
796
|
-
logger.info('[iCloud] User authenticated after setUpAuth');
|
|
797
773
|
onAuthStatusUpdate == null ? void 0 : onAuthStatusUpdate('Authenticated');
|
|
798
774
|
return;
|
|
799
775
|
}
|
|
800
776
|
// User needs to sign in
|
|
801
|
-
logger.info('[iCloud] User authentication required');
|
|
802
777
|
onAuthStatusUpdate == null ? void 0 : onAuthStatusUpdate('Waiting for sign-in...');
|
|
803
778
|
if (onSignInRequired) ;
|
|
804
779
|
return new Promise((resolve, reject)=>{
|
|
@@ -829,7 +804,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
829
804
|
if (await isUserAuthenticated(container)) {
|
|
830
805
|
resolved = true;
|
|
831
806
|
cleanup();
|
|
832
|
-
logger.info('[iCloud] Authentication successful');
|
|
833
807
|
onAuthStatusUpdate == null ? void 0 : onAuthStatusUpdate('Authenticated');
|
|
834
808
|
if (onSignInComplete) ;
|
|
835
809
|
resolve();
|
|
@@ -843,7 +817,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
843
817
|
resolved = true;
|
|
844
818
|
cleanup();
|
|
845
819
|
if (onSignInComplete) ;
|
|
846
|
-
logger.warn('[iCloud] Authentication timed out');
|
|
847
820
|
reject(new Error('iCloud sign-in timed out. Please ensure you are signed into iCloud ' + 'in your browser settings and try again. If the problem persists, ' + 'check your internet connection or try a different backup method.'));
|
|
848
821
|
}
|
|
849
822
|
}, timeoutMs);
|
|
@@ -859,7 +832,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
859
832
|
};
|
|
860
833
|
/**
|
|
861
834
|
* Save backup data to iCloud with retry logic
|
|
862
|
-
* Stores data in the same format as Google Drive for consistency
|
|
863
835
|
*/ const saveBackupToICloud = async (backupData, retryOptions)=>{
|
|
864
836
|
const { maxAttempts = 3, retryInterval = 1000 } = {};
|
|
865
837
|
return retryPromise(async ()=>{
|
|
@@ -868,16 +840,11 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
868
840
|
const record = {
|
|
869
841
|
recordType: BACKUP_RECORD_TYPE,
|
|
870
842
|
fields: {
|
|
871
|
-
// Store as JSON string to match Google Drive format
|
|
872
843
|
backupData: {
|
|
873
844
|
value: JSON.stringify(backupData)
|
|
874
|
-
},
|
|
875
|
-
timestamp: {
|
|
876
|
-
value: Date.now()
|
|
877
845
|
}
|
|
878
846
|
}
|
|
879
847
|
};
|
|
880
|
-
logger.debug('[iCloud] Saving backup record to CloudKit');
|
|
881
848
|
const response = await privateDB.saveRecords([
|
|
882
849
|
record
|
|
883
850
|
]);
|
|
@@ -887,9 +854,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
887
854
|
throw new Error(errorMessage);
|
|
888
855
|
}
|
|
889
856
|
const savedRecord = response.records[0];
|
|
890
|
-
logger.info('[iCloud] Backup saved successfully', {
|
|
891
|
-
recordName: savedRecord.recordName
|
|
892
|
-
});
|
|
893
857
|
return savedRecord;
|
|
894
858
|
}, {
|
|
895
859
|
maxAttempts,
|
|
@@ -904,12 +868,11 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
904
868
|
const container = CloudKit.getDefaultContainer();
|
|
905
869
|
const privateDB = container.privateCloudDatabase;
|
|
906
870
|
try {
|
|
907
|
-
logger.debug('[iCloud] Querying backup records');
|
|
908
871
|
const response = await privateDB.performQuery({
|
|
909
872
|
recordType: BACKUP_RECORD_TYPE,
|
|
910
873
|
sortBy: [
|
|
911
874
|
{
|
|
912
|
-
fieldName: '
|
|
875
|
+
fieldName: 'created',
|
|
913
876
|
ascending: false
|
|
914
877
|
}
|
|
915
878
|
]
|
|
@@ -931,9 +894,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
931
894
|
backupData: JSON.parse(fields.backupData.value)
|
|
932
895
|
};
|
|
933
896
|
});
|
|
934
|
-
logger.info('[iCloud] Found backups', {
|
|
935
|
-
count: records.length
|
|
936
|
-
});
|
|
937
897
|
return records;
|
|
938
898
|
} catch (error) {
|
|
939
899
|
logger.error('[iCloud] Failed to list backups:', error);
|
|
@@ -947,9 +907,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
947
907
|
const privateDB = container.privateCloudDatabase;
|
|
948
908
|
try {
|
|
949
909
|
var _fields_backupData;
|
|
950
|
-
logger.debug('[iCloud] Fetching backup record', {
|
|
951
|
-
recordName
|
|
952
|
-
});
|
|
953
910
|
const response = await privateDB.fetchRecords([
|
|
954
911
|
recordName
|
|
955
912
|
]);
|
|
@@ -959,9 +916,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
959
916
|
}
|
|
960
917
|
const record = response.records[0];
|
|
961
918
|
if (!record) {
|
|
962
|
-
logger.warn('[iCloud] Backup record not found', {
|
|
963
|
-
recordName
|
|
964
|
-
});
|
|
965
919
|
return null;
|
|
966
920
|
}
|
|
967
921
|
const fields = record.fields;
|
|
@@ -974,9 +928,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
974
928
|
modified: record.modified.timestamp,
|
|
975
929
|
backupData: JSON.parse(fields.backupData.value)
|
|
976
930
|
};
|
|
977
|
-
logger.info('[iCloud] Backup retrieved successfully', {
|
|
978
|
-
recordName
|
|
979
|
-
});
|
|
980
931
|
return backupRecord;
|
|
981
932
|
} catch (error) {
|
|
982
933
|
logger.error('[iCloud] Failed to get backup:', error);
|
|
@@ -989,9 +940,6 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
989
940
|
const container = CloudKit.getDefaultContainer();
|
|
990
941
|
const privateDB = container.privateCloudDatabase;
|
|
991
942
|
try {
|
|
992
|
-
logger.debug('[iCloud] Deleting backup record', {
|
|
993
|
-
recordName
|
|
994
|
-
});
|
|
995
943
|
const response = await privateDB.deleteRecords([
|
|
996
944
|
recordName
|
|
997
945
|
]);
|
|
@@ -999,20 +947,13 @@ const ensureICloudAuth = async (onSignInRequired, onSignInComplete, onAuthStatus
|
|
|
999
947
|
logger.error('[iCloud] Delete error:', response.errors);
|
|
1000
948
|
throw new Error(mapCloudKitError(response.errors[0]));
|
|
1001
949
|
}
|
|
1002
|
-
logger.info('[iCloud] Backup deleted successfully', {
|
|
1003
|
-
recordName
|
|
1004
|
-
});
|
|
1005
950
|
} catch (error) {
|
|
1006
951
|
logger.error('[iCloud] Failed to delete backup:', error);
|
|
1007
952
|
throw error;
|
|
1008
953
|
}
|
|
1009
954
|
};
|
|
1010
955
|
const initializeCloudKit = async (config, signInButtonId, onSignInRequired, onSignInComplete, onAuthStatusUpdate, authOptions)=>{
|
|
1011
|
-
logger.info('[iCloud] Initializing CloudKit');
|
|
1012
956
|
await loadCloudKit();
|
|
1013
|
-
if (signInButtonId) {
|
|
1014
|
-
resetCloudKitConfig();
|
|
1015
|
-
}
|
|
1016
957
|
configureCloudKit(config, signInButtonId);
|
|
1017
958
|
await ensureICloudAuth(onSignInRequired, onSignInComplete, onAuthStatusUpdate);
|
|
1018
959
|
};
|
|
@@ -1217,42 +1158,82 @@ class WalletBusyError extends Error {
|
|
|
1217
1158
|
this.accountAddress = accountAddress;
|
|
1218
1159
|
}
|
|
1219
1160
|
}
|
|
1220
|
-
|
|
1161
|
+
/**
|
|
1162
|
+
* Creates distribution where shares go to specified cloud providers
|
|
1163
|
+
* Last share goes to cloud providers, rest to Dynamic backend
|
|
1164
|
+
* @param providers - Array of cloud providers to backup to
|
|
1165
|
+
* @param allShares - All key shares to distribute
|
|
1166
|
+
*/ const createCloudProviderDistribution = ({ providers, allShares })=>{
|
|
1167
|
+
const cloudProviderShares = {};
|
|
1168
|
+
// Last share goes to cloud providers, rest to Dynamic
|
|
1169
|
+
const sharesForCloud = allShares.slice(-1);
|
|
1170
|
+
providers.forEach((provider)=>{
|
|
1171
|
+
cloudProviderShares[provider] = sharesForCloud;
|
|
1172
|
+
});
|
|
1173
|
+
return {
|
|
1174
|
+
clientShares: allShares.slice(0, -1),
|
|
1175
|
+
cloudProviderShares
|
|
1176
|
+
};
|
|
1177
|
+
};
|
|
1178
|
+
/**
|
|
1179
|
+
* Creates distribution with delegation + cloud backup
|
|
1180
|
+
* Client shares backed up to Dynamic AND cloud providers
|
|
1181
|
+
* Delegated share goes to webhook
|
|
1182
|
+
*/ const createDelegationWithCloudProviderDistribution = ({ providers, existingShares, delegatedShare })=>{
|
|
1183
|
+
const cloudProviderShares = {};
|
|
1184
|
+
providers.forEach((provider)=>{
|
|
1185
|
+
cloudProviderShares[provider] = existingShares;
|
|
1186
|
+
});
|
|
1187
|
+
return {
|
|
1221
1188
|
clientShares: existingShares,
|
|
1222
|
-
|
|
1189
|
+
cloudProviderShares,
|
|
1223
1190
|
delegatedShare
|
|
1191
|
+
};
|
|
1192
|
+
};
|
|
1193
|
+
/**
|
|
1194
|
+
* Creates distribution for adding cloud backup to existing delegation
|
|
1195
|
+
* Client shares go to both Dynamic AND cloud providers
|
|
1196
|
+
* delegatedShare is undefined - we don't re-publish, but preserve the location
|
|
1197
|
+
*/ const createAddCloudProviderToExistingDelegationDistribution = ({ providers, clientShares })=>{
|
|
1198
|
+
const cloudProviderShares = {};
|
|
1199
|
+
providers.forEach((provider)=>{
|
|
1200
|
+
cloudProviderShares[provider] = clientShares;
|
|
1224
1201
|
});
|
|
1202
|
+
return {
|
|
1203
|
+
clientShares,
|
|
1204
|
+
cloudProviderShares
|
|
1205
|
+
};
|
|
1206
|
+
};
|
|
1207
|
+
/**
|
|
1208
|
+
* Checks if wallet has backup on any of the specified providers
|
|
1209
|
+
*/ const hasCloudProviderBackup = (backupInfo, providers)=>{
|
|
1210
|
+
if (!(backupInfo == null ? void 0 : backupInfo.backups)) return false;
|
|
1211
|
+
return providers.some((provider)=>{
|
|
1212
|
+
var _backupInfo_backups_provider;
|
|
1213
|
+
var _backupInfo_backups_provider_length;
|
|
1214
|
+
return ((_backupInfo_backups_provider_length = (_backupInfo_backups_provider = backupInfo.backups[provider]) == null ? void 0 : _backupInfo_backups_provider.length) != null ? _backupInfo_backups_provider_length : 0) > 0;
|
|
1215
|
+
});
|
|
1216
|
+
};
|
|
1217
|
+
/**
|
|
1218
|
+
* Gets all cloud providers that have backups for this wallet
|
|
1219
|
+
*/ const getActiveCloudProviders = (backupInfo)=>{
|
|
1220
|
+
if (!(backupInfo == null ? void 0 : backupInfo.backups)) return [];
|
|
1221
|
+
return Object.entries(backupInfo.backups).filter(([location, backups])=>location !== core.BackupLocation.DYNAMIC && location !== core.BackupLocation.DELEGATED && backups.length > 0).map(([location])=>location);
|
|
1222
|
+
};
|
|
1225
1223
|
const createDelegationOnlyDistribution = ({ existingShares, delegatedShare })=>({
|
|
1226
1224
|
clientShares: existingShares,
|
|
1227
|
-
|
|
1225
|
+
cloudProviderShares: {},
|
|
1228
1226
|
delegatedShare
|
|
1229
1227
|
});
|
|
1230
|
-
const createGoogleDriveOnlyDistribution = ({ allShares })=>({
|
|
1231
|
-
clientShares: allShares.slice(0, -1),
|
|
1232
|
-
googleDriveShares: allShares.slice(-1)
|
|
1233
|
-
});
|
|
1234
1228
|
const createDynamicOnlyDistribution = ({ allShares })=>({
|
|
1235
1229
|
clientShares: allShares,
|
|
1236
|
-
|
|
1230
|
+
cloudProviderShares: {}
|
|
1237
1231
|
});
|
|
1238
|
-
const hasGoogleDriveBackup = (backupInfo)=>{
|
|
1239
|
-
var _backupInfo_backups_BackupLocation_GOOGLE_DRIVE, _backupInfo_backups;
|
|
1240
|
-
var _backupInfo_backups_BackupLocation_GOOGLE_DRIVE_length;
|
|
1241
|
-
return ((_backupInfo_backups_BackupLocation_GOOGLE_DRIVE_length = backupInfo == null ? void 0 : (_backupInfo_backups = backupInfo.backups) == null ? void 0 : (_backupInfo_backups_BackupLocation_GOOGLE_DRIVE = _backupInfo_backups[core.BackupLocation.GOOGLE_DRIVE]) == null ? void 0 : _backupInfo_backups_BackupLocation_GOOGLE_DRIVE.length) != null ? _backupInfo_backups_BackupLocation_GOOGLE_DRIVE_length : 0) > 0;
|
|
1242
|
-
};
|
|
1243
1232
|
const hasDelegatedBackup = (backupInfo)=>{
|
|
1244
1233
|
var _backupInfo_backups_BackupLocation_DELEGATED, _backupInfo_backups;
|
|
1245
1234
|
var _backupInfo_backups_BackupLocation_DELEGATED_length;
|
|
1246
1235
|
return ((_backupInfo_backups_BackupLocation_DELEGATED_length = backupInfo == null ? void 0 : (_backupInfo_backups = backupInfo.backups) == null ? void 0 : (_backupInfo_backups_BackupLocation_DELEGATED = _backupInfo_backups[core.BackupLocation.DELEGATED]) == null ? void 0 : _backupInfo_backups_BackupLocation_DELEGATED.length) != null ? _backupInfo_backups_BackupLocation_DELEGATED_length : 0) > 0;
|
|
1247
1236
|
};
|
|
1248
|
-
/**
|
|
1249
|
-
* Distribution for adding Google Drive backup to an existing delegation.
|
|
1250
|
-
* Client's shares go to both Dynamic and Google Drive.
|
|
1251
|
-
* delegatedShare is undefined - we don't re-publish, but preserve the location.
|
|
1252
|
-
*/ const createAddGoogleDriveToExistingDelegationDistribution = ({ clientShares })=>({
|
|
1253
|
-
clientShares: clientShares,
|
|
1254
|
-
googleDriveShares: clientShares
|
|
1255
|
-
});
|
|
1256
1237
|
|
|
1257
1238
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
1258
1239
|
class DynamicWalletClient {
|
|
@@ -2021,7 +2002,7 @@ class DynamicWalletClient {
|
|
|
2021
2002
|
existingClientKeyShares
|
|
2022
2003
|
};
|
|
2023
2004
|
}
|
|
2024
|
-
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, signedSessionId,
|
|
2005
|
+
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, signedSessionId, cloudProviders = [], delegateToProjectEnvironment = false, mfaToken, revokeDelegation = false }) {
|
|
2025
2006
|
return this.withWalletBusyLock({
|
|
2026
2007
|
accountAddress,
|
|
2027
2008
|
operation: core.WalletOperation.RESHARE,
|
|
@@ -2032,14 +2013,14 @@ class DynamicWalletClient {
|
|
|
2032
2013
|
newThresholdSignatureScheme,
|
|
2033
2014
|
password,
|
|
2034
2015
|
signedSessionId,
|
|
2035
|
-
|
|
2016
|
+
cloudProviders,
|
|
2036
2017
|
delegateToProjectEnvironment,
|
|
2037
2018
|
mfaToken,
|
|
2038
2019
|
revokeDelegation
|
|
2039
2020
|
})
|
|
2040
2021
|
});
|
|
2041
2022
|
}
|
|
2042
|
-
async internalReshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, signedSessionId,
|
|
2023
|
+
async internalReshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined, signedSessionId, cloudProviders = [], delegateToProjectEnvironment = false, mfaToken, revokeDelegation = false }) {
|
|
2043
2024
|
const dynamicRequestId = uuid.v4();
|
|
2044
2025
|
try {
|
|
2045
2026
|
await this.verifyPassword({
|
|
@@ -2106,28 +2087,31 @@ class DynamicWalletClient {
|
|
|
2106
2087
|
...newReshareResults
|
|
2107
2088
|
];
|
|
2108
2089
|
let distribution;
|
|
2109
|
-
|
|
2110
|
-
|
|
2090
|
+
// Generic distribution logic - works with any cloud providers
|
|
2091
|
+
if (delegateToProjectEnvironment && cloudProviders.length > 0) {
|
|
2092
|
+
// Delegation + Cloud Providers: Client's existing share backs up to both Dynamic and cloud providers.
|
|
2111
2093
|
// The new share goes to the webhook for delegation.
|
|
2112
|
-
distribution =
|
|
2094
|
+
distribution = createDelegationWithCloudProviderDistribution({
|
|
2095
|
+
providers: cloudProviders,
|
|
2113
2096
|
existingShares: existingReshareResults,
|
|
2114
2097
|
delegatedShare: newReshareResults[0]
|
|
2115
2098
|
});
|
|
2116
2099
|
} else if (delegateToProjectEnvironment) {
|
|
2117
2100
|
// Delegation only: Client's existing share backs up to Dynamic.
|
|
2118
|
-
// The new share goes to the webhook for delegation. No
|
|
2101
|
+
// The new share goes to the webhook for delegation. No cloud provider backup.
|
|
2119
2102
|
distribution = createDelegationOnlyDistribution({
|
|
2120
2103
|
existingShares: existingReshareResults,
|
|
2121
2104
|
delegatedShare: newReshareResults[0]
|
|
2122
2105
|
});
|
|
2123
|
-
} else if (
|
|
2124
|
-
//
|
|
2125
|
-
// The last share (new share) goes to
|
|
2126
|
-
distribution =
|
|
2106
|
+
} else if (cloudProviders.length > 0) {
|
|
2107
|
+
// Cloud Providers only: Split shares between Dynamic (N-1) and cloud providers (1).
|
|
2108
|
+
// The last share (new share) goes to cloud providers.
|
|
2109
|
+
distribution = createCloudProviderDistribution({
|
|
2110
|
+
providers: cloudProviders,
|
|
2127
2111
|
allShares: allClientShares
|
|
2128
2112
|
});
|
|
2129
2113
|
} else {
|
|
2130
|
-
// No delegation, no
|
|
2114
|
+
// No delegation, no cloud providers: All shares go to Dynamic backend only.
|
|
2131
2115
|
distribution = createDynamicOnlyDistribution({
|
|
2132
2116
|
allShares: allClientShares
|
|
2133
2117
|
});
|
|
@@ -2155,7 +2139,7 @@ class DynamicWalletClient {
|
|
|
2155
2139
|
chainName,
|
|
2156
2140
|
oldThresholdSignatureScheme,
|
|
2157
2141
|
newThresholdSignatureScheme,
|
|
2158
|
-
|
|
2142
|
+
cloudProviders,
|
|
2159
2143
|
dynamicRequestId
|
|
2160
2144
|
}
|
|
2161
2145
|
});
|
|
@@ -2188,6 +2172,8 @@ class DynamicWalletClient {
|
|
|
2188
2172
|
throw new Error('Delegation is not allowed for SUI');
|
|
2189
2173
|
}
|
|
2190
2174
|
const currentThresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
2175
|
+
// Get active cloud providers to maintain existing backups
|
|
2176
|
+
const activeProviders = getActiveCloudProviders((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.clientKeySharesBackupInfo);
|
|
2191
2177
|
await this.reshare({
|
|
2192
2178
|
chainName: this.walletMap[accountAddress].chainName,
|
|
2193
2179
|
accountAddress,
|
|
@@ -2195,7 +2181,7 @@ class DynamicWalletClient {
|
|
|
2195
2181
|
newThresholdSignatureScheme,
|
|
2196
2182
|
password,
|
|
2197
2183
|
signedSessionId,
|
|
2198
|
-
|
|
2184
|
+
cloudProviders: activeProviders,
|
|
2199
2185
|
delegateToProjectEnvironment: true,
|
|
2200
2186
|
mfaToken,
|
|
2201
2187
|
revokeDelegation
|
|
@@ -2494,17 +2480,21 @@ class DynamicWalletClient {
|
|
|
2494
2480
|
externalKeyShareId: data.keyShareIds[0]
|
|
2495
2481
|
});
|
|
2496
2482
|
}
|
|
2497
|
-
|
|
2498
|
-
|
|
2483
|
+
// Handle all cloud provider backups generically
|
|
2484
|
+
for (const [provider, shares] of Object.entries(distribution.cloudProviderShares)){
|
|
2485
|
+
if (!shares || shares.length === 0) continue;
|
|
2486
|
+
const backupLocation = provider;
|
|
2487
|
+
const encryptedCloudShares = await Promise.all(shares.map((keyShare)=>this.encryptKeyShare({
|
|
2499
2488
|
keyShare,
|
|
2500
2489
|
password
|
|
2501
2490
|
})));
|
|
2502
|
-
await this.
|
|
2491
|
+
await this.uploadToCloudProvider({
|
|
2492
|
+
provider: backupLocation,
|
|
2503
2493
|
accountAddress,
|
|
2504
|
-
encryptedKeyShares:
|
|
2494
|
+
encryptedKeyShares: encryptedCloudShares
|
|
2505
2495
|
});
|
|
2506
2496
|
locations.push({
|
|
2507
|
-
location:
|
|
2497
|
+
location: backupLocation
|
|
2508
2498
|
});
|
|
2509
2499
|
}
|
|
2510
2500
|
if (distribution.delegatedShare) {
|
|
@@ -2601,44 +2591,52 @@ class DynamicWalletClient {
|
|
|
2601
2591
|
* @param params.signedSessionId - Optional signed session ID for authentication
|
|
2602
2592
|
* @param params.backupToGoogleDrive - Whether to backup to Google Drive (defaults to false)
|
|
2603
2593
|
* @returns Promise with backup metadata including share locations and IDs
|
|
2604
|
-
*/ async storeEncryptedBackupByWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId,
|
|
2594
|
+
*/ async storeEncryptedBackupByWallet({ accountAddress, clientKeyShares = undefined, password = undefined, signedSessionId, cloudProviders = [], delegatedKeyshare = undefined }) {
|
|
2605
2595
|
var _this_walletMap_accountAddress, _this_walletMap_accountAddress1;
|
|
2606
2596
|
const keySharesToBackup = clientKeyShares != null ? clientKeyShares : await this.getClientKeySharesFromLocalStorage({
|
|
2607
2597
|
accountAddress
|
|
2608
2598
|
});
|
|
2609
|
-
|
|
2599
|
+
// Check if we should backup to cloud providers (either requested or already exists)
|
|
2600
|
+
const activeCloudProviders = getActiveCloudProviders((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress.clientKeySharesBackupInfo);
|
|
2601
|
+
const shouldBackupToCloudProviders = cloudProviders.length > 0 || activeCloudProviders.length > 0;
|
|
2602
|
+
// Use requested providers, or fall back to existing active providers
|
|
2603
|
+
const providersToBackup = cloudProviders.length > 0 ? cloudProviders : activeCloudProviders;
|
|
2610
2604
|
const hasExistingDelegation = hasDelegatedBackup((_this_walletMap_accountAddress1 = this.walletMap[accountAddress]) == null ? void 0 : _this_walletMap_accountAddress1.clientKeySharesBackupInfo);
|
|
2611
2605
|
let distribution;
|
|
2612
2606
|
let preserveDelegatedLocation = false;
|
|
2613
|
-
|
|
2614
|
-
|
|
2607
|
+
// Generic distribution logic - works with any cloud providers
|
|
2608
|
+
if (delegatedKeyshare && shouldBackupToCloudProviders) {
|
|
2609
|
+
// NEW delegation + Cloud Providers: Client's shares back up to both Dynamic and cloud providers.
|
|
2615
2610
|
// The delegated share goes to the webhook.
|
|
2616
|
-
distribution =
|
|
2611
|
+
distribution = createDelegationWithCloudProviderDistribution({
|
|
2612
|
+
providers: providersToBackup,
|
|
2617
2613
|
existingShares: keySharesToBackup,
|
|
2618
2614
|
delegatedShare: delegatedKeyshare
|
|
2619
2615
|
});
|
|
2620
2616
|
} else if (delegatedKeyshare) {
|
|
2621
2617
|
// NEW delegation only: Client's shares back up to Dynamic.
|
|
2622
|
-
// The delegated share goes to the webhook. No
|
|
2618
|
+
// The delegated share goes to the webhook. No cloud provider backup.
|
|
2623
2619
|
distribution = createDelegationOnlyDistribution({
|
|
2624
2620
|
existingShares: keySharesToBackup,
|
|
2625
2621
|
delegatedShare: delegatedKeyshare
|
|
2626
2622
|
});
|
|
2627
|
-
} else if (hasExistingDelegation &&
|
|
2628
|
-
// ADD
|
|
2623
|
+
} else if (hasExistingDelegation && shouldBackupToCloudProviders) {
|
|
2624
|
+
// ADD Cloud Providers to EXISTING delegation: Client's share backs up to both Dynamic and cloud providers.
|
|
2629
2625
|
// Don't re-publish delegated share, just preserve the location.
|
|
2630
|
-
distribution =
|
|
2626
|
+
distribution = createAddCloudProviderToExistingDelegationDistribution({
|
|
2627
|
+
providers: providersToBackup,
|
|
2631
2628
|
clientShares: keySharesToBackup
|
|
2632
2629
|
});
|
|
2633
2630
|
preserveDelegatedLocation = true;
|
|
2634
|
-
} else if (
|
|
2635
|
-
//
|
|
2636
|
-
// The last share (new share) goes to
|
|
2637
|
-
distribution =
|
|
2631
|
+
} else if (shouldBackupToCloudProviders && keySharesToBackup.length >= 2) {
|
|
2632
|
+
// Cloud Providers only (no delegation): Split shares between Dynamic (N-1) and cloud providers (1).
|
|
2633
|
+
// The last share (new share) goes to cloud providers.
|
|
2634
|
+
distribution = createCloudProviderDistribution({
|
|
2635
|
+
providers: providersToBackup,
|
|
2638
2636
|
allShares: keySharesToBackup
|
|
2639
2637
|
});
|
|
2640
2638
|
} else {
|
|
2641
|
-
// No delegation, no
|
|
2639
|
+
// No delegation, no cloud providers: All shares go to Dynamic backend only.
|
|
2642
2640
|
distribution = createDynamicOnlyDistribution({
|
|
2643
2641
|
allShares: keySharesToBackup
|
|
2644
2642
|
});
|
|
@@ -2807,16 +2805,10 @@ class DynamicWalletClient {
|
|
|
2807
2805
|
this.walletMap = JSON.parse(wallets);
|
|
2808
2806
|
}
|
|
2809
2807
|
/**
|
|
2810
|
-
*
|
|
2811
|
-
* - For 2-of-2 wallets: Automatically reshares to 2-of-3 threshold, then distributes shares (1 to backend, 1 to
|
|
2812
|
-
* - For 2-of-3 wallets: Call storeEncryptedBackupByWallet to backup for backend and
|
|
2813
|
-
|
|
2814
|
-
* @param params - The backup parameters
|
|
2815
|
-
* @param params.accountAddress - The wallet account address to backup
|
|
2816
|
-
* @param params.password - Optional password for encryption (uses environment ID if not provided)
|
|
2817
|
-
* @param params.signedSessionId - Optional signed session ID for authentication
|
|
2818
|
-
* @returns Promise<string[]> - Array of Google Drive key share IDs that were backed up
|
|
2819
|
-
*/ async backupKeySharesToGoogleDrive({ accountAddress, password, signedSessionId }) {
|
|
2808
|
+
* Internal helper method that handles the complete flow for ensuring wallet key shares are backed up to a cloud provider.
|
|
2809
|
+
* - For 2-of-2 wallets: Automatically reshares to 2-of-3 threshold, then distributes shares (1 to backend, 1 to cloud)
|
|
2810
|
+
* - For 2-of-3 wallets: Call storeEncryptedBackupByWallet to backup for backend and cloud
|
|
2811
|
+
*/ async backupKeySharesToCloudProvider({ accountAddress, password, signedSessionId, backupLocation }) {
|
|
2820
2812
|
try {
|
|
2821
2813
|
await this.getWallet({
|
|
2822
2814
|
accountAddress,
|
|
@@ -2834,93 +2826,86 @@ class DynamicWalletClient {
|
|
|
2834
2826
|
newThresholdSignatureScheme: core.ThresholdSignatureScheme.TWO_OF_THREE,
|
|
2835
2827
|
password,
|
|
2836
2828
|
signedSessionId,
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
const googleDriveShares = backupInfo.backups[core.BackupLocation.GOOGLE_DRIVE] || [];
|
|
2841
|
-
return googleDriveShares.map((ks)=>{
|
|
2842
|
-
var _ks_externalKeyShareId;
|
|
2843
|
-
return (_ks_externalKeyShareId = ks.externalKeyShareId) != null ? _ks_externalKeyShareId : '';
|
|
2829
|
+
cloudProviders: [
|
|
2830
|
+
backupLocation
|
|
2831
|
+
]
|
|
2844
2832
|
});
|
|
2845
2833
|
} else {
|
|
2846
2834
|
await this.storeEncryptedBackupByWallet({
|
|
2847
2835
|
accountAddress,
|
|
2848
2836
|
password,
|
|
2849
2837
|
signedSessionId,
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
const googleDriveShares = backupInfo.backups[core.BackupLocation.GOOGLE_DRIVE] || [];
|
|
2854
|
-
return googleDriveShares.map((ks)=>{
|
|
2855
|
-
var _ks_externalKeyShareId;
|
|
2856
|
-
return (_ks_externalKeyShareId = ks.externalKeyShareId) != null ? _ks_externalKeyShareId : '';
|
|
2838
|
+
cloudProviders: [
|
|
2839
|
+
backupLocation
|
|
2840
|
+
]
|
|
2857
2841
|
});
|
|
2858
2842
|
}
|
|
2859
2843
|
} catch (error) {
|
|
2860
2844
|
logError({
|
|
2861
|
-
message:
|
|
2845
|
+
message: `Error in backupKeySharesToCloudProvider (${backupLocation})`,
|
|
2862
2846
|
error: error,
|
|
2863
2847
|
context: {
|
|
2864
|
-
accountAddress
|
|
2848
|
+
accountAddress,
|
|
2849
|
+
backupLocation
|
|
2865
2850
|
}
|
|
2866
2851
|
});
|
|
2867
2852
|
throw error;
|
|
2868
2853
|
}
|
|
2869
2854
|
}
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
2884
|
-
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2855
|
+
/**
|
|
2856
|
+
* This method handles the complete flow for ensuring wallet key shares are backed up to Google Drive:
|
|
2857
|
+
* - For 2-of-2 wallets: Automatically reshares to 2-of-3 threshold, then distributes shares (1 to backend, 1 to Google Drive)
|
|
2858
|
+
* - For 2-of-3 wallets: Call storeEncryptedBackupByWallet to backup for backend and Google Drive
|
|
2859
|
+
*
|
|
2860
|
+
* @param params - The backup parameters
|
|
2861
|
+
* @param params.accountAddress - The wallet account address to backup
|
|
2862
|
+
* @param params.password - Optional password for encryption (uses environment ID if not provided)
|
|
2863
|
+
* @param params.signedSessionId - Optional signed session ID for authentication
|
|
2864
|
+
*/ async backupKeySharesToGoogleDrive({ accountAddress, password, signedSessionId }) {
|
|
2865
|
+
return this.backupKeySharesToCloudProvider({
|
|
2866
|
+
accountAddress,
|
|
2867
|
+
password,
|
|
2868
|
+
signedSessionId,
|
|
2869
|
+
backupLocation: core.BackupLocation.GOOGLE_DRIVE
|
|
2870
|
+
});
|
|
2871
|
+
}
|
|
2872
|
+
/**
|
|
2873
|
+
* This method handles the complete flow for ensuring wallet key shares are backed up to iCloud:
|
|
2874
|
+
* - For 2-of-2 wallets: Automatically reshares to 2-of-3 threshold, then distributes shares (1 to backend, 1 to iCloud)
|
|
2875
|
+
* - For 2-of-3 wallets: Call storeEncryptedBackupByWallet to backup for backend and iCloud
|
|
2876
|
+
*
|
|
2877
|
+
* @param params - The backup parameters
|
|
2878
|
+
* @param params.accountAddress - The wallet account address to backup
|
|
2879
|
+
* @param params.password - Optional password for encryption (uses environment ID if not provided)
|
|
2880
|
+
* @param params.signedSessionId - Optional signed session ID for authentication
|
|
2881
|
+
*/ async backupKeySharesToICloud({ accountAddress, password, signedSessionId }) {
|
|
2882
|
+
return this.backupKeySharesToCloudProvider({
|
|
2883
|
+
accountAddress,
|
|
2884
|
+
password,
|
|
2885
|
+
signedSessionId,
|
|
2886
|
+
backupLocation: core.BackupLocation.ICLOUD
|
|
2887
|
+
});
|
|
2888
|
+
}
|
|
2889
|
+
/**
|
|
2890
|
+
* Generic router method that uploads encrypted key shares to the specified cloud provider
|
|
2891
|
+
* @param provider - The cloud backup provider (GOOGLE_DRIVE, ICLOUD, etc.)
|
|
2892
|
+
* @param accountAddress - Wallet account address
|
|
2893
|
+
* @param encryptedKeyShares - Already encrypted key shares to upload
|
|
2894
|
+
* @returns Promise<void>
|
|
2895
|
+
*/ async uploadToCloudProvider({ provider, accountAddress, encryptedKeyShares }) {
|
|
2896
|
+
switch(provider){
|
|
2897
|
+
case core.BackupLocation.GOOGLE_DRIVE:
|
|
2898
|
+
return this.uploadKeySharesToGoogleDrive({
|
|
2899
|
+
accountAddress,
|
|
2900
|
+
encryptedKeyShares
|
|
2897
2901
|
});
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
});
|
|
2906
|
-
if (onProgress) {
|
|
2907
|
-
onProgress(0, 1);
|
|
2908
|
-
}
|
|
2909
|
-
const savedRecord = await saveBackupToICloud(backupData);
|
|
2910
|
-
savedRecords.push(savedRecord);
|
|
2911
|
-
if (onProgress) {
|
|
2912
|
-
onProgress(1, 1);
|
|
2913
|
-
}
|
|
2914
|
-
return savedRecords;
|
|
2915
|
-
} catch (error) {
|
|
2916
|
-
logError({
|
|
2917
|
-
message: 'Error in backupKeySharesToICloud',
|
|
2918
|
-
error: error,
|
|
2919
|
-
context: {
|
|
2920
|
-
accountAddress
|
|
2921
|
-
}
|
|
2922
|
-
});
|
|
2923
|
-
throw error;
|
|
2902
|
+
case core.BackupLocation.ICLOUD:
|
|
2903
|
+
return this.uploadKeySharesToICloud({
|
|
2904
|
+
accountAddress,
|
|
2905
|
+
encryptedKeyShares
|
|
2906
|
+
});
|
|
2907
|
+
default:
|
|
2908
|
+
throw new Error(`Unsupported cloud provider: ${provider}`);
|
|
2924
2909
|
}
|
|
2925
2910
|
}
|
|
2926
2911
|
/**
|
|
@@ -2972,6 +2957,40 @@ class DynamicWalletClient {
|
|
|
2972
2957
|
throw error;
|
|
2973
2958
|
}
|
|
2974
2959
|
}
|
|
2960
|
+
/**
|
|
2961
|
+
* Private method that handles only the iCloud upload mechanics without any reshare logic.
|
|
2962
|
+
* It takes already encrypted key shares and uploads them to iCloud.
|
|
2963
|
+
* @param accountAddress - The wallet account address
|
|
2964
|
+
* @param encryptedKeyShares - Already encrypted key shares to upload
|
|
2965
|
+
* @returns Promise<void>
|
|
2966
|
+
*/ async uploadKeySharesToICloud({ accountAddress, encryptedKeyShares }) {
|
|
2967
|
+
try {
|
|
2968
|
+
var _environmentSettings_sdk_waas, _environmentSettings_sdk;
|
|
2969
|
+
if (encryptedKeyShares.length === 0) {
|
|
2970
|
+
throw new Error('No key shares found');
|
|
2971
|
+
}
|
|
2972
|
+
const environmentSettings = await this.apiClient.getEnvironmentSettings();
|
|
2973
|
+
const iCloudConfig = environmentSettings == null ? void 0 : (_environmentSettings_sdk = environmentSettings.sdk) == null ? void 0 : (_environmentSettings_sdk_waas = _environmentSettings_sdk.waas) == null ? void 0 : _environmentSettings_sdk_waas.iCloud;
|
|
2974
|
+
await initializeCloudKit(iCloudConfig);
|
|
2975
|
+
const thresholdSignatureScheme = this.walletMap[accountAddress].thresholdSignatureScheme;
|
|
2976
|
+
const backupData = createBackupData({
|
|
2977
|
+
encryptedKeyShares,
|
|
2978
|
+
accountAddress,
|
|
2979
|
+
thresholdSignatureScheme
|
|
2980
|
+
});
|
|
2981
|
+
await saveBackupToICloud(backupData);
|
|
2982
|
+
return;
|
|
2983
|
+
} catch (error) {
|
|
2984
|
+
logError({
|
|
2985
|
+
message: 'Error in uploadKeySharesToICloud',
|
|
2986
|
+
error: error,
|
|
2987
|
+
context: {
|
|
2988
|
+
accountAddress
|
|
2989
|
+
}
|
|
2990
|
+
});
|
|
2991
|
+
throw error;
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2975
2994
|
async exportClientKeysharesFromGoogleDrive({ accountAddress, password, signedSessionId }) {
|
|
2976
2995
|
try {
|
|
2977
2996
|
await this.getWallet({
|
|
@@ -3624,25 +3643,26 @@ exports.ERROR_VERIFY_MESSAGE_SIGNATURE = ERROR_VERIFY_MESSAGE_SIGNATURE;
|
|
|
3624
3643
|
exports.ERROR_VERIFY_TRANSACTION_SIGNATURE = ERROR_VERIFY_TRANSACTION_SIGNATURE;
|
|
3625
3644
|
exports.WalletBusyError = WalletBusyError;
|
|
3626
3645
|
exports.cancelICloudAuth = cancelICloudAuth;
|
|
3627
|
-
exports.
|
|
3646
|
+
exports.createAddCloudProviderToExistingDelegationDistribution = createAddCloudProviderToExistingDelegationDistribution;
|
|
3628
3647
|
exports.createBackupData = createBackupData;
|
|
3648
|
+
exports.createCloudProviderDistribution = createCloudProviderDistribution;
|
|
3629
3649
|
exports.createDelegationOnlyDistribution = createDelegationOnlyDistribution;
|
|
3630
|
-
exports.
|
|
3650
|
+
exports.createDelegationWithCloudProviderDistribution = createDelegationWithCloudProviderDistribution;
|
|
3631
3651
|
exports.createDynamicOnlyDistribution = createDynamicOnlyDistribution;
|
|
3632
|
-
exports.createGoogleDriveOnlyDistribution = createGoogleDriveOnlyDistribution;
|
|
3633
3652
|
exports.deleteICloudBackup = deleteICloudBackup;
|
|
3634
3653
|
exports.downloadStringAsFile = downloadStringAsFile;
|
|
3635
3654
|
exports.extractPubkey = extractPubkey;
|
|
3636
3655
|
exports.formatEvmMessage = formatEvmMessage;
|
|
3637
3656
|
exports.formatMessage = formatMessage;
|
|
3657
|
+
exports.getActiveCloudProviders = getActiveCloudProviders;
|
|
3638
3658
|
exports.getClientKeyShareBackupInfo = getClientKeyShareBackupInfo;
|
|
3639
3659
|
exports.getClientKeyShareExportFileName = getClientKeyShareExportFileName;
|
|
3640
3660
|
exports.getGoogleOAuthAccountId = getGoogleOAuthAccountId;
|
|
3641
3661
|
exports.getICloudBackup = getICloudBackup;
|
|
3642
3662
|
exports.getMPCSignatureScheme = getMPCSignatureScheme;
|
|
3643
3663
|
exports.getMPCSigner = getMPCSigner;
|
|
3664
|
+
exports.hasCloudProviderBackup = hasCloudProviderBackup;
|
|
3644
3665
|
exports.hasDelegatedBackup = hasDelegatedBackup;
|
|
3645
|
-
exports.hasGoogleDriveBackup = hasGoogleDriveBackup;
|
|
3646
3666
|
exports.isBrowser = isBrowser;
|
|
3647
3667
|
exports.isHexString = isHexString;
|
|
3648
3668
|
exports.listICloudBackups = listICloudBackups;
|