radar-sdk-js 4.2.1-beta.0 → 4.2.1-beta.2

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/dist/radar.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"radar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"radar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/dist/types.d.ts CHANGED
@@ -52,6 +52,7 @@ export interface RadarTrackParams {
52
52
  metadata?: RadarMetadata;
53
53
  tripOptions?: RadarTripOptions;
54
54
  desiredAccuracy?: 'high' | 'medium' | 'low';
55
+ fraud?: boolean;
55
56
  }
56
57
  export declare enum RadarEventConfidence {
57
58
  none = 0,
@@ -59,7 +60,7 @@ export declare enum RadarEventConfidence {
59
60
  medium = 2,
60
61
  high = 3
61
62
  }
62
- export type RadarEventType = 'unknown' | 'user.entered_geofence' | 'user.entered_home' | 'user.entered_office' | 'user.entered_place' | 'user.entered_region_country' | 'user.entered_region_dma' | 'user.entered_region_state' | 'user.exited_geofence' | 'user.exited_home' | 'user.exited_office' | 'user.exited_place' | 'user.exited_region_country' | 'user.exited_region_dma' | 'user.exited_region_state' | 'user.nearby_place_chain' | 'user.started_traveling' | 'user.stopped_traveling' | 'user.started_commuting' | 'user.stopped_commuting' | 'user.started_trip' | 'user.updated_trip' | 'user.approaching_trip_destination' | 'user.arrived_at_trip_destination' | 'user.stopped_trip';
63
+ export type RadarEventType = 'unknown' | 'user.entered_geofence' | 'user.entered_home' | 'user.entered_office' | 'user.entered_place' | 'user.entered_region_country' | 'user.entered_region_dma' | 'user.entered_region_state' | 'user.exited_geofence' | 'user.exited_home' | 'user.exited_office' | 'user.exited_place' | 'user.exited_region_country' | 'user.exited_region_dma' | 'user.exited_region_state' | 'user.nearby_place_chain' | 'user.started_traveling' | 'user.stopped_traveling' | 'user.started_commuting' | 'user.stopped_commuting' | 'user.started_trip' | 'user.updated_trip' | 'user.approaching_trip_destination' | 'user.arrived_at_trip_destination' | 'user.stopped_trip' | 'user.failed_fraud';
63
64
  export interface RadarGeofence {
64
65
  _id: string;
65
66
  description: string;
@@ -142,8 +143,11 @@ export interface RadarTrackResponse extends RadarResponse {
142
143
  user?: RadarUser;
143
144
  events?: RadarEvent[];
144
145
  }
145
- export interface RadarTrackTokenResponse extends RadarResponse {
146
+ export interface RadarTrackVerifiedResponse extends RadarTrackResponse {
146
147
  token?: String;
148
+ expiresAt?: Date;
149
+ expiresIn?: number;
150
+ passed?: boolean;
147
151
  }
148
152
  export interface RadarContextResponse extends RadarResponse {
149
153
  location?: Location;
@@ -179,7 +183,7 @@ export interface RadarCustomEvent {
179
183
  export interface RadarConversionResponse extends RadarResponse {
180
184
  event: RadarCustomEvent;
181
185
  }
182
- export type RadarGeocodeLayer = 'place' | 'address' | 'intersection' | 'street' | 'neighborhood' | 'postalCode' | 'locality' | 'county' | 'state' | 'country' | 'coarse' | 'fine';
186
+ export type RadarGeocodeLayer = 'place' | 'address' | 'postalCode' | 'locality' | 'county' | 'state' | 'country' | 'coarse' | 'fine';
183
187
  export interface RadarAddress {
184
188
  addressLabel?: string;
185
189
  borough?: string;
@@ -243,7 +247,9 @@ export interface RadarAutocompleteParams {
243
247
  limit?: number;
244
248
  layers?: RadarGeocodeLayer[];
245
249
  countryCode?: string;
250
+ /** @deprecated this is always true, regardless of the value passed here */
246
251
  expandUnits?: boolean;
252
+ mailable?: boolean;
247
253
  }
248
254
  export interface RadarAutocompleteResponse extends RadarResponse {
249
255
  addresses: RadarAutocompleteAddress[];
@@ -333,6 +339,7 @@ export interface RadarSearchGeofencesParams {
333
339
  tags?: string[] | string;
334
340
  metadata?: RadarMetadata;
335
341
  limit?: number;
342
+ includeGeometry?: boolean;
336
343
  }
337
344
  export interface RadarSearchGeofencesResponse extends RadarResponse {
338
345
  geofences: RadarGeofence[];
@@ -357,6 +364,7 @@ export interface RadarAutocompleteUIOptions {
357
364
  layers?: RadarGeocodeLayer[];
358
365
  countryCode?: string;
359
366
  expandUnits?: boolean;
367
+ mailable?: boolean;
360
368
  placeholder?: string;
361
369
  onSelection?: (selection: any) => void;
362
370
  onRequest?: (params: RadarAutocompleteParams) => void;
@@ -0,0 +1 @@
1
+ export declare const signJWT: (payload: object, key: string) => Promise<string>;
@@ -0,0 +1 @@
1
+ export declare const ping: (host: string) => Promise<any>;
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- declare const _default: "4.2.1-beta.0";
1
+ declare const _default: "4.2.1-beta.2";
2
2
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "radar-sdk-js",
3
- "version": "4.2.1-beta.0",
3
+ "version": "4.2.1-beta.2",
4
4
  "description": "Web Javascript SDK for Radar, location infrastructure for mobile and web apps.",
5
5
  "homepage": "https://radar.com",
6
6
  "type": "module",
package/src/api/search.ts CHANGED
@@ -22,6 +22,7 @@ class SearchAPI {
22
22
  layers,
23
23
  countryCode,
24
24
  expandUnits,
25
+ mailable,
25
26
  } = params;
26
27
 
27
28
  // near can be provided as a string or Location object
@@ -42,6 +43,7 @@ class SearchAPI {
42
43
  layers,
43
44
  countryCode,
44
45
  expandUnits,
46
+ mailable,
45
47
  },
46
48
  });
47
49
 
@@ -65,6 +67,7 @@ class SearchAPI {
65
67
  tags,
66
68
  metadata,
67
69
  limit,
70
+ includeGeometry,
68
71
  } = params;
69
72
 
70
73
  // use browser location if "near" not provided
@@ -90,6 +93,7 @@ class SearchAPI {
90
93
  tags,
91
94
  metadata,
92
95
  limit,
96
+ includeGeometry,
93
97
  },
94
98
  });
95
99
 
package/src/api/track.ts CHANGED
@@ -6,16 +6,17 @@ import Logger from '../logger';
6
6
  import Navigator from '../navigator';
7
7
  import Session from '../session';
8
8
  import Storage from '../storage';
9
-
10
9
  import TripsAPI from './trips';
10
+ import { signJWT } from '../util/jwt';
11
+ import { ping } from '../util/net';
11
12
 
12
- import type { RadarTrackParams, RadarTrackResponse } from '../types';
13
+ import type { RadarTrackParams, RadarTrackResponse, RadarTrackVerifiedResponse } from '../types';
13
14
 
14
15
  class TrackAPI {
15
16
  static async trackOnce(params: RadarTrackParams) {
16
17
  const options = Config.get();
17
18
 
18
- let { latitude, longitude, accuracy, desiredAccuracy } = params;
19
+ let { latitude, longitude, accuracy, desiredAccuracy, fraud } = params;
19
20
 
20
21
  // if latitude & longitude are not provided,
21
22
  // try and retrieve device location (will prompt for location permissions)
@@ -42,6 +43,13 @@ class TrackAPI {
42
43
  const deviceType = params.deviceType || 'Web';
43
44
  const description = params.description || Storage.getItem(Storage.DESCRIPTION);
44
45
 
46
+ let timeZone;
47
+ try {
48
+ timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
49
+ } catch (err: any) {
50
+ Logger.warn(`Error getting time zone: ${err.message}`);
51
+ }
52
+
45
53
  // save userId for trip tracking
46
54
  if (!userId) {
47
55
  Logger.warn('userId not provided for trackOnce.');
@@ -75,9 +83,113 @@ class TrackAPI {
75
83
  stopped: true,
76
84
  userId,
77
85
  tripOptions,
86
+ timeZone,
78
87
  };
79
88
 
80
- const response: any = await Http.request({
89
+ let response: any;
90
+ if (fraud) {
91
+ const host = 'https://api-verified.radar.io';
92
+ const pingHost = 'ping.radar-verify.com';
93
+
94
+ const lang = navigator.language;
95
+ const langs = navigator.languages;
96
+
97
+ const { dk }: any = await Http.request({
98
+ host,
99
+ method: 'GET',
100
+ path: 'config',
101
+ data: {
102
+ deviceId,
103
+ installId,
104
+ sessionId,
105
+ locationAuthorization,
106
+ },
107
+ headers: {
108
+ 'X-Radar-Desktop-Device-Type': 'Web',
109
+ },
110
+ });
111
+
112
+ let sclVal = -1;
113
+ let cslVal = -1;
114
+ try {
115
+ const [sclRes, csl] = await Promise.all([
116
+ Http.request({
117
+ host: `https://${pingHost}`,
118
+ method: 'GET',
119
+ path: 'ping',
120
+ }),
121
+ ping(`wss://${pingHost}`),
122
+ ]);
123
+ const { scl }: any = sclRes;
124
+ sclVal = scl;
125
+ cslVal = csl;
126
+ } catch (err) {
127
+ // do nothing, send scl = -1 and csl = -1
128
+ }
129
+
130
+ const payload = {
131
+ payload: JSON.stringify({
132
+ ...body,
133
+ scl: sclVal,
134
+ csl: cslVal,
135
+ lang,
136
+ langs,
137
+ }),
138
+ };
139
+
140
+ const reqToken = await signJWT(payload, dk);
141
+
142
+ response = await Http.request({
143
+ host,
144
+ method: 'POST',
145
+ path: 'track',
146
+ data: {
147
+ token: reqToken,
148
+ },
149
+ headers: {
150
+ 'X-Radar-Body-Is-Token': 'true',
151
+ },
152
+ });
153
+
154
+ if (options.debug && response && response.user) {
155
+ if (!response.user.metadata) {
156
+ response.user.metadata = {};
157
+ }
158
+
159
+ response.user.metadata['radar:debug'] = {
160
+ sclVal,
161
+ cslVal,
162
+ };
163
+ }
164
+
165
+ let { user, events, token, expiresAt } = response;
166
+ const location = { latitude, longitude, accuracy };
167
+ let passed;
168
+ let expiresIn;
169
+ if (expiresAt) {
170
+ expiresAt = new Date(expiresAt);
171
+ passed = user?.fraud?.passed && user?.country?.passed && user?.state?.passed;
172
+ expiresIn = (expiresAt.getTime() - Date.now()) / 1000;
173
+ }
174
+
175
+ const trackRes = {
176
+ user,
177
+ events,
178
+ location,
179
+ token,
180
+ expiresAt,
181
+ expiresIn,
182
+ passed,
183
+ } as RadarTrackVerifiedResponse;
184
+
185
+ if (options.debug) {
186
+ trackRes.response = response;
187
+ }
188
+
189
+ return trackRes;
190
+ }
191
+
192
+ response = await Http.request({
81
193
  method: 'POST',
82
194
  path: 'track',
83
195
  data: body,
package/src/api/verify.ts CHANGED
@@ -6,7 +6,7 @@ import Logger from '../logger';
6
6
  import Session from '../session';
7
7
  import Storage from '../storage';
8
8
 
9
- import type { RadarTrackParams, RadarTrackResponse, RadarTrackTokenResponse } from '../types';
9
+ import type { RadarTrackParams, RadarTrackVerifiedResponse } from '../types';
10
10
 
11
11
  class VerifyAPI {
12
12
  static async trackVerified(params: RadarTrackParams, encrypted: Boolean = false) {
@@ -44,16 +44,16 @@ class VerifyAPI {
44
44
  };
45
45
 
46
46
  let userAgent = navigator.userAgent;
47
- const mac = userAgent && userAgent.toLowerCase().includes('mac');
47
+ const apple = userAgent && (userAgent.toLowerCase().includes('mac') || userAgent.toLowerCase().includes('iphone') || userAgent.toLowerCase().includes('ipod') || userAgent.toLowerCase().includes('ipad'));
48
48
 
49
49
  const response: any = await Http.request({
50
50
  method: 'GET',
51
51
  path: 'verify',
52
52
  data: body,
53
- host: mac ? 'https://radar-verify.com:52516' : 'http://localhost:52516',
53
+ host: apple ? 'https://radar-verify.com:52516' : 'http://localhost:52516',
54
54
  });
55
55
 
56
- const { user, events, token } = response;
56
+ let { user, events, token, expiresAt } = response;
57
57
  let location;
58
58
  if (user && user.location && user.location.coordinates && user.locationAccuracy) {
59
59
  location = {
@@ -62,24 +62,23 @@ class VerifyAPI {
62
62
  accuracy: user.locationAccuracy,
63
63
  };
64
64
  }
65
-
66
- if (encrypted) {
67
- const trackTokenRes = {
68
- token,
69
- } as RadarTrackTokenResponse;
70
-
71
- if (options.debug) {
72
- trackTokenRes.response = response;
73
- }
74
-
75
- return trackTokenRes;
65
+ let passed;
66
+ let expiresIn;
67
+ if (expiresAt) {
68
+ expiresAt = new Date(expiresAt);
69
+ passed = user?.fraud?.passed && user?.country?.passed && user?.state?.passed;
70
+ expiresIn = (expiresAt.getTime() - Date.now()) / 1000;
76
71
  }
77
72
 
78
73
  const trackRes = {
79
74
  user,
80
75
  events,
81
76
  location,
82
- } as RadarTrackResponse;
77
+ token,
78
+ expiresAt,
79
+ expiresIn,
80
+ passed,
81
+ } as RadarTrackVerifiedResponse;
83
82
 
84
83
  if (options.debug) {
85
84
  trackRes.response = response;
package/src/errors.ts CHANGED
@@ -23,19 +23,19 @@ export class RadarLocationError extends RadarError {
23
23
  }
24
24
  }
25
25
 
26
- export class RadarLocationPermissionsError extends RadarError {
26
+ export class RadarPermissionsError extends RadarError {
27
27
  constructor(message: string) {
28
28
  super(message);
29
- this.name = 'RadarLocationPermissionsError';
29
+ this.name = 'RadarPermissionsError';
30
30
  this.status = 'ERROR_PERMISSIONS';
31
31
  }
32
32
  }
33
33
 
34
- export class RadarDesktopAppError extends RadarError {
34
+ export class RadarVerifyAppError extends RadarError {
35
35
  constructor() {
36
- super('Desktop app not running.');
37
- this.name = 'RadarDesktopAppError';
38
- this.status = 'ERROR_DESKTOP_APP';
36
+ super('Radar Verify app not running.');
37
+ this.name = 'RadarVerifyAppError';
38
+ this.status = 'ERROR_VERIFY_APP';
39
39
  }
40
40
  }
41
41
 
@@ -131,11 +131,11 @@ export class RadarServerError extends RadarError {
131
131
  }
132
132
  }
133
133
 
134
- export class RadarTimeoutError extends RadarError {
134
+ export class RadarNetworkError extends RadarError {
135
135
  constructor() {
136
136
  super('Request timed out.');
137
- this.name = 'RadarTimeoutError';
138
- this.status = 'ERROR_TIMED_OUT';
137
+ this.name = 'RadarNetworkError';
138
+ this.status = 'ERROR_NETWORK';
139
139
  }
140
140
  }
141
141
 
package/src/http.ts CHANGED
@@ -4,18 +4,18 @@ import Logger from './logger';
4
4
 
5
5
  import {
6
6
  RadarBadRequestError,
7
- RadarDesktopAppError,
8
7
  RadarForbiddenError,
9
8
  RadarLocationError,
10
- RadarLocationPermissionsError,
9
+ RadarNetworkError,
11
10
  RadarNotFoundError,
12
11
  RadarPaymentRequiredError,
12
+ RadarPermissionsError,
13
13
  RadarPublishableKeyError,
14
14
  RadarRateLimitError,
15
15
  RadarServerError,
16
- RadarTimeoutError,
17
16
  RadarUnauthorizedError,
18
17
  RadarUnknownError,
18
+ RadarVerifyAppError,
19
19
  } from './errors';
20
20
 
21
21
  export type HttpMethod = 'GET' | 'PUT' | 'PATCH' | 'POST' | 'DELETE';
@@ -31,11 +31,13 @@ class Http {
31
31
  path,
32
32
  data,
33
33
  host,
34
+ headers,
34
35
  }: {
35
36
  method: HttpMethod;
36
37
  path: string;
37
38
  data?: any;
38
39
  host?: string;
40
+ headers?: Record<string, string>;
39
41
  }) {
40
42
  return new Promise<HttpResponse>((resolve, reject) => {
41
43
  const options = Config.get();
@@ -76,13 +78,21 @@ class Http {
76
78
  const xhr = new XMLHttpRequest();
77
79
  xhr.open(method, url, true);
78
80
 
79
- // set headers
81
+ // set standard headers
80
82
  xhr.setRequestHeader('Authorization', publishableKey);
81
83
  xhr.setRequestHeader('Content-Type', 'application/json');
82
84
  xhr.setRequestHeader('X-Radar-Device-Type', 'Web');
83
85
  xhr.setRequestHeader('X-Radar-SDK-Version', SDK_VERSION);
84
86
 
85
- // set custom headers if present
87
+ // set passed custom headers if present
88
+ if (headers) {
89
+ Object.keys(headers).forEach(key => {
90
+ const val = headers[key];
91
+ xhr.setRequestHeader(key, val);
92
+ });
93
+ }
94
+
95
+ // set config custom headers if present
86
96
  if (typeof options.getRequestHeaders === 'function') {
87
97
  const headers: { [key: string]: string } = options.getRequestHeaders();
88
98
  Object.keys(headers || {}).forEach((key) => {
@@ -100,11 +110,11 @@ class Http {
100
110
 
101
111
  const error = response?.meta?.error;
102
112
  if (error === 'ERROR_PERMISSIONS') {
103
- return reject(new RadarLocationPermissionsError('Location permissions not granted.'));
113
+ return reject(new RadarPermissionsError('Location permissions not granted.'));
104
114
  } else if (error === 'ERROR_LOCATION') {
105
115
  return reject(new RadarLocationError('Could not determine location.'));
106
116
  } else if (error === 'ERROR_NETWORK') {
107
- return reject(new RadarTimeoutError());
117
+ return reject(new RadarNetworkError());
108
118
  }
109
119
 
110
120
  if (xhr.status == 200) {
@@ -143,15 +153,15 @@ class Http {
143
153
  }
144
154
 
145
155
  xhr.onerror = function() {
146
- if (host && host === 'https://radar-verify.com:52516') {
147
- reject(new RadarDesktopAppError());
156
+ if (host && (host === 'http://localhost:52516' || host === 'https://radar-verify.com:52516')) {
157
+ reject(new RadarVerifyAppError());
148
158
  } else {
149
159
  reject(new RadarServerError());
150
160
  }
151
161
  }
152
162
 
153
163
  xhr.ontimeout = function() {
154
- reject(new RadarTimeoutError());
164
+ reject(new RadarVerifyAppError());
155
165
  }
156
166
 
157
167
  xhr.send(JSON.stringify(body));
package/src/index.ts CHANGED
@@ -148,10 +148,6 @@ class Radar {
148
148
  return VerifyAPI.trackVerified(params);
149
149
  }
150
150
 
151
- public static trackVerifiedToken(params: RadarTrackParams = {}) {
152
- return VerifyAPI.trackVerified(params, true);
153
- }
154
-
155
151
  public static getContext(params: Location) {
156
152
  return ContextAPI.getContext(params);
157
153
  }
package/src/navigator.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import Config from './config';
2
2
  import Logger from './logger';
3
3
  import Storage from './storage';
4
- import { RadarLocationError, RadarLocationPermissionsError } from './errors';
4
+ import { RadarLocationError, RadarPermissionsError } from './errors';
5
5
 
6
6
  import type { LocationAuthorization, NavigatorPosition } from './types';
7
7
 
@@ -9,13 +9,6 @@ interface PositionOptionOverrides {
9
9
  desiredAccuracy?: string;
10
10
  }
11
11
 
12
- // https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError
13
- const PERMISSION_ERROR_MESSAGES: any = {
14
- 1: 'Permission denied.',
15
- 2: 'Position unavailable.',
16
- 3: 'Timeout.',
17
- };
18
-
19
12
  const DEFAULT_POSITION_OPTIONS: PositionOptions = {
20
13
  maximumAge: 0,
21
14
  timeout: 1000 * 30, // 30 seconds
@@ -95,9 +88,11 @@ class Navigator {
95
88
  return resolve({ latitude, longitude, accuracy });
96
89
  },
97
90
  (err: GeolocationPositionError) => { // location call failed or user did not grant permission
98
- if (err && err.code) {
99
- const message = PERMISSION_ERROR_MESSAGES[err.code.toString()] || 'unknown';
100
- return reject(new RadarLocationPermissionsError(message));
91
+ if (err && err.code === 1) {
92
+ // https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError
93
+ // code 1 means location permissions denied
94
+ // codes 2 and 3 mean location unavailable or timeout
95
+ return reject(new RadarPermissionsError('Location permissions denied.'));
101
96
  }
102
97
  return reject(new RadarLocationError('Could not determine location.'));
103
98
  },
package/src/types.ts CHANGED
@@ -73,6 +73,7 @@ export interface RadarTrackParams {
73
73
  metadata?: RadarMetadata;
74
74
  tripOptions?: RadarTripOptions;
75
75
  desiredAccuracy?: 'high' | 'medium' | 'low';
76
+ fraud?: boolean;
76
77
  }
77
78
 
78
79
  export enum RadarEventConfidence {
@@ -107,7 +108,8 @@ export type RadarEventType =
107
108
  | 'user.updated_trip'
108
109
  | 'user.approaching_trip_destination'
109
110
  | 'user.arrived_at_trip_destination'
110
- | 'user.stopped_trip';
111
+ | 'user.stopped_trip'
112
+ | 'user.failed_fraud';
111
113
 
112
114
  export interface RadarGeofence {
113
115
  _id: string;
@@ -211,8 +213,11 @@ export interface RadarTrackResponse extends RadarResponse {
211
213
  events?: RadarEvent[];
212
214
  }
213
215
 
214
- export interface RadarTrackTokenResponse extends RadarResponse {
216
+ export interface RadarTrackVerifiedResponse extends RadarTrackResponse {
215
217
  token?: String;
218
+ expiresAt?: Date;
219
+ expiresIn?: number;
220
+ passed?: boolean;
216
221
  }
217
222
 
218
223
  export interface RadarContextResponse extends RadarResponse {
@@ -257,9 +262,6 @@ export interface RadarConversionResponse extends RadarResponse {
257
262
  export type RadarGeocodeLayer =
258
263
  | 'place'
259
264
  | 'address'
260
- | 'intersection'
261
- | 'street'
262
- | 'neighborhood'
263
265
  | 'postalCode'
264
266
  | 'locality'
265
267
  | 'county'
@@ -341,7 +343,9 @@ export interface RadarAutocompleteParams {
341
343
  limit?: number;
342
344
  layers?: RadarGeocodeLayer[];
343
345
  countryCode?: string;
346
+ /** @deprecated this is always true, regardless of the value passed here */
344
347
  expandUnits?: boolean;
348
+ mailable?: boolean;
345
349
  }
346
350
 
347
351
  export interface RadarAutocompleteResponse extends RadarResponse {
@@ -448,6 +452,7 @@ export interface RadarSearchGeofencesParams {
448
452
  tags?: string[] | string;
449
453
  metadata?: RadarMetadata;
450
454
  limit?: number;
455
+ includeGeometry?: boolean;
451
456
  }
452
457
 
453
458
  export interface RadarSearchGeofencesResponse extends RadarResponse {
@@ -476,6 +481,7 @@ export interface RadarAutocompleteUIOptions {
476
481
  layers?: RadarGeocodeLayer[];
477
482
  countryCode?: string;
478
483
  expandUnits?: boolean;
484
+ mailable?: boolean;
479
485
  placeholder?: string, // Placeholder text for the input field
480
486
  onSelection?: (selection: any) => void,
481
487
  onRequest?: (params: RadarAutocompleteParams) => void,
@@ -236,7 +236,7 @@ class AutocompleteUI {
236
236
  }
237
237
 
238
238
  public async fetchResults(query: string) {
239
- const { limit, layers, countryCode, expandUnits, onRequest } = this.config;
239
+ const { limit, layers, countryCode, expandUnits, mailable, onRequest } = this.config;
240
240
 
241
241
  const params: RadarAutocompleteParams = {
242
242
  query,
@@ -244,6 +244,7 @@ class AutocompleteUI {
244
244
  layers,
245
245
  countryCode,
246
246
  expandUnits,
247
+ mailable,
247
248
  }
248
249
 
249
250
  if (this.near) {
@@ -0,0 +1,28 @@
1
+ const base64Encode = (str: string): string =>
2
+ btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
3
+
4
+ export const signJWT = async (payload: object, key: string): Promise<string> => {
5
+ const encoder = new TextEncoder();
6
+
7
+ const encodedHeader = base64Encode(JSON.stringify({
8
+ alg: 'HS256',
9
+ typ: 'JWT',
10
+ }));
11
+ const encodedPayload = base64Encode(JSON.stringify(payload));
12
+
13
+ const keyData = encoder.encode(key);
14
+ const messageData = encoder.encode(`${encodedHeader}.${encodedPayload}`);
15
+
16
+ const cryptoKey = await crypto.subtle.importKey(
17
+ 'raw',
18
+ keyData,
19
+ { name: 'HMAC', hash: { name: 'SHA-256' } },
20
+ false,
21
+ ['sign']
22
+ );
23
+
24
+ const signatureArrayBuffer = await crypto.subtle.sign('HMAC', cryptoKey, messageData);
25
+ const signature = base64Encode(String.fromCharCode(...Array.from(new Uint8Array(signatureArrayBuffer))));
26
+
27
+ return `${encodedHeader}.${encodedPayload}.${signature}`;
28
+ };