@notabene/javascript-sdk 2.16.0 → 2.17.0-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.16.0",
13
+ "version": "2.17.0-next.4",
14
14
  "source": "src/notabene.ts",
15
15
  "main": "dist/cjs/notabene.cjs",
16
16
  "module": "dist/esm/notabene.js",
@@ -107,4 +107,4 @@
107
107
  "@commitlint/config-conventional"
108
108
  ]
109
109
  }
110
- }
110
+ }
@@ -7,12 +7,10 @@ import type {
7
7
 
8
8
  export type OriginatorV2 = {
9
9
  originatorPerson: PersonV2[];
10
- customerIdentification?: string;
11
10
  };
12
11
 
13
12
  export type BeneficiaryV2 = {
14
13
  beneficiaryPerson: PersonV2[];
15
- customerIdentification?: string;
16
14
  };
17
15
 
18
16
  export type NaturalPersonNameIDV2 = {
@@ -27,6 +25,7 @@ export type NaturalPersonNameV2 = Omit<NaturalPersonName, 'nameIdentifier'> & {
27
25
 
28
26
  export type NaturalPersonV2 = Omit<NaturalPerson, 'name'> & {
29
27
  name: NaturalPersonNameV2;
28
+ customerIdentification?: string;
30
29
  };
31
30
 
32
31
  export type PersonV2 = Omit<Person, 'naturalPerson'> & {
package/src/notabene.ts CHANGED
@@ -14,6 +14,7 @@ import type {
14
14
  ComponentResponse,
15
15
  ConnectionOptions,
16
16
  ConnectionRequest,
17
+ ContactSupportConfig,
17
18
  CosmosMetadata,
18
19
  Counterparty,
19
20
  CounterpartyAssistConfig,
@@ -63,6 +64,7 @@ import type {
63
64
  ValidationError,
64
65
  VASP,
65
66
  VASPOptions,
67
+ VASPTrustStatus,
66
68
  Wallet,
67
69
  Withdrawal,
68
70
  } from './types';
@@ -73,6 +75,7 @@ import {
73
75
  ErrorIdentifierCode,
74
76
  HMType,
75
77
  IdentityVerificationMethod,
78
+ InfoIdentifierCode,
76
79
  PersonType,
77
80
  ProofStatus,
78
81
  ProofTypes,
@@ -116,6 +119,7 @@ export {
116
119
  ErrorIdentifierCode,
117
120
  HMType,
118
121
  IdentityVerificationMethod,
122
+ InfoIdentifierCode,
119
123
  PersonType,
120
124
  ProofStatus,
121
125
  ProofTypes,
@@ -139,6 +143,7 @@ export type {
139
143
  ComponentResponse,
140
144
  ConnectionOptions,
141
145
  ConnectionRequest,
146
+ ContactSupportConfig,
142
147
  CosmosMetadata,
143
148
  Counterparty,
144
149
  CounterpartyAssistConfig,
@@ -189,6 +194,7 @@ export type {
189
194
  ValidationError,
190
195
  VASP,
191
196
  VASPOptions,
197
+ VASPTrustStatus,
192
198
  Wallet,
193
199
  Withdrawal,
194
200
  };
@@ -191,9 +191,7 @@ export function componentResponseToV1TxCreateRequest(
191
191
  ? txCreate.transactionAsset
192
192
  : txCreate.transactionAsset?.caip19) ||
193
193
  '',
194
- amountDecimal:
195
- value?.amountDecimal ||
196
- (txCreate.transactionAmount ? parseFloat(txCreate.transactionAmount) : 0),
194
+ amountDecimal: value?.amountDecimal ?? txCreate.transactionAmount ?? 0,
197
195
  customer: value?.customer,
198
196
  } as Withdrawal;
199
197
 
package/src/types.ts CHANGED
@@ -516,7 +516,7 @@ type BeneficiaryFields = {
516
516
  type DepositRequestFields = {
517
517
  destination: BlockchainAddress | CAIP10;
518
518
  asset: TransactionAsset;
519
- amountDecimal: number;
519
+ amountDecimal: string | number;
520
520
  travelAddress?: TravelAddress;
521
521
  cryptoCredential?: CryptoCredential;
522
522
  };
@@ -572,7 +572,7 @@ export interface Transaction extends ComponentRequest {
572
572
  agent: Agent;
573
573
  counterparty: Counterparty;
574
574
  asset: TransactionAsset;
575
- amountDecimal: number;
575
+ amountDecimal: string | number;
576
576
  proof?: OwnershipProof;
577
577
  assetPrice?: {
578
578
  price: number;
@@ -789,14 +789,53 @@ export enum VASPSearchControl {
789
789
  }
790
790
 
791
791
  /**
792
- * Options for which VASPs to be searchable
792
+ * Trust status assigned to a VASP in the Notabene network.
793
+ *
794
+ * Used by {@link VASPOptions.showTrustStatus} to filter which VASPs are listed in the picker.
795
+ *
793
796
  * @public
794
797
  */
795
- export type VASPOptions = {
796
- addUnknown?: boolean;
797
- onlyActive?: boolean;
798
- searchable?: VASPSearchControl[]; // If array left empty all VASPs will be searchable
799
- };
798
+ export type VASPTrustStatus = 'TRUSTED' | 'NEW' | 'FLAGGED' | 'BANNED';
799
+
800
+ /**
801
+ * Options controlling which VASPs are listed and searchable in the picker.
802
+ *
803
+ * Two mutually exclusive variants:
804
+ *
805
+ * - **V1** — `addUnknown`, `onlyActive`, `searchable` (filters by {@link VASPSearchControl} status).
806
+ * - **V2** — `addUnknown`, `onlyActive`, `showTrustStatus` (filters by {@link VASPTrustStatus}).
807
+ *
808
+ * `searchable` (V1-only) cannot be combined with `showTrustStatus` (V2-only);
809
+ * TypeScript will reject the mix at compile time. `addUnknown` and `onlyActive` are valid in both variants.
810
+ *
811
+ * @example V1
812
+ * ```ts
813
+ * { addUnknown: true, onlyActive: true, searchable: [VASPSearchControl.ALLOWED] }
814
+ * ```
815
+ *
816
+ * @example V2
817
+ * ```ts
818
+ * { addUnknown: true, onlyActive: true, showTrustStatus: ['TRUSTED', 'NEW'] }
819
+ * ```
820
+ *
821
+ * @public
822
+ */
823
+ export type VASPOptions =
824
+ // V1 vasps options
825
+ | {
826
+ addUnknown?: boolean;
827
+ onlyActive?: boolean;
828
+ searchable?: VASPSearchControl[]; // If array left empty all VASPs will be searchable
829
+ }
830
+ // V2 vasps options
831
+ | {
832
+ // Typing `searchable` as `undefined` (rather than omitting it) makes TS reject
833
+ // mixing V1 and V2 options, e.g. { searchable: [...], showTrustStatus: [...] }.
834
+ searchable?: undefined;
835
+ addUnknown?: boolean;
836
+ onlyActive?: boolean;
837
+ showTrustStatus?: VASPTrustStatus[];
838
+ };
800
839
 
801
840
  /**
802
841
  * Available methods for identity verification
@@ -883,6 +922,7 @@ export interface ThresholdOptions {
883
922
  * - `'signature'` — wallet connection for ownership proof via signature
884
923
  * - `'manual-signing'` — ownership proof via manual message signing
885
924
  * - `'add-vasp'` — manually add an unlisted exchange/VASP (hosted flow)
925
+ * - `'contact-support'` — show a contact support button
886
926
  *
887
927
  * Options are automatically filtered by flow (e.g. `add-vasp` is ignored in self-hosted).
888
928
  * Including an option implicitly enables that capability.
@@ -895,7 +935,28 @@ export type SectionOption =
895
935
  | 'microtransfer' // ProofTypes.MicroTransfer
896
936
  | 'signature'
897
937
  | 'manual-signing'
898
- | 'add-vasp';
938
+ | 'add-vasp'
939
+ | 'contact-support';
940
+
941
+ /**
942
+ * Configuration for the contact support action.
943
+ *
944
+ * @remarks
945
+ * Contact support is **enabled** by including `'contact-support'` in
946
+ * `agentSections.main` or `agentSections.fallback`. This object only
947
+ * configures the behaviour when the feature is enabled.
948
+ *
949
+ * - With `contactSupport: { supportUrl: "..." }` — clicking sends an info
950
+ * message to the host **and** attempts to open the URL as a fallback.
951
+ * - Without `contactSupport` — clicking only sends an info message; the
952
+ * host decides what to do.
953
+ *
954
+ * @public
955
+ */
956
+ export interface ContactSupportConfig {
957
+ /** URL to open when the user clicks the support button */
958
+ supportUrl: string;
959
+ }
899
960
 
900
961
  /**
901
962
  * Explicit layout configuration for the agent selection step.
@@ -944,6 +1005,12 @@ export interface TransactionOptions {
944
1005
  vasps?: VASPOptions;
945
1006
  hide?: ValidationSections[]; // You can hide a specific section of the component by listing it here
946
1007
  counterpartyAssist?: CounterpartyAssistConfig;
1008
+ /**
1009
+ * Configuration for the contact support button.
1010
+ * Enablement is controlled via `agentSections` — include `'contact-support'`
1011
+ * in `main` or `fallback` to show the button.
1012
+ */
1013
+ contactSupport?: ContactSupportConfig;
947
1014
  autoSubmit?: boolean; // Defaults to false
948
1015
  }
949
1016
  /**
@@ -1072,16 +1139,26 @@ export type Warning = {
1072
1139
  identifier?: WarningIdentifierCode;
1073
1140
  };
1074
1141
 
1142
+ /**
1143
+ * Identifier codes for info messages
1144
+ * @public
1145
+ */
1146
+ export enum InfoIdentifierCode {
1147
+ CONTACT_SUPPORT = 'CONTACT_SUPPORT',
1148
+ }
1149
+
1075
1150
  /**
1076
1151
  * Represents an info component message
1077
1152
  * @param message - Info message
1078
1153
  * @param description - Description of the info message
1154
+ * @param identifier - Identifier code of the info message
1079
1155
  * @public
1080
1156
  */
1081
1157
  export type Info = {
1082
1158
  type: CMType.INFO;
1083
1159
  message: string;
1084
1160
  description?: string;
1161
+ identifier?: InfoIdentifierCode;
1085
1162
  };
1086
1163
 
1087
1164
  /**
@@ -1,6 +1,7 @@
1
1
  import fc from 'fast-check';
2
2
  import type {
3
3
  Agent,
4
+ AgentSections,
4
5
  BlockchainAddress,
5
6
  CAIP10,
6
7
  CAIP19,
@@ -9,6 +10,7 @@ import type {
9
10
  CallbackOptions,
10
11
  ConnectionOptions,
11
12
  ConnectionRequest,
13
+ ContactSupportConfig,
12
14
  Counterparty,
13
15
  CryptoCredential,
14
16
  Deposit,
@@ -19,11 +21,13 @@ import type {
19
21
  ISOCurrency,
20
22
  ISODate,
21
23
  NaturalPerson,
24
+ SectionOption,
22
25
  ThresholdOptions,
23
26
  TransactionAsset,
24
27
  TransactionOptions,
25
28
  TravelAddress,
26
29
  VASPOptions,
30
+ VASPTrustStatus,
27
31
  Withdrawal,
28
32
  } from '../types';
29
33
  import {
@@ -31,6 +35,7 @@ import {
31
35
  PersonType,
32
36
  ProofTypes,
33
37
  ValidationSections,
38
+ VASPSearchControl,
34
39
  } from '../types';
35
40
  import {
36
41
  CAIP10_MATCHER,
@@ -91,6 +96,18 @@ export const arbitraryAgent = (): fc.Arbitrary<Agent> =>
91
96
  verified: fc.boolean(),
92
97
  });
93
98
 
99
+ // Generates decimal strings with 18+ fractional digits to test precision beyond float64
100
+ const arbitraryHighPrecisionDecimal = (): fc.Arbitrary<string> =>
101
+ fc
102
+ .tuple(
103
+ fc.integer({ min: 0, max: 999999 }),
104
+ fc.stringMatching(/^\d{18,24}$/),
105
+ )
106
+ .map(([integer, fractional]) => `${integer}.${fractional}`);
107
+
108
+ const arbitraryAmountDecimal = (): fc.Arbitrary<string | number> =>
109
+ fc.oneof(fc.float({ min: 0, noNaN: true }), arbitraryHighPrecisionDecimal());
110
+
94
111
  export const arbitraryCounterparty = (): fc.Arbitrary<Counterparty> =>
95
112
  arbitraryNaturalPerson(); // For simplicity we'll just use NaturalPerson
96
113
 
@@ -99,7 +116,7 @@ export const arbitraryWithdrawal = (): fc.Arbitrary<Withdrawal> =>
99
116
  agent: arbitraryAgent(),
100
117
  counterparty: arbitraryCounterparty(),
101
118
  asset: arbitraryTransactionAsset(),
102
- amountDecimal: fc.float(),
119
+ amountDecimal: arbitraryAmountDecimal(),
103
120
  destination: fc.oneof(arbitraryBlockchainAddress(), arbitraryCAIP10()),
104
121
  });
105
122
 
@@ -149,7 +166,7 @@ export const arbitraryDepositRequest = (): fc.Arbitrary<DepositRequest> =>
149
166
  agent: arbitraryAgent(),
150
167
  counterparty: arbitraryCounterparty(),
151
168
  asset: arbitraryTransactionAsset(),
152
- amountDecimal: fc.float(),
169
+ amountDecimal: arbitraryAmountDecimal(),
153
170
  destination: fc.oneof(arbitraryBlockchainAddress(), arbitraryCAIP10()),
154
171
  travelAddress: fc.option(arbitraryTravelAddress()),
155
172
  cryptoCredential: fc.option(arbitraryCryptoCredential()),
@@ -194,14 +211,63 @@ export const arbitraryFieldTypes = (): fc.Arbitrary<FieldTypes> =>
194
211
  });
195
212
 
196
213
  export const arbitraryVASPOptions = (): fc.Arbitrary<VASPOptions> =>
214
+ fc.oneof(
215
+ fc.record({
216
+ addUnknown: fc.option(fc.boolean(), { nil: undefined }),
217
+ onlyActive: fc.option(fc.boolean(), { nil: undefined }),
218
+ searchable: fc.option(
219
+ fc.array(
220
+ fc.constantFrom(VASPSearchControl.ALLOWED, VASPSearchControl.PENDING),
221
+ ),
222
+ { nil: undefined },
223
+ ),
224
+ }),
225
+ fc.record({
226
+ addUnknown: fc.option(fc.boolean(), { nil: undefined }),
227
+ onlyActive: fc.option(fc.boolean(), { nil: undefined }),
228
+ showTrustStatus: fc.option(
229
+ fc.array(
230
+ fc.constantFrom<VASPTrustStatus>(
231
+ 'TRUSTED',
232
+ 'NEW',
233
+ 'FLAGGED',
234
+ 'BANNED',
235
+ ),
236
+ ),
237
+ { nil: undefined },
238
+ ),
239
+ }),
240
+ );
241
+
242
+ const SECTION_OPTIONS: SectionOption[] = [
243
+ 'self-declaration',
244
+ 'screenshot',
245
+ 'microtransfer',
246
+ 'signature',
247
+ 'manual-signing',
248
+ 'add-vasp',
249
+ 'contact-support',
250
+ ];
251
+
252
+ export const arbitrarySectionOption = (): fc.Arbitrary<SectionOption> =>
253
+ fc.constantFrom(...SECTION_OPTIONS);
254
+
255
+ export const arbitraryAgentSections = (): fc.Arbitrary<AgentSections> =>
197
256
  fc.record({
198
- addUnknown: fc.option(fc.boolean()),
199
- onlyActive: fc.option(fc.boolean()),
257
+ main: fc.option(fc.array(arbitrarySectionOption())),
258
+ fallback: fc.option(fc.array(arbitrarySectionOption())),
200
259
  });
201
260
 
261
+ export const arbitraryContactSupportConfig =
262
+ (): fc.Arbitrary<ContactSupportConfig> =>
263
+ fc.record({
264
+ supportUrl: fc.webUrl(),
265
+ });
266
+
202
267
  export const arbitraryTransactionOptions =
203
268
  (): fc.Arbitrary<TransactionOptions> =>
204
269
  fc.record({
270
+ agentSections: fc.option(arbitraryAgentSections()),
205
271
  proofs: fc.option(
206
272
  fc.record({
207
273
  microTransfer: fc.option(
@@ -228,6 +294,7 @@ export const arbitraryTransactionOptions =
228
294
  hide: fc.option(
229
295
  fc.array(fc.constantFrom(...Object.values(ValidationSections))),
230
296
  ),
297
+ contactSupport: fc.option(arbitraryContactSupportConfig()),
231
298
  });
232
299
 
233
300
  export const arbitraryDepositRequestOptions =
@@ -249,7 +316,7 @@ export const arbitraryDeposit = (): fc.Arbitrary<Deposit> =>
249
316
  agent: arbitraryAgent(),
250
317
  counterparty: arbitraryCounterparty(),
251
318
  asset: arbitraryTransactionAsset(),
252
- amountDecimal: fc.float({ min: 0, max: 1e6 }),
319
+ amountDecimal: arbitraryAmountDecimal(),
253
320
  origin: fc.oneof(arbitraryBlockchainAddress(), arbitraryCAIP10()),
254
321
  source: fc.oneof(arbitraryBlockchainAddress(), arbitraryCAIP10()),
255
322
  });