wealthica-sdk-js 0.0.17 → 0.0.19

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/README.md CHANGED
@@ -165,7 +165,7 @@ token = await user.getToken(); // fetches and returns a new token
165
165
  token = await user.getToken({ minimumLifeTime: 600 }); // fetches and returns another new token
166
166
  ```
167
167
 
168
- #### user.getConnectData({ provider, redirectURI, state, lang, theme, providersPerLine })
168
+ #### user.getConnectData({ provider, redirectURI, state, lang, theme, providersPerLine, webhookURI })
169
169
 
170
170
  This method returns a Wealthica Connect URL and authentication token for user to connect an institution.
171
171
 
@@ -192,6 +192,7 @@ const { url, token } = await user.getConnectData({
192
192
  theme: 'light', // optional (light | dark), 'light' by default
193
193
  providersPerLine: 1, // optional (1 | 2), 2 by default
194
194
  features: 'feature1,feature2', // optional, a comma-separated list of features. undefined by default
195
+ webhookURI: 'YOUR_WEBHOOK_URI', // optional, URL to receive webhook notifications (must be HTTPS)
195
196
  });
196
197
  // {
197
198
  // url: "https://connect.wealthica.com/connect/coinbase?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&origin=YOUR_SITE_ORIGIN&state=YOUR_APP_STATE&lang=en&theme=light&providersPerLine=2",
@@ -227,7 +228,7 @@ const user2 = wealthica.login('USER_ID_2');
227
228
  const { url: url2, token } = await user2.getConnectData();
228
229
  ```
229
230
 
230
- #### user.connect({ provider, providers, institutionId, lang, theme, providersPerLine, features, origin })
231
+ #### user.connect({ provider, providers, institutionId, lang, theme, providersPerLine, features, origin, webhookURI })
231
232
 
232
233
  This method starts the Wealthica Connect process inside your webpage/app for user to connect their institution.
233
234
 
@@ -238,6 +239,7 @@ This method accepts the same parameters as `user.getConnectData()` except for `r
238
239
  ```javascript
239
240
  user.connect({
240
241
  // additional options
242
+ webhookURI: 'YOUR_WEBHOOK_URI', // optional, URL to receive webhook notifications (must be HTTPS)
241
243
  }).onConnection((institution, data) => {
242
244
  console.log('provider', data.provider);
243
245
  // Send the institution to your server
@@ -249,7 +251,7 @@ user.connect({
249
251
  });
250
252
  ```
251
253
 
252
- #### user.reconnect(institutionId)
254
+ #### user.reconnect(institutionId, { lang, theme, features, origin, webhookURI })
253
255
 
254
256
  This method starts the Wealthica Connect process to re-connect an existing institution that has expired/revoked credentials.
255
257
 
@@ -258,6 +260,7 @@ Connection response are provided via callbacks.
258
260
  ```javascript
259
261
  user.reconnect('INSTITUTION_ID', {
260
262
  // additional options
263
+ webhookURI: 'YOUR_WEBHOOK_URI', // optional, URL to receive webhook notifications (must be HTTPS)
261
264
  }).onConnection(((institution, data) => {
262
265
  console.log('provider', data.provider);
263
266
  // Send the institution to your server
@@ -269,6 +272,49 @@ user.reconnect('INSTITUTION_ID', {
269
272
  });
270
273
  ```
271
274
 
275
+ ### Feature Flags
276
+
277
+ The `features` parameter accepts a comma-separated list of feature flags to enable specific behaviors in the Connect widget.
278
+
279
+ #### Available Feature Flags
280
+
281
+ **`quick_retry`** *(Available from v0.0.19+)*
282
+
283
+ Enables a quick retry option when temporary connection failures occur (e.g., timeout, temporary API issues).
284
+
285
+ - **Default:** Disabled
286
+ - **Behavior:** When enabled, users see a retry button instead of automatic widget closure after temporary failures
287
+ - **Retry Limit:** One retry attempt per session
288
+
289
+ **Usage Example:**
290
+
291
+ ```javascript
292
+ // Enable quick retry feature
293
+ user.connect({
294
+ provider: 'td',
295
+ features: 'quick_retry',
296
+ // ... other options
297
+ }).onConnection((institution) => {
298
+ console.log('Connected:', institution);
299
+ }).onError((error) => {
300
+ console.error('Error:', error);
301
+ }).onEvent((name, data) => {
302
+ // Listen for retry events
303
+ if (name === 'RETRY_ATTEMPT') {
304
+ console.log('User is retrying connection');
305
+ }
306
+ if (name === 'RETRY_DECLINED') {
307
+ console.log('User declined to retry');
308
+ }
309
+ });
310
+
311
+ // Enable multiple features
312
+ user.connect({
313
+ features: 'quick_retry,another_feature',
314
+ // ... other options
315
+ });
316
+ ```
317
+
272
318
  ### User APIs
273
319
 
274
320
  These methods return user data and thus require a Wealthica Connect SDK User instance. They automatically fetch a new token if necessary so you would not be bothered with tokens logic.
@@ -96,6 +96,10 @@ type ConnectDataOptions = {
96
96
  redirectURI: string;
97
97
  providers: Array<string> | undefined;
98
98
  providerGroups: Array<string> | undefined;
99
+ theme: string;
100
+ providersPerLine: number | string;
101
+ features: string;
102
+ webhookURI: string;
99
103
  }
100
104
 
101
105
  type ConnectData = {
@@ -96,6 +96,10 @@ type ConnectDataOptions = {
96
96
  redirectURI: string;
97
97
  providers: Array<string> | undefined;
98
98
  providerGroups: Array<string> | undefined;
99
+ theme: string;
100
+ providersPerLine: number | string;
101
+ features: string;
102
+ webhookURI: string;
99
103
  }
100
104
 
101
105
  type ConnectData = {
@@ -6000,6 +6000,7 @@ var API = /*#__PURE__*/function () {
6000
6000
  this._onWidgetMessage = this._onMessage.bind(this);
6001
6001
  this._widgetOpened = false;
6002
6002
  this._widgetActive = false;
6003
+ this._features = null;
6003
6004
  }
6004
6005
  _createClass(API, [{
6005
6006
  key: "_init",
@@ -6208,9 +6209,11 @@ var API = /*#__PURE__*/function () {
6208
6209
  theme,
6209
6210
  providersPerLine,
6210
6211
  features,
6212
+ webhookURI,
6211
6213
  _this$config5,
6212
6214
  clientId,
6213
6215
  connectURL,
6216
+ _url,
6214
6217
  token,
6215
6218
  query,
6216
6219
  queryString,
@@ -6221,13 +6224,32 @@ var API = /*#__PURE__*/function () {
6221
6224
  switch (_context4.prev = _context4.next) {
6222
6225
  case 0:
6223
6226
  options = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {};
6224
- provider = options.provider, institutionId = options.institutionId, state = options.state, _options$origin = options.origin, origin = _options$origin === void 0 ? this.isBrowser ? window.location.origin : undefined : _options$origin, lang = options.lang, _options$redirectURI = options.redirectURI, redirectURI = _options$redirectURI === void 0 ? this.config.redirectURI : _options$redirectURI, providers = options.providers, _options$providerGrou = options.providerGroups, providerGroups = _options$providerGrou === void 0 ? ['core'] : _options$providerGrou, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features;
6225
- _this$config5 = this.config, clientId = _this$config5.clientId, connectURL = _this$config5.connectURL; // Get a token with at least 10 minutes left
6226
- _context4.next = 5;
6227
+ provider = options.provider, institutionId = options.institutionId, state = options.state, _options$origin = options.origin, origin = _options$origin === void 0 ? this.isBrowser ? window.location.origin : undefined : _options$origin, lang = options.lang, _options$redirectURI = options.redirectURI, redirectURI = _options$redirectURI === void 0 ? this.config.redirectURI : _options$redirectURI, providers = options.providers, _options$providerGrou = options.providerGroups, providerGroups = _options$providerGrou === void 0 ? ['core'] : _options$providerGrou, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features, webhookURI = options.webhookURI;
6228
+ _this$config5 = this.config, clientId = _this$config5.clientId, connectURL = _this$config5.connectURL; // Validate webhookURI if provided
6229
+ if (!webhookURI) {
6230
+ _context4.next = 13;
6231
+ break;
6232
+ }
6233
+ _context4.prev = 4;
6234
+ _url = new URL(webhookURI);
6235
+ if (!(_url.protocol !== 'https:')) {
6236
+ _context4.next = 8;
6237
+ break;
6238
+ }
6239
+ throw new Error('Webhook URI must use HTTPS protocol');
6240
+ case 8:
6241
+ _context4.next = 13;
6242
+ break;
6243
+ case 10:
6244
+ _context4.prev = 10;
6245
+ _context4.t0 = _context4["catch"](4);
6246
+ throw new Error("Invalid webhook URI: ".concat(_context4.t0.message));
6247
+ case 13:
6248
+ _context4.next = 15;
6227
6249
  return this.getToken({
6228
6250
  minimumLifetime: 600
6229
6251
  });
6230
- case 5:
6252
+ case 15:
6231
6253
  token = _context4.sent;
6232
6254
  query = {
6233
6255
  client_id: clientId,
@@ -6240,7 +6262,8 @@ var API = /*#__PURE__*/function () {
6240
6262
  provider_groups: providerGroups.join(','),
6241
6263
  theme: ['light', 'dark'].includes(theme) ? theme : 'light',
6242
6264
  providers_per_line: providersPerLine && ['1', '2'].includes(providersPerLine.toString()) ? providersPerLine.toString() : '2',
6243
- features: features
6265
+ features: features,
6266
+ webhook_uri: webhookURI
6244
6267
  }; // Cleanup blank params
6245
6268
  Object.keys(query).forEach(function (key) {
6246
6269
  return [undefined, null, ''].includes(query[key]) && delete query[key];
@@ -6254,12 +6277,12 @@ var API = /*#__PURE__*/function () {
6254
6277
  url: "".concat(url, "?").concat(queryString),
6255
6278
  token: token
6256
6279
  });
6257
- case 12:
6280
+ case 22:
6258
6281
  case "end":
6259
6282
  return _context4.stop();
6260
6283
  }
6261
6284
  }
6262
- }, _callee4, this);
6285
+ }, _callee4, this, [[4, 10]]);
6263
6286
  }));
6264
6287
  function getConnectData() {
6265
6288
  return _getConnectData.apply(this, arguments);
@@ -6313,15 +6336,16 @@ var API = /*#__PURE__*/function () {
6313
6336
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6314
6337
  if (!this.isBrowser) throw new Error('Only supported in Browser.');
6315
6338
  _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
6316
- var provider, providers, providerGroups, institutionId, lang, theme, providersPerLine, features, connectionType, origin, _yield$_this$getConne, url, token;
6339
+ var provider, providers, providerGroups, institutionId, lang, theme, providersPerLine, features, connectionType, origin, webhookURI, _yield$_this$getConne, url, token;
6317
6340
  return regeneratorRuntime.wrap(function _callee5$(_context5) {
6318
6341
  while (1) {
6319
6342
  switch (_context5.prev = _context5.next) {
6320
6343
  case 0:
6321
6344
  _context5.prev = 0;
6322
6345
  _this._widgetOpened = true;
6323
- provider = options.provider, providers = options.providers, providerGroups = options.providerGroups, institutionId = options.institutionId, lang = options.lang, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features, connectionType = options.connectionType, origin = options.origin;
6324
- _context5.next = 5;
6346
+ provider = options.provider, providers = options.providers, providerGroups = options.providerGroups, institutionId = options.institutionId, lang = options.lang, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features, connectionType = options.connectionType, origin = options.origin, webhookURI = options.webhookURI; // Store features for timeout calculation
6347
+ _this._features = features;
6348
+ _context5.next = 6;
6325
6349
  return _this.getConnectData({
6326
6350
  provider: provider,
6327
6351
  providers: providers,
@@ -6331,9 +6355,10 @@ var API = /*#__PURE__*/function () {
6331
6355
  theme: theme,
6332
6356
  providersPerLine: providersPerLine,
6333
6357
  features: features,
6334
- origin: origin
6358
+ origin: origin,
6359
+ webhookURI: webhookURI
6335
6360
  });
6336
- case 5:
6361
+ case 6:
6337
6362
  _yield$_this$getConne = _context5.sent;
6338
6363
  url = _yield$_this$getConne.url;
6339
6364
  token = _yield$_this$getConne.token;
@@ -6355,18 +6380,18 @@ var API = /*#__PURE__*/function () {
6355
6380
  _this._widgetActive = true;
6356
6381
  _this._addListeners();
6357
6382
  _this._addWatchers();
6358
- _context5.next = 19;
6383
+ _context5.next = 20;
6359
6384
  break;
6360
- case 16:
6361
- _context5.prev = 16;
6385
+ case 17:
6386
+ _context5.prev = 17;
6362
6387
  _context5.t0 = _context5["catch"](0);
6363
- _this._closeWidgetWithError(500, 'Connection refused');
6364
- case 19:
6388
+ _this._closeWidgetWithError(500, _context5.t0.message || 'Connection refused');
6389
+ case 20:
6365
6390
  case "end":
6366
6391
  return _context5.stop();
6367
6392
  }
6368
6393
  }
6369
- }, _callee5, null, [[0, 16]]);
6394
+ }, _callee5, null, [[0, 17]]);
6370
6395
  }))();
6371
6396
  }
6372
6397
  }, {
@@ -6422,10 +6447,16 @@ var API = /*#__PURE__*/function () {
6422
6447
  key: "_addWatchers",
6423
6448
  value: function _addWatchers() {
6424
6449
  var _this2 = this;
6425
- // Watch for widget timeout (10 minutes)
6450
+ // Determine timeout based on features
6451
+ var hasQuickRetry = this._features && this._features.split(',').map(function (f) {
6452
+ return f.trim();
6453
+ }).includes('quick_retry');
6454
+ var timeoutMinutes = hasQuickRetry ? 30 : 10;
6455
+
6456
+ // Watch for widget timeout
6426
6457
  var timeoutWatcher = setTimeout(function () {
6427
6458
  _this2._closeWidgetWithError(400, 'Connection timeout');
6428
- }, 10 * 60 * 1000);
6459
+ }, timeoutMinutes * 60 * 1000);
6429
6460
 
6430
6461
  // Watch for widget status (whether closed by user or successfully finished) and clean it up
6431
6462
  var doneWatcher = setInterval(function () {
package/dist/wealthica.js CHANGED
@@ -5990,6 +5990,7 @@ var API = /*#__PURE__*/function () {
5990
5990
  this._onWidgetMessage = this._onMessage.bind(this);
5991
5991
  this._widgetOpened = false;
5992
5992
  this._widgetActive = false;
5993
+ this._features = null;
5993
5994
  }
5994
5995
  _createClass(API, [{
5995
5996
  key: "_init",
@@ -6198,9 +6199,11 @@ var API = /*#__PURE__*/function () {
6198
6199
  theme,
6199
6200
  providersPerLine,
6200
6201
  features,
6202
+ webhookURI,
6201
6203
  _this$config5,
6202
6204
  clientId,
6203
6205
  connectURL,
6206
+ _url,
6204
6207
  token,
6205
6208
  query,
6206
6209
  queryString,
@@ -6211,13 +6214,32 @@ var API = /*#__PURE__*/function () {
6211
6214
  switch (_context4.prev = _context4.next) {
6212
6215
  case 0:
6213
6216
  options = _args4.length > 0 && _args4[0] !== undefined ? _args4[0] : {};
6214
- provider = options.provider, institutionId = options.institutionId, state = options.state, _options$origin = options.origin, origin = _options$origin === void 0 ? this.isBrowser ? window.location.origin : undefined : _options$origin, lang = options.lang, _options$redirectURI = options.redirectURI, redirectURI = _options$redirectURI === void 0 ? this.config.redirectURI : _options$redirectURI, providers = options.providers, _options$providerGrou = options.providerGroups, providerGroups = _options$providerGrou === void 0 ? ['core'] : _options$providerGrou, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features;
6215
- _this$config5 = this.config, clientId = _this$config5.clientId, connectURL = _this$config5.connectURL; // Get a token with at least 10 minutes left
6216
- _context4.next = 5;
6217
+ provider = options.provider, institutionId = options.institutionId, state = options.state, _options$origin = options.origin, origin = _options$origin === void 0 ? this.isBrowser ? window.location.origin : undefined : _options$origin, lang = options.lang, _options$redirectURI = options.redirectURI, redirectURI = _options$redirectURI === void 0 ? this.config.redirectURI : _options$redirectURI, providers = options.providers, _options$providerGrou = options.providerGroups, providerGroups = _options$providerGrou === void 0 ? ['core'] : _options$providerGrou, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features, webhookURI = options.webhookURI;
6218
+ _this$config5 = this.config, clientId = _this$config5.clientId, connectURL = _this$config5.connectURL; // Validate webhookURI if provided
6219
+ if (!webhookURI) {
6220
+ _context4.next = 13;
6221
+ break;
6222
+ }
6223
+ _context4.prev = 4;
6224
+ _url = new URL(webhookURI);
6225
+ if (!(_url.protocol !== 'https:')) {
6226
+ _context4.next = 8;
6227
+ break;
6228
+ }
6229
+ throw new Error('Webhook URI must use HTTPS protocol');
6230
+ case 8:
6231
+ _context4.next = 13;
6232
+ break;
6233
+ case 10:
6234
+ _context4.prev = 10;
6235
+ _context4.t0 = _context4["catch"](4);
6236
+ throw new Error("Invalid webhook URI: ".concat(_context4.t0.message));
6237
+ case 13:
6238
+ _context4.next = 15;
6217
6239
  return this.getToken({
6218
6240
  minimumLifetime: 600
6219
6241
  });
6220
- case 5:
6242
+ case 15:
6221
6243
  token = _context4.sent;
6222
6244
  query = {
6223
6245
  client_id: clientId,
@@ -6230,7 +6252,8 @@ var API = /*#__PURE__*/function () {
6230
6252
  provider_groups: providerGroups.join(','),
6231
6253
  theme: ['light', 'dark'].includes(theme) ? theme : 'light',
6232
6254
  providers_per_line: providersPerLine && ['1', '2'].includes(providersPerLine.toString()) ? providersPerLine.toString() : '2',
6233
- features: features
6255
+ features: features,
6256
+ webhook_uri: webhookURI
6234
6257
  }; // Cleanup blank params
6235
6258
  Object.keys(query).forEach(function (key) {
6236
6259
  return [undefined, null, ''].includes(query[key]) && delete query[key];
@@ -6244,12 +6267,12 @@ var API = /*#__PURE__*/function () {
6244
6267
  url: "".concat(url, "?").concat(queryString),
6245
6268
  token: token
6246
6269
  });
6247
- case 12:
6270
+ case 22:
6248
6271
  case "end":
6249
6272
  return _context4.stop();
6250
6273
  }
6251
6274
  }
6252
- }, _callee4, this);
6275
+ }, _callee4, this, [[4, 10]]);
6253
6276
  }));
6254
6277
  function getConnectData() {
6255
6278
  return _getConnectData.apply(this, arguments);
@@ -6303,15 +6326,16 @@ var API = /*#__PURE__*/function () {
6303
6326
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
6304
6327
  if (!this.isBrowser) throw new Error('Only supported in Browser.');
6305
6328
  _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee5() {
6306
- var provider, providers, providerGroups, institutionId, lang, theme, providersPerLine, features, connectionType, origin, _yield$_this$getConne, url, token;
6329
+ var provider, providers, providerGroups, institutionId, lang, theme, providersPerLine, features, connectionType, origin, webhookURI, _yield$_this$getConne, url, token;
6307
6330
  return regeneratorRuntime.wrap(function _callee5$(_context5) {
6308
6331
  while (1) {
6309
6332
  switch (_context5.prev = _context5.next) {
6310
6333
  case 0:
6311
6334
  _context5.prev = 0;
6312
6335
  _this._widgetOpened = true;
6313
- provider = options.provider, providers = options.providers, providerGroups = options.providerGroups, institutionId = options.institutionId, lang = options.lang, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features, connectionType = options.connectionType, origin = options.origin;
6314
- _context5.next = 5;
6336
+ provider = options.provider, providers = options.providers, providerGroups = options.providerGroups, institutionId = options.institutionId, lang = options.lang, theme = options.theme, providersPerLine = options.providersPerLine, features = options.features, connectionType = options.connectionType, origin = options.origin, webhookURI = options.webhookURI; // Store features for timeout calculation
6337
+ _this._features = features;
6338
+ _context5.next = 6;
6315
6339
  return _this.getConnectData({
6316
6340
  provider: provider,
6317
6341
  providers: providers,
@@ -6321,9 +6345,10 @@ var API = /*#__PURE__*/function () {
6321
6345
  theme: theme,
6322
6346
  providersPerLine: providersPerLine,
6323
6347
  features: features,
6324
- origin: origin
6348
+ origin: origin,
6349
+ webhookURI: webhookURI
6325
6350
  });
6326
- case 5:
6351
+ case 6:
6327
6352
  _yield$_this$getConne = _context5.sent;
6328
6353
  url = _yield$_this$getConne.url;
6329
6354
  token = _yield$_this$getConne.token;
@@ -6345,18 +6370,18 @@ var API = /*#__PURE__*/function () {
6345
6370
  _this._widgetActive = true;
6346
6371
  _this._addListeners();
6347
6372
  _this._addWatchers();
6348
- _context5.next = 19;
6373
+ _context5.next = 20;
6349
6374
  break;
6350
- case 16:
6351
- _context5.prev = 16;
6375
+ case 17:
6376
+ _context5.prev = 17;
6352
6377
  _context5.t0 = _context5["catch"](0);
6353
- _this._closeWidgetWithError(500, 'Connection refused');
6354
- case 19:
6378
+ _this._closeWidgetWithError(500, _context5.t0.message || 'Connection refused');
6379
+ case 20:
6355
6380
  case "end":
6356
6381
  return _context5.stop();
6357
6382
  }
6358
6383
  }
6359
- }, _callee5, null, [[0, 16]]);
6384
+ }, _callee5, null, [[0, 17]]);
6360
6385
  }))();
6361
6386
  }
6362
6387
  }, {
@@ -6412,10 +6437,16 @@ var API = /*#__PURE__*/function () {
6412
6437
  key: "_addWatchers",
6413
6438
  value: function _addWatchers() {
6414
6439
  var _this2 = this;
6415
- // Watch for widget timeout (10 minutes)
6440
+ // Determine timeout based on features
6441
+ var hasQuickRetry = this._features && this._features.split(',').map(function (f) {
6442
+ return f.trim();
6443
+ }).includes('quick_retry');
6444
+ var timeoutMinutes = hasQuickRetry ? 30 : 10;
6445
+
6446
+ // Watch for widget timeout
6416
6447
  var timeoutWatcher = setTimeout(function () {
6417
6448
  _this2._closeWidgetWithError(400, 'Connection timeout');
6418
- }, 10 * 60 * 1000);
6449
+ }, timeoutMinutes * 60 * 1000);
6419
6450
 
6420
6451
  // Watch for widget status (whether closed by user or successfully finished) and clean it up
6421
6452
  var doneWatcher = setInterval(function () {
@@ -96,6 +96,10 @@ type ConnectDataOptions = {
96
96
  redirectURI: string;
97
97
  providers: Array<string> | undefined;
98
98
  providerGroups: Array<string> | undefined;
99
+ theme: string;
100
+ providersPerLine: number | string;
101
+ features: string;
102
+ webhookURI: string;
99
103
  }
100
104
 
101
105
  type ConnectData = {