@notabene/javascript-sdk 2.14.2-next.2 → 2.14.2-next.4

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
@@ -10,7 +10,7 @@
10
10
  "author": "Notabene <developers@notabene.id>",
11
11
  "license": "MIT",
12
12
  "packageManager": "yarn@4.5.1",
13
- "version": "2.14.2-next.2",
13
+ "version": "2.14.2-next.4",
14
14
  "source": "src/notabene.ts",
15
15
  "main": "dist/cjs/notabene.cjs",
16
16
  "module": "dist/esm/notabene.js",
@@ -1,5 +1,5 @@
1
1
  import { fc, test } from '@fast-check/vitest';
2
- import { describe } from 'vitest';
2
+ import { describe, expect, it } from 'vitest';
3
3
  import Notabene from '../notabene';
4
4
  import {
5
5
  abitraryCallbackOptions,
@@ -14,11 +14,13 @@ import {
14
14
  arbitraryWithdrawal,
15
15
  } from '../utils/arbitraries';
16
16
 
17
+ const arbitraryNodeUrl = () => fc.webUrl().map((u) => u.replace(/\/+$/, ''));
18
+
17
19
  describe('Notabene', () => {
18
20
  describe('defaults', () => {
19
21
  test.prop([
20
22
  fc.string({ minLength: 3 }),
21
- fc.webUrl(),
23
+ arbitraryNodeUrl(),
22
24
  arbitraryComponent(),
23
25
  fc.object(),
24
26
  ])(
@@ -32,7 +34,7 @@ describe('Notabene', () => {
32
34
  return (
33
35
  url.hash ===
34
36
  `#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify(value))}` &&
35
- url.searchParams.get('nodeUrl') === nodeUrl &&
37
+ url.searchParams.get('nodeUrl') === nodeUrl.replace(/\/+$/, '') &&
36
38
  url.pathname === `/${component}`
37
39
  );
38
40
  },
@@ -42,7 +44,7 @@ describe('Notabene', () => {
42
44
  describe('locale', () => {
43
45
  test.prop([
44
46
  fc.string({ minLength: 3 }),
45
- fc.webUrl(),
47
+ arbitraryNodeUrl(),
46
48
  arbitraryComponent(),
47
49
  fc.object(),
48
50
  arbitraryLocale(),
@@ -84,7 +86,7 @@ describe('Notabene', () => {
84
86
  describe('with uxUrl', () => {
85
87
  test.prop([
86
88
  fc.string({ minLength: 3 }),
87
- fc.webUrl(),
89
+ arbitraryNodeUrl(),
88
90
  arbitraryComponent(),
89
91
  fc.webAuthority(),
90
92
  fc.object(),
@@ -113,7 +115,7 @@ describe('Notabene', () => {
113
115
  describe('with value and configuration', () => {
114
116
  test.prop([
115
117
  fc.string({ minLength: 3 }),
116
- fc.webUrl(),
118
+ arbitraryNodeUrl(),
117
119
  arbitraryComponent(),
118
120
  fc.object(),
119
121
  fc.object(),
@@ -140,7 +142,7 @@ describe('Notabene', () => {
140
142
  describe('with value and configuration', () => {
141
143
  test.prop([
142
144
  fc.string({ minLength: 3 }),
143
- fc.webUrl(),
145
+ arbitraryNodeUrl(),
144
146
  arbitraryComponent(),
145
147
  fc.object(),
146
148
  fc.object(),
@@ -170,7 +172,7 @@ describe('Notabene', () => {
170
172
  describe('createWithdrawalAssist', () => {
171
173
  test.prop([
172
174
  fc.string({ minLength: 3 }), // authToken
173
- fc.webUrl(), // nodeUrl
175
+ arbitraryNodeUrl(), // nodeUrl
174
176
  arbitraryWithdrawal(),
175
177
  arbitraryTransactionOptions(), // options
176
178
  abitraryCallbackOptions(), // callbacks
@@ -204,7 +206,7 @@ describe('Notabene', () => {
204
206
  describe('createDepositRequest', () => {
205
207
  test.prop([
206
208
  fc.string({ minLength: 3 }), // authToken
207
- fc.webUrl(), // nodeUrl
209
+ arbitraryNodeUrl(), // nodeUrl
208
210
  arbitraryDepositRequest(),
209
211
  arbitraryDepositRequestOptions(), // options
210
212
  abitraryCallbackOptions(), // callbacks
@@ -238,7 +240,7 @@ describe('Notabene', () => {
238
240
  describe('createConnectWallet', () => {
239
241
  test.prop([
240
242
  fc.string({ minLength: 3 }), // authToken
241
- fc.webUrl(), // nodeUrl
243
+ arbitraryNodeUrl(), // nodeUrl
242
244
  arbitraryConnectionRequest(),
243
245
  arbitraryConnectionOptions(), // options
244
246
  abitraryCallbackOptions(), // callbacks
@@ -268,10 +270,80 @@ describe('Notabene', () => {
268
270
  },
269
271
  );
270
272
  });
273
+ describe('nodeUrl trailing slash normalization', () => {
274
+ it('should strip a single trailing slash', () => {
275
+ const notabene = new Notabene({
276
+ nodeUrl: 'https://api.eu1.notabene.id/',
277
+ authToken: 'token',
278
+ });
279
+ const url = new URL(notabene.componentUrl('withdrawal-assist', {}));
280
+ expect(url.searchParams.get('nodeUrl')).toBe(
281
+ 'https://api.eu1.notabene.id',
282
+ );
283
+ });
284
+
285
+ it('should strip multiple trailing slashes', () => {
286
+ const notabene = new Notabene({
287
+ nodeUrl: 'https://api.eu1.notabene.id///',
288
+ authToken: 'token',
289
+ });
290
+ const url = new URL(notabene.componentUrl('withdrawal-assist', {}));
291
+ expect(url.searchParams.get('nodeUrl')).toBe(
292
+ 'https://api.eu1.notabene.id',
293
+ );
294
+ });
295
+
296
+ it('should leave a clean URL unchanged', () => {
297
+ const notabene = new Notabene({
298
+ nodeUrl: 'https://api.eu1.notabene.id',
299
+ authToken: 'token',
300
+ });
301
+ const url = new URL(notabene.componentUrl('withdrawal-assist', {}));
302
+ expect(url.searchParams.get('nodeUrl')).toBe(
303
+ 'https://api.eu1.notabene.id',
304
+ );
305
+ });
306
+
307
+ it('should trim whitespace', () => {
308
+ const notabene = new Notabene({
309
+ nodeUrl: ' https://api.eu1.notabene.id ',
310
+ authToken: 'token',
311
+ });
312
+ const url = new URL(notabene.componentUrl('withdrawal-assist', {}));
313
+ expect(url.searchParams.get('nodeUrl')).toBe(
314
+ 'https://api.eu1.notabene.id',
315
+ );
316
+ });
317
+
318
+ it('should throw for an invalid URL', () => {
319
+ expect(
320
+ () => new Notabene({ nodeUrl: 'not-a-url', authToken: 'token' }),
321
+ ).toThrow('Invalid nodeUrl');
322
+ });
323
+
324
+ it('should throw for a non-http protocol', () => {
325
+ expect(
326
+ () =>
327
+ new Notabene({ nodeUrl: 'ftp://example.com', authToken: 'token' }),
328
+ ).toThrow('must start with http:// or https://');
329
+ });
330
+
331
+ it('should preserve URL paths', () => {
332
+ const notabene = new Notabene({
333
+ nodeUrl: 'https://api.notabene.id/v2',
334
+ authToken: 'token',
335
+ });
336
+ const url = new URL(notabene.componentUrl('withdrawal-assist', {}));
337
+ expect(url.searchParams.get('nodeUrl')).toBe(
338
+ 'https://api.notabene.id/v2',
339
+ );
340
+ });
341
+ });
342
+
271
343
  describe('createDepositAssist', () => {
272
344
  test.prop([
273
345
  fc.string({ minLength: 3 }), // authToken
274
- fc.webUrl(), // nodeUrl
346
+ arbitraryNodeUrl(), // nodeUrl
275
347
  arbitraryDeposit(),
276
348
  arbitraryTransactionOptions(), // options
277
349
  abitraryCallbackOptions(), // callbacks
package/src/notabene.ts CHANGED
@@ -70,7 +70,6 @@ import {
70
70
  ErrorIdentifierCode,
71
71
  HMType,
72
72
  IdentityVerificationMethod,
73
- OAuthProvider,
74
73
  PersonType,
75
74
  ProofStatus,
76
75
  ProofTypes,
@@ -113,7 +112,6 @@ export {
113
112
  ErrorIdentifierCode,
114
113
  HMType,
115
114
  IdentityVerificationMethod,
116
- OAuthProvider,
117
115
  PersonType,
118
116
  ProofStatus,
119
117
  ProofTypes,
@@ -228,6 +226,23 @@ export interface NotabeneConfig {
228
226
  *
229
227
  * @public
230
228
  */
229
+ /** Trim whitespace, validate, and strip trailing slashes from a URL. */
230
+ function normalizeUrl(url: string, field: string): string {
231
+ const normalized = url.trim().replace(/\/+$/, '');
232
+ let parsed: URL;
233
+ try {
234
+ parsed = new URL(normalized);
235
+ } catch {
236
+ throw new Error(`Invalid ${field}: "${url}" is not a valid URL`);
237
+ }
238
+ if (!['http:', 'https:'].includes(parsed.protocol)) {
239
+ throw new Error(
240
+ `Invalid ${field}: "${url}" (must start with http:// or https://)`,
241
+ );
242
+ }
243
+ return normalized;
244
+ }
245
+
231
246
  export default class Notabene {
232
247
  private nodeUrl?: string;
233
248
  private authToken?: string;
@@ -241,8 +256,13 @@ export default class Notabene {
241
256
  * @param config - Configuration options for the Notabene SDK
242
257
  */
243
258
  constructor(config: NotabeneConfig) {
244
- this.uxUrl = config.uxUrl || 'https://connect.notabene.id';
245
- this.nodeUrl = config.nodeUrl;
259
+ this.uxUrl = normalizeUrl(
260
+ config.uxUrl || 'https://connect.notabene.id',
261
+ 'uxUrl',
262
+ );
263
+ this.nodeUrl = config.nodeUrl
264
+ ? normalizeUrl(config.nodeUrl, 'nodeUrl')
265
+ : undefined;
246
266
  this.authToken = config.authToken;
247
267
  this.theme = config.theme;
248
268
  this.locale = config.locale;
@@ -9,7 +9,7 @@ import { Deposit, Withdrawal } from '../types';
9
9
  export function isDeposit(
10
10
  transaction: Withdrawal | Deposit,
11
11
  ): transaction is Deposit {
12
- return 'source' in transaction && transaction.source !== undefined;
12
+ return (transaction as Deposit).source !== undefined;
13
13
  }
14
14
 
15
15
  export function isWithdrawal(
package/src/types.ts CHANGED
@@ -792,7 +792,6 @@ export type VASPOptions = {
792
792
  */
793
793
  export enum IdentityVerificationMethod {
794
794
  SMS = 'sms',
795
- EMAIL = 'email',
796
795
  }
797
796
 
798
797
  /**
@@ -808,14 +807,6 @@ export enum CodeVerificationStatus {
808
807
  UNREACHABLE = 'unreachable',
809
808
  }
810
809
 
811
- /**
812
- * Supported OAuth providers for authentication
813
- * @public
814
- */
815
- export enum OAuthProvider {
816
- COINBASE = 'coinbase',
817
- }
818
-
819
810
  /**
820
811
  * Configuration options for identity verification
821
812
  * @public
@@ -823,8 +814,6 @@ export enum OAuthProvider {
823
814
  export type IdentityVerificationConfig = {
824
815
  /** The required verification method. If not specified, none will be used */
825
816
  requiredMethod?: IdentityVerificationMethod;
826
- /** OAuth provider(s) to use for authentication. Can be a single provider or array of providers */
827
- oAuth?: OAuthProvider[] | OAuthProvider;
828
817
  };
829
818
 
830
819
  /**
@@ -839,6 +828,7 @@ export type CounterpartyAssistConfig =
839
828
  | boolean
840
829
  | {
841
830
  counterpartyTypes: PersonType[];
831
+ /** @remarks Requires a transactionId to be passed in. */
842
832
  identityVerification?: IdentityVerificationConfig;
843
833
  };
844
834