wallet-stack 1.0.0-alpha.138 → 1.0.0-alpha.139

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wallet-stack",
3
- "version": "1.0.0-alpha.138",
3
+ "version": "1.0.0-alpha.139",
4
4
  "author": "Valora Inc",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/src/app/saga.ts CHANGED
@@ -260,9 +260,8 @@ function* watchDeepLinks() {
260
260
 
261
261
  export function* handleOpenUrl(action: OpenUrlAction) {
262
262
  const { url, openExternal, isSecureOrigin } = action
263
- const walletConnectEnabled: boolean = yield* call(isWalletConnectEnabled, url)
264
263
  Logger.debug(TAG, 'Handling url', url)
265
- if (isDeepLink(url) || (walletConnectEnabled && isWalletConnectDeepLink(url))) {
264
+ if (isDeepLink(url) || (isWalletConnectDeepLink(url) && (yield* call(isWalletConnectEnabled)))) {
266
265
  // Handle celo links directly, this avoids showing the "Open with App" sheet on Android
267
266
  yield* call(handleDeepLink, openDeepLink(url, isSecureOrigin))
268
267
  } else if (/^https?:\/\//i.test(url) === true && !openExternal) {
package/src/dapps/saga.ts CHANGED
@@ -43,8 +43,10 @@ export function* handleOpenDapp(action: PayloadAction<DappSelectedAction>) {
43
43
  ).inAppWebviewEnabled
44
44
 
45
45
  if (dappsWebViewEnabled) {
46
- const walletConnectEnabled: boolean = yield* call(isWalletConnectEnabled, dappUrl)
47
- if (isDeepLink(dappUrl) || (walletConnectEnabled && isWalletConnectDeepLink(dappUrl))) {
46
+ if (
47
+ isDeepLink(dappUrl) ||
48
+ (isWalletConnectDeepLink(dappUrl) && (yield* call(isWalletConnectEnabled)))
49
+ ) {
48
50
  yield* call(handleDeepLink, openDeepLink(dappUrl, true))
49
51
  } else {
50
52
  navigate(Screens.WebViewScreen, { uri: dappUrl })
@@ -88,11 +88,9 @@ export function* handleQRCodeDefault({
88
88
  }: HandleQRCodeDetectedAction) {
89
89
  AppAnalytics.track(QrScreenEvents.qr_scanned, qrCode)
90
90
 
91
- const walletConnectEnabled: boolean = yield* call(isWalletConnectEnabled, qrCode.data)
92
-
93
91
  // TODO there's some duplication with deep links handing
94
92
  // would be nice to refactor this
95
- if (qrCode.data.startsWith('wc:') && walletConnectEnabled) {
93
+ if (qrCode.data.startsWith('wc:') && (yield* call(isWalletConnectEnabled))) {
96
94
  yield* fork(handleLoadingWithTimeout, WalletConnectPairingOrigin.Scan)
97
95
  yield* call(initialiseWalletConnect, qrCode.data, WalletConnectPairingOrigin.Scan)
98
96
  return
@@ -36,6 +36,8 @@ import {
36
36
  handlePendingState,
37
37
  initialiseWalletConnect,
38
38
  initialiseWalletConnectV2,
39
+ isWalletConnectEnabled,
40
+ isWalletConnectV2Uri,
39
41
  normalizeTransactions,
40
42
  walletConnectSaga,
41
43
  } from 'src/walletConnect/saga'
@@ -1046,6 +1048,63 @@ describe('showActionRequest', () => {
1046
1048
  const v2ConnectionString =
1047
1049
  'wc:79a02f869d0f921e435a5e0643304548ebfa4a0430f9c66fe8b1a9254db7ef77@2?relay-protocol=irn&symKey=f661b0a9316a4ce0b6892bdce42bea0f45037f2c1bee9e118a3a4bc868a32a39'
1048
1050
 
1051
+ describe('isWalletConnectV2Uri', () => {
1052
+ it('returns true for a v2 wc: URI', () => {
1053
+ expect(isWalletConnectV2Uri(v2ConnectionString)).toBe(true)
1054
+ })
1055
+
1056
+ it('returns false for any string that is not a wc: pairing URI', () => {
1057
+ // parseUri is meant for wc: URIs only; passing anything else would force it
1058
+ // down its base64 link-mode fallback, which can throw on RN's strict native
1059
+ // base64 decoder. The startsWith('wc:') guard keeps non-WC strings out.
1060
+ expect(isWalletConnectV2Uri('https://churrito.fi')).toBe(false)
1061
+ expect(isWalletConnectV2Uri('testapp://wallet/wc?uri=wc:abc@2')).toBe(false)
1062
+ expect(isWalletConnectV2Uri('')).toBe(false)
1063
+ })
1064
+
1065
+ it('returns false for a v1 wc: URI', () => {
1066
+ expect(isWalletConnectV2Uri('wc:abc@1?bridge=https%3A%2F%2Fbridge.walletconnect.org')).toBe(
1067
+ false
1068
+ )
1069
+ })
1070
+ })
1071
+
1072
+ describe('isWalletConnectEnabled', () => {
1073
+ it('returns true when project id is set and v2 is not disabled', () => {
1074
+ jest.mocked(getAppConfig).mockReturnValue({
1075
+ displayName: 'Test App',
1076
+ deepLinkUrlScheme: 'testapp',
1077
+ registryName: 'test',
1078
+ features: { walletConnect: { projectId: '123' } },
1079
+ })
1080
+ jest.mocked(getFeatureGate).mockReturnValue(false)
1081
+ expect(isWalletConnectEnabled()).toBe(true)
1082
+ })
1083
+
1084
+ it('returns false when project id is missing', () => {
1085
+ jest.mocked(getAppConfig).mockReturnValue({
1086
+ displayName: 'Test App',
1087
+ deepLinkUrlScheme: 'testapp',
1088
+ registryName: 'test',
1089
+ })
1090
+ jest.mocked(getFeatureGate).mockReturnValue(false)
1091
+ expect(isWalletConnectEnabled()).toBe(false)
1092
+ })
1093
+
1094
+ it('returns false when v2 is feature-gated off', () => {
1095
+ jest.mocked(getAppConfig).mockReturnValue({
1096
+ displayName: 'Test App',
1097
+ deepLinkUrlScheme: 'testapp',
1098
+ registryName: 'test',
1099
+ features: { walletConnect: { projectId: '123' } },
1100
+ })
1101
+ jest
1102
+ .mocked(getFeatureGate)
1103
+ .mockImplementation((gate) => gate === StatsigFeatureGates.DISABLE_WALLET_CONNECT_V2)
1104
+ expect(isWalletConnectEnabled()).toBe(false)
1105
+ })
1106
+ })
1107
+
1049
1108
  describe('initialiseWalletConnect', () => {
1050
1109
  const origin = WalletConnectPairingOrigin.Deeplink
1051
1110
  it('initializes v2 if enabled and there is a wallet connect project id', async () => {
@@ -1123,31 +1123,29 @@ export function* initialiseWalletConnectV2(uri: string, origin: WalletConnectPai
1123
1123
  yield* put(initialisePairing(uri, origin))
1124
1124
  }
1125
1125
 
1126
- export function isWalletConnectEnabled(uri: string) {
1127
- const { version } = parseUri(uri)
1126
+ export function isWalletConnectV2Uri(uri: string): boolean {
1127
+ if (!uri.startsWith('wc:')) {
1128
+ return false
1129
+ }
1130
+ return parseUri(uri).version === 2
1131
+ }
1132
+
1133
+ export function isWalletConnectEnabled(): boolean {
1128
1134
  const walletConnectV2Disabled = getFeatureGate(StatsigFeatureGates.DISABLE_WALLET_CONNECT_V2)
1129
1135
  const walletConnectProjectId = getAppConfig().features?.walletConnect?.projectId
1130
-
1131
- return !!walletConnectProjectId && !walletConnectV2Disabled && version === 2
1136
+ return !!walletConnectProjectId && !walletConnectV2Disabled
1132
1137
  }
1133
1138
 
1134
1139
  export function* initialiseWalletConnect(uri: string, origin: WalletConnectPairingOrigin) {
1135
- const walletConnectEnabled = yield* call(isWalletConnectEnabled, uri)
1136
-
1137
- const { version } = parseUri(uri)
1138
- if (!walletConnectEnabled) {
1139
- Logger.debug('initialiseWalletConnect', `v${version} is disabled, ignoring`)
1140
+ if (!isWalletConnectV2Uri(uri)) {
1141
+ Logger.debug('initialiseWalletConnect', 'URI is not a WalletConnect v2 link, ignoring')
1140
1142
  return
1141
1143
  }
1142
-
1143
- switch (version) {
1144
- case 2:
1145
- yield* call(initialiseWalletConnectV2, uri, origin)
1146
- break
1147
- case 1:
1148
- default:
1149
- throw new Error(`Unsupported WalletConnect version '${version}'`)
1144
+ if (!isWalletConnectEnabled()) {
1145
+ Logger.debug('initialiseWalletConnect', 'WalletConnect is disabled, ignoring')
1146
+ return
1150
1147
  }
1148
+ yield* call(initialiseWalletConnectV2, uri, origin)
1151
1149
  }
1152
1150
 
1153
1151
  export function* showWalletConnectionSuccessMessage(dappName: string) {