@monerium/sdk 3.4.10 → 3.5.0

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
@@ -98,6 +98,7 @@ We recommend starting in the [Developer Portal](https://docs.monerium.com). Ther
98
98
  > Client Credentials is used when there's no need for user interaction, and the system-to-system interaction requires authentication.
99
99
 
100
100
  ```ts
101
+ // Current version - Deprecated in v4
101
102
  import { MoneriumClient } from '@monerium/sdk';
102
103
  // Initialize the client with credentials
103
104
  const monerium = new MoneriumClient({
@@ -116,6 +117,71 @@ const { access_token, refresh_token } = monerium.bearerProfile as BearerProfile;
116
117
 
117
118
  // Use refresh token to get a new access token
118
119
  await monerium.getAccess(refresh_token);
120
+
121
+ /*
122
+ * Upcoming v4 - factory function
123
+ */
124
+
125
+ import {
126
+ randomPKCECodeVerifier,
127
+ calculatePKCECodeChallenge,
128
+ buildAuthorizationUrl,
129
+ authorizationCodeGrant,
130
+ refreshTokenGrant,
131
+ createMoneriumClient,
132
+ } from '@monerium/sdk';
133
+
134
+ // --- Initiate login ---
135
+ const codeVerifier = randomPKCECodeVerifier();
136
+ const codeChallenge = calculatePKCECodeChallenge(codeVerifier);
137
+ session.set('pkce_verifier', codeVerifier); // server-side session
138
+
139
+ const url = buildAuthorizationUrl({
140
+ environment: 'sandbox',
141
+ clientId: 'your-client-id',
142
+ redirectUri: 'https://your-app.com/callback',
143
+ codeChallenge,
144
+ });
145
+ res.redirect(url);
146
+
147
+ // --- On the callback page ---
148
+ const { code } = parseAuthorizationResponse(
149
+ new URL(req.url, 'https://your-app.com')
150
+ );
151
+ const codeVerifier = session.get('pkce_verifier');
152
+ session.delete('pkce_verifier');
153
+
154
+ const bearerProfile = await authorizationCodeGrant({
155
+ environment: 'sandbox',
156
+ clientId: 'your-client-id',
157
+ redirectUri: 'https://your-app.com/callback',
158
+ code,
159
+ codeVerifier,
160
+ });
161
+
162
+ req.session.accessToken = bearerProfile.access_token;
163
+ req.session.refreshToken = bearerProfile.refresh_token;
164
+ req.session.accessExpiry = Date.now() + bearerProfile.expires_in * 1000;
165
+
166
+ // --- Use the API ---
167
+ const client = createMoneriumClient({
168
+ environment: 'sandbox',
169
+ getAccessToken: async () => {
170
+ if (Date.now() > session.accessExpiry) {
171
+ const newProfile = await refreshTokenGrant({
172
+ environment: 'sandbox',
173
+ clientId: 'your-client-id',
174
+ refreshToken: session.refreshToken,
175
+ });
176
+ session.accessToken = newProfile.access_token;
177
+ session.accessExpiry = Date.now() + newProfile.expires_in * 1000;
178
+ return newProfile.access_token;
179
+ }
180
+ return session.accessToken;
181
+ },
182
+ });
183
+
184
+ const profiles = await client.getProfiles();
119
185
  ```
120
186
 
121
187
  API documentation:
package/dist/index.d.ts CHANGED
@@ -1,3 +1,115 @@
1
+ type TransportRequest = {
2
+ method: string;
3
+ url: string;
4
+ headers: Record<string, string>;
5
+ body?: BodyInit | string;
6
+ signal?: AbortSignal;
7
+ };
8
+ type TransportResponse = {
9
+ status: number;
10
+ headers?: Record<string, string>;
11
+ bodyText: string;
12
+ };
13
+ /**
14
+ * Replaces the internal `fetch` call. Headers (`Authorization`, `Content-Type`,
15
+ * `Accept`) are pre-populated. Must return a `Promise` resolving with the raw
16
+ * response `status` and `bodyText`. Throw on network-level failures.
17
+ * The SDK owns JSON parsing and error normalisation.
18
+ */
19
+ type Transport = (request: TransportRequest) => Promise<TransportResponse>;
20
+
21
+ /**
22
+ * Single source of truth for all supported EVM chain pairs.
23
+ *
24
+ * Each entry is a { production, sandbox } pair sharing the same network family.
25
+ *
26
+ * ── Adding a new EVM chain ────────────────────────────────────────────────────
27
+ * Add ONE entry to EVM_CHAIN_PAIRS below. All types (ProductionChain,
28
+ * SandboxChain, EvmChainId) and all lookup maps (chainIdToName,
29
+ * validEvmChainNames, productionToSandbox) are derived automatically.
30
+ * ─────────────────────────────────────────────────────────────────────────────
31
+ */
32
+ declare const EVM_CHAIN_PAIRS: readonly [{
33
+ readonly production: {
34
+ readonly id: "ethereum";
35
+ readonly chainId: 1;
36
+ };
37
+ readonly sandbox: {
38
+ readonly id: "sepolia";
39
+ readonly chainId: 11155111;
40
+ };
41
+ }, {
42
+ readonly production: {
43
+ readonly id: "gnosis";
44
+ readonly chainId: 100;
45
+ };
46
+ readonly sandbox: {
47
+ readonly id: "chiado";
48
+ readonly chainId: 10200;
49
+ };
50
+ }, {
51
+ readonly production: {
52
+ readonly id: "polygon";
53
+ readonly chainId: 137;
54
+ };
55
+ readonly sandbox: {
56
+ readonly id: "amoy";
57
+ readonly chainId: 80002;
58
+ };
59
+ }, {
60
+ readonly production: {
61
+ readonly id: "arbitrum";
62
+ readonly chainId: 42161;
63
+ };
64
+ readonly sandbox: {
65
+ readonly id: "arbitrumsepolia";
66
+ readonly chainId: 421614;
67
+ };
68
+ }, {
69
+ readonly production: {
70
+ readonly id: "linea";
71
+ readonly chainId: 59144;
72
+ };
73
+ readonly sandbox: {
74
+ readonly id: "lineasepolia";
75
+ readonly chainId: 59141;
76
+ };
77
+ }, {
78
+ readonly production: {
79
+ readonly id: "scroll";
80
+ readonly chainId: 534352;
81
+ };
82
+ readonly sandbox: {
83
+ readonly id: "scrollsepolia";
84
+ readonly chainId: 534351;
85
+ };
86
+ }, {
87
+ readonly production: {
88
+ readonly id: "base";
89
+ readonly chainId: 8453;
90
+ };
91
+ readonly sandbox: {
92
+ readonly id: "basesepolia";
93
+ readonly chainId: 84532;
94
+ };
95
+ }, {
96
+ readonly production: {
97
+ readonly id: "camino";
98
+ readonly chainId: 500;
99
+ };
100
+ readonly sandbox: {
101
+ readonly id: "columbus";
102
+ readonly chainId: 501;
103
+ };
104
+ }];
105
+ type ProductionChain = (typeof EVM_CHAIN_PAIRS)[number]['production']['id'] | 'noble';
106
+ type SandboxChain = (typeof EVM_CHAIN_PAIRS)[number]['sandbox']['id'] | 'grand';
107
+ /**
108
+ * All known EVM chain IDs. The union extends `number` for backwards
109
+ * compatibility — known values are listed in EVM_CHAIN_PAIRS above.
110
+ */
111
+ type EvmChainId = number | (typeof EVM_CHAIN_PAIRS)[number]['production' | 'sandbox']['chainId'];
112
+
1
113
  type Environment = {
2
114
  name: ENV;
3
115
  api: string;
@@ -11,10 +123,8 @@ type Config = {
11
123
  };
12
124
  };
13
125
  type ENV = 'sandbox' | 'production';
14
- type SandboxChain = 'sepolia' | 'chiado' | 'amoy' | 'arbitrumsepolia' | 'lineasepolia' | 'scrollsepolia' | 'columbus' | 'grand';
15
- type ProductionChain = 'ethereum' | 'gnosis' | 'polygon' | 'arbitrum' | 'linea' | 'scroll' | 'camino' | 'noble';
126
+
16
127
  type Chain = string | ProductionChain | SandboxChain;
17
- type EvmChainId = number | 1 | 11155111 | 100 | 10200 | 500 | 501 | 137 | 80002 | 42161 | 421614 | 59141 | 59144 | 534352 | 534351;
18
128
  type ChainId = EvmChainId | CosmosChainId;
19
129
  type CosmosChainId = 'noble-1' | 'grand-1' | 'florin-1';
20
130
  declare enum Currency {
@@ -93,7 +203,10 @@ interface PKCERequest extends PKCERequestShared {
93
203
  signature?: string;
94
204
  /** The network of the wallet to automatically link */
95
205
  chain?: Chain | ChainId;
96
- /** You can skip the connect wallet and request IBAN steps in the Authorization Flow and use the Link Address and Request IBAN API endpoints after you have gotten the authorization */
206
+ /**
207
+ * You can skip the connect wallet and request IBAN steps in the Authorization Flow and use the Link Address and Request IBAN API endpoints after you have gotten the authorization
208
+ * @deprecated Account creation is no longer offered in the auth flow
209
+ * */
97
210
  skip_create_account?: boolean;
98
211
  /** You can skip the KYC onboarding steps in the Authorization Flow and use the the details, additional data, and verifications API endpoints after you have gotten the authorization. */
99
212
  skip_kyc?: boolean;
@@ -494,6 +607,9 @@ interface OrderNotificationQueryParams {
494
607
  state?: OrderState;
495
608
  profile?: string;
496
609
  }
610
+ /**
611
+ * @deprecated Will be removed in v4 in favour of 'MoneriumClientOptions'
612
+ */
497
613
  type ClassOptions = {
498
614
  environment?: ENV;
499
615
  debug?: boolean;
@@ -502,10 +618,16 @@ interface AuthFlowOptionsShared {
502
618
  /** the state oauth parameter */
503
619
  state?: string;
504
620
  }
621
+ /**
622
+ * @deprecated Will be removed in v4 in favour of 'BuildAuthorizationUrlOptions'
623
+ */
505
624
  interface AuthFlowOptions extends AuthFlowOptionsShared {
506
625
  /** the email of the user to prefill the login form */
507
626
  email?: string;
508
- /** skip account creation in auth flow */
627
+ /**
628
+ * skip account creation in auth flow
629
+ * @deprecated: acccount creation is no longer offered in the auth flow
630
+ */
509
631
  skipCreateAccount?: boolean;
510
632
  /** skip KYC in auth flow */
511
633
  skipKyc?: boolean;
@@ -516,6 +638,9 @@ interface AuthFlowOptions extends AuthFlowOptionsShared {
516
638
  /** the chain of the address */
517
639
  chain?: Chain | ChainId;
518
640
  }
641
+ /**
642
+ * @deprecated Will be removed in v4 in favour of 'BuildSiweAuthorizationUrlOptions'
643
+ */
519
644
  interface AuthFlowSIWEOptions extends AuthFlowOptionsShared {
520
645
  /** Signature for the SIWE message. Must include the 0x prefix. */
521
646
  signature: string;
@@ -595,7 +720,358 @@ interface SignaturesResponse {
595
720
  total: number;
596
721
  }
597
722
 
723
+ type MoneriumClientOptions = {
724
+ environment?: ENV;
725
+ getAccessToken: () => string | Promise<string>;
726
+ accessToken?: never;
727
+ transport?: Transport;
728
+ } | {
729
+ environment?: ENV;
730
+ accessToken: string;
731
+ getAccessToken?: never;
732
+ transport?: Transport;
733
+ } | {
734
+ environment?: ENV;
735
+ accessToken?: never;
736
+ getAccessToken?: never;
737
+ transport?: Transport;
738
+ };
739
+ /**
740
+ * Creates a Monerium client instance.
741
+ * @beta
742
+ * @group v4
743
+ * @category v4 - Client instance.
744
+ */
745
+ declare function createMoneriumClient(options: MoneriumClientOptions): {
746
+ /**
747
+ * @group Authentication
748
+ * @see {@link https://docs.monerium.com/api#tag/auth/operation/auth-context | API Documentation}
749
+ */
750
+ getAuthContext: () => Promise<AuthContext>;
751
+ /**
752
+ * @group Profiles
753
+ * @param {string} profile - the id of the profile to fetch.
754
+ * @see {@link https://docs.monerium.com/api#tag/profiles/operation/profile | API Documentation}
755
+ */
756
+ getProfile: (id: string) => Promise<Profile>;
757
+ /**
758
+ * @group Profiles
759
+ * @see {@link https://docs.monerium.com/api#tag/profiles/operation/profiles | API Documentation}
760
+ */
761
+ getProfiles: (params?: ProfilesQueryParams) => Promise<ProfilesResponse>;
762
+ /**
763
+ * @group Profiles
764
+ * @see {@link https://docs.monerium.com/api#tag/profiles/operation/patch-profile-details | API Documentation}
765
+ */
766
+ submitProfileDetails: (profileId: string, body: SubmitProfileDetailsPayload) => Promise<ResponseStatus>;
767
+ /**
768
+ * Get details for a single address by using the address public key after the
769
+ * address has been successfully linked to Monerium.
770
+ *
771
+ * @group Addresses
772
+ * @param {string} address - The public key of the blockchain account.
773
+ * @see {@link https://docs.monerium.com/api#tag/addresses/operation/address | API Documentation}
774
+ */
775
+ getAddress: (address: string) => Promise<Address>;
776
+ /**
777
+ * @group Addresses
778
+ * @param {AddressesQueryParams} [params] - No required parameters.
779
+ * @see {@link https://docs.monerium.com/api#tag/addresses/operation/addresses | API Documentation}
780
+ */
781
+ getAddresses: (params?: AddressesQueryParams) => Promise<AddressesResponse>;
782
+ /**
783
+ * @group Addresses
784
+ * @see {@link https://docs.monerium.com/api#tag/addresses/operation/balances | API Documentation}
785
+ */
786
+ getBalances: (address: string, chain: Chain | ChainId, currencies?: Currency | Currency[]) => Promise<Balances>;
787
+ /**
788
+ * Add a new address to the profile.
789
+ *
790
+ * @group Addresses
791
+ * @see {@link https://docs.monerium.com/api#tag/addresses/operation/link-address | API Documentation}
792
+ */
793
+ linkAddress: (payload: LinkAddress) => Promise<LinkedAddress>;
794
+ /**
795
+ * Fetch details about a single IBAN.
796
+ *
797
+ * @group IBANs
798
+ * @param {string} iban - the IBAN to fetch.
799
+ * @see {@link https://docs.monerium.com/api#tag/ibans/operation/iban | API Documentation}
800
+ */
801
+ getIban: (iban: string) => Promise<IBAN>;
802
+ /**
803
+ * Fetch all IBANs for the profile.
804
+ *
805
+ * @group IBANs
806
+ * @see {@link https://docs.monerium.com/api#tag/ibans/operation/ibans | API Documentation}
807
+ */
808
+ getIbans: (params?: IbansQueryParams) => Promise<IBANsResponse>;
809
+ /**
810
+ * @group IBANs
811
+ * @param {RequestIbanPayload} payload
812
+ * @see {@link https://docs.monerium.com/api#tag/ibans/operation/request-iban | API Documentation}
813
+ */
814
+ requestIban: ({ address, chain, emailNotifications, }: RequestIbanPayload) => Promise<ResponseStatus>;
815
+ /**
816
+ * @group IBANs
817
+ * @param {string} iban - the IBAN to move.
818
+ * @param {MoveIbanPayload} payload - the payload to move the IBAN.
819
+ * @see {@link https://docs.monerium.com/api#tag/ibans/operation/move-iban | API Documentation}
820
+ */
821
+ moveIban: (iban: string, { address, chain }: MoveIbanPayload) => Promise<ResponseStatus>;
822
+ /**
823
+ * @group Orders
824
+ * @see {@link https://docs.monerium.com/api/#tag/orders/operation/order | API Documentation}
825
+ */
826
+ getOrder: (orderId: string) => Promise<Order>;
827
+ /**
828
+ * @group Orders
829
+ * @see {@link https://docs.monerium.com/api/#tag/orders/operation/orders | API Documentation}
830
+ */
831
+ getOrders: (filter?: OrderFilter) => Promise<OrdersResponse>;
832
+ /**
833
+ * Place a new order.
834
+ *
835
+ * **Note:** For multi-signature orders, the API returns a 202 Accepted response
836
+ * with `{status: 202, statusText: "Accepted"}` instead of the full Order object.
837
+ *
838
+ * @returns Promise that resolves to either:
839
+ * - `Order` - Full order object for regular orders
840
+ * - `ResponseStatus` - Status object for multi-sig orders
841
+ *
842
+ * @group Orders
843
+ * @see {@link https://docs.monerium.com/api#tag/orders/operation/post-orders | API Documentation}
844
+ */
845
+ placeOrder: (order: NewOrder) => Promise<Order | ResponseStatus>;
846
+ /**
847
+ * @group Tokens
848
+ * @see {@link https://docs.monerium.com/api#tag/tokens | API Documentation}
849
+ */
850
+ getTokens: () => Promise<Token[]>;
851
+ /**
852
+ * Get pending signatures for the authenticated user.
853
+ *
854
+ * @group Signatures
855
+ * @param {SignaturesQueryParams} [params] - Optional query parameters to filter signatures.
856
+ * @see {@link https://docs.monerium.com/api#tag/signatures/operation/get-signatures | API Documentation}
857
+ */
858
+ getSignatures: (params?: SignaturesQueryParams) => Promise<SignaturesResponse>;
859
+ /**
860
+ * @group Files
861
+ * @see {@link https://docs.monerium.com/api/#tag/files | API Documentation}
862
+ */
863
+ /**
864
+ * Upload a supporting document for KYC onboarding or order support.
865
+ *
866
+ * Requires `Blob` and `FormData` support — available in Node.js 18+,
867
+ * browsers, and Cloudflare Workers. Not available in all environments.
868
+ *
869
+ * @param document - File content as a `Blob`, `Uint8Array`, or `ArrayBuffer`.
870
+ * Node.js `Buffer` is a `Uint8Array` and works directly.
871
+ * @param filename - Optional filename sent to the API (e.g. `'kyc.pdf'`).
872
+ */
873
+ uploadSupportingDocument: (document: Blob | Uint8Array | ArrayBuffer, filename?: string) => Promise<SupportingDoc>;
874
+ };
875
+
876
+ /**
877
+ * @group v4
878
+ * @category v4 - Authorization
879
+ * @beta
880
+ */
881
+ interface BuildAuthorizationUrlOptions {
882
+ environment?: ENV;
883
+ clientId: string;
884
+ redirectUri: string;
885
+ codeChallenge: string;
886
+ state?: string;
887
+ email?: string;
888
+ skipKyc?: boolean;
889
+ address?: string;
890
+ signature?: string;
891
+ chain?: string;
892
+ }
893
+ /**
894
+ * Build the authorization redirect URL.
895
+ * Returns a URL string — the caller navigates to it.
896
+ * The SDK does not redirect.
897
+ * @group v4
898
+ * @category v4 - Authorization
899
+ * @beta
900
+ */
901
+ declare const buildAuthorizationUrl: (options: BuildAuthorizationUrlOptions) => string;
902
+ /**
903
+ * @group v4
904
+ * @category v4 - Authorization
905
+ * @beta
906
+ */
907
+ interface BuildSiweAuthorizationUrlOptions {
908
+ environment?: ENV;
909
+ clientId: string;
910
+ redirectUri: string;
911
+ codeChallenge: string;
912
+ message: string;
913
+ signature: string;
914
+ state?: string;
915
+ }
916
+ /**
917
+ * Build the SIWE authorization redirect URL.
918
+ * Returns a URL string — the caller navigates to it.
919
+ * The SDK does not redirect.
920
+ *
921
+ * @group v4
922
+ * @category v4 - Authorization
923
+ * @beta
924
+ */
925
+ declare const buildSiweAuthorizationUrl: (options: BuildSiweAuthorizationUrlOptions) => string;
926
+ /**
927
+ * @group v4
928
+ * @category v4 - Authorization
929
+ * @beta
930
+ */
931
+ interface AuthorizationCodeGrantOptions {
932
+ environment?: ENV;
933
+ clientId: string;
934
+ redirectUri: string;
935
+ code: string;
936
+ codeVerifier: string;
937
+ transport?: Transport;
938
+ }
939
+ /**
940
+ * Exchange an authorization code for tokens.
941
+ * The caller stores the returned BearerProfile — the SDK does not write to any storage.
942
+ *
943
+ * @group v4
944
+ * @category v4 - Authorization
945
+ * @beta
946
+ */
947
+ declare const authorizationCodeGrant: (options: AuthorizationCodeGrantOptions) => Promise<BearerProfile>;
948
+ interface RefreshTokenGrantOptions {
949
+ environment?: ENV;
950
+ clientId: string;
951
+ refreshToken: string;
952
+ transport?: Transport;
953
+ }
954
+ /**
955
+ * Get a new access token using a refresh token.
956
+ * The caller stores the returned BearerProfile — the SDK does not write to any storage.
957
+ * @beta
958
+ */
959
+ declare const refreshTokenGrant: (options: RefreshTokenGrantOptions) => Promise<BearerProfile>;
960
+ interface ClientCredentialsGrantOptions {
961
+ environment?: ENV;
962
+ clientId: string;
963
+ clientSecret: string;
964
+ transport?: Transport;
965
+ }
966
+ /**
967
+ * Get an access token using client credentials. Server-side only.
968
+ * clientSecret must never be used in a browser context.
969
+ *
970
+ * @group v4
971
+ * @category v4 - Authorization
972
+ * @beta
973
+ */
974
+ declare const clientCredentialsGrant: (options: ClientCredentialsGrantOptions) => Promise<BearerProfile>;
975
+ /**
976
+ * @group v4
977
+ * @category v4 - Authorization
978
+ * @beta
979
+ */
980
+ interface ParsedAuthorizationResponse {
981
+ code?: string;
982
+ state?: string;
983
+ error?: string;
984
+ errorDescription?: string;
985
+ }
986
+ /**
987
+ * Parse a callback URL or query string into structured fields.
988
+ *
989
+ * - No globals. No side effects. Never throws.
990
+ * - Returns an empty object if none of the expected parameters are present.
991
+ * - Check for the presence of `code` or `error` to determine if the URL
992
+ * contains an OAuth2 authorization response.
993
+ *
994
+ * @example
995
+ * const { code, error } = parseAuthorizationResponse(req.url);
996
+ * const { code, error } = parseAuthorizationResponse('?code=abc&state=xyz');
997
+ * @experimental may not be included in v4
998
+ * @group v4
999
+ * @category v4 - Helpers
1000
+ */
1001
+ declare const parseAuthorizationResponse: (input: string) => ParsedAuthorizationResponse;
1002
+
598
1003
  /**
1004
+ * Generate a cryptographically random PKCE code verifier (RFC 7636).
1005
+ * Returns a base64url-encoded string of 32 random bytes (256 bits of entropy).
1006
+ * The caller is responsible for storing this until the callback.
1007
+ * @group v4
1008
+ * @category v4 - PKCE
1009
+ */
1010
+ declare const randomPKCECodeVerifier: () => string;
1011
+ /**
1012
+ * Derive the S256 code challenge from a code verifier.
1013
+ * Synchronous. Returns a base64url-encoded SHA-256 hash.
1014
+ * @group v4
1015
+ * @category v4 - PKCE
1016
+ */
1017
+ declare const calculatePKCECodeChallenge: (codeVerifier: string) => string;
1018
+
1019
+ /**
1020
+ * Thrown when the Monerium API returns a non-2xx response.
1021
+ * Fields map directly to the API response body — nothing is translated or normalised.
1022
+ *
1023
+ * @example
1024
+ * try {
1025
+ * await client.getProfiles();
1026
+ * } catch (err) {
1027
+ * if (err instanceof MoneriumApiError) {
1028
+ * console.log(err.code); // 401
1029
+ * console.log(err.status); // "Unauthorized"
1030
+ * console.log(err.message); // "Not authenticated"
1031
+ * console.log(err.errors); // field-level validation errors, if present
1032
+ * }
1033
+ * }
1034
+ * @group v4
1035
+ * @category v4 - Errors
1036
+ */
1037
+ declare class MoneriumApiError extends Error {
1038
+ code: number;
1039
+ status: string;
1040
+ errors?: Record<string, string>;
1041
+ details?: unknown;
1042
+ constructor(body: {
1043
+ code: number;
1044
+ status: string;
1045
+ message: string;
1046
+ errors?: Record<string, string>;
1047
+ details?: unknown;
1048
+ });
1049
+ }
1050
+ type MoneriumSdkErrorType = 'network_error' | 'authentication_required' | 'invalid_configuration';
1051
+ /**
1052
+ * Thrown for SDK-level failures — no HTTP response involved.
1053
+ *
1054
+ * @example
1055
+ * try {
1056
+ * await client.getProfiles();
1057
+ * } catch (err) {
1058
+ * if (err instanceof MoneriumSdkError) {
1059
+ * console.log(err.type); // 'network_error' | 'authentication_required' | ...
1060
+ * console.log(err.cause); // underlying fetch error, if type === 'network_error'
1061
+ * }
1062
+ * }
1063
+ * @group v4
1064
+ * @category v4 - Errors
1065
+ */
1066
+ declare class MoneriumSdkError extends Error {
1067
+ type: MoneriumSdkErrorType;
1068
+ cause?: unknown;
1069
+ constructor(type: MoneriumSdkErrorType, message: string, cause?: unknown);
1070
+ }
1071
+
1072
+ /**
1073
+ * @deprecated Class will be removed in v4 in favour of 'createMoneriumClient' function.
1074
+ *
599
1075
  * In the [Monerium UI](https://monerium.app/), create an application to get the `clientId` and register your `redirectUri`.
600
1076
  * ```ts
601
1077
  * import { MoneriumClient } from '@monerium/sdk';
@@ -629,10 +1105,13 @@ declare class MoneriumClient {
629
1105
  * */
630
1106
  state: string | undefined;
631
1107
  /**
1108
+ * @deprecated Class will be removed in v4 in favour of 'createMoneriumClient' function.
1109
+ *
632
1110
  * @defaultValue `sandbox`
633
1111
  * */
634
1112
  constructor(envOrOptions?: ENV | ClassOptions);
635
1113
  /**
1114
+ * @deprecated will be removed in v4 - in favour of `buildAuthorizationUrl`
636
1115
  * Constructs the url to the authorization code flow and redirects,
637
1116
  * Code Verifier needed for the code challenge is stored in local storage
638
1117
  * For automatic wallet link, add the following properties: `address`, `signature` & `chain`
@@ -647,6 +1126,7 @@ declare class MoneriumClient {
647
1126
  */
648
1127
  authorize(params?: AuthFlowOptions): Promise<void>;
649
1128
  /**
1129
+ * @deprecated will be removed in v4 - in favour of `buildSiweAuthorizationUrl`
650
1130
  * Constructs the url to the authorization code flow and redirects,
651
1131
  * Code Verifier needed for the code challenge is stored in local storage
652
1132
  *
@@ -666,6 +1146,7 @@ declare class MoneriumClient {
666
1146
  */
667
1147
  siwe(params: AuthFlowSIWEOptions): Promise<void>;
668
1148
  /**
1149
+ * @deprecated Will be removed in v4 in favour of 'authorizationCodeGrant', 'refreshTokenGrant' and 'clientCredentialsGrant'
669
1150
  * Will use the authorization code flow code to get access token
670
1151
  *
671
1152
  * @group Authentication
@@ -753,12 +1234,12 @@ declare class MoneriumClient {
753
1234
  getIbans(queryParameters?: IbansQueryParams): Promise<IBANsResponse>;
754
1235
  /**
755
1236
  * @group Orders
756
- * @see {@link https://docs.monerium.com/api#tag/orders | API Documentation}
1237
+ * @see {@link https://docs.monerium.com/api/#tag/orders/operation/orders | API Documentation}
757
1238
  */
758
1239
  getOrders(filter?: OrderFilter): Promise<OrdersResponse>;
759
1240
  /**
760
1241
  * @group Orders
761
- * @see {@link https://docs.monerium.com/api#tag/order | API Documentation}
1242
+ * @see {@link https://docs.monerium.com/api/#tag/orders/operation/order | API Documentation}
762
1243
  */
763
1244
  getOrder(orderId: string): Promise<Order>;
764
1245
  /**
@@ -829,16 +1310,18 @@ declare class MoneriumClient {
829
1310
  */
830
1311
  requestIban({ address, chain, emailNotifications, }: RequestIbanPayload): Promise<ResponseStatus>;
831
1312
  /**
1313
+ * @deprecated There is no longer a PUT endpoint for profile details. Use PATCH instead.
832
1314
  * @group Profiles
833
1315
  * @see {@link https://docs.monerium.com/api#tag/profiles/operation/profile-details | API Documentation}
834
1316
  */
835
1317
  submitProfileDetails(profile: string, body: SubmitProfileDetailsPayload): Promise<ResponseStatus>;
836
1318
  /**
837
- * @group Orders
838
- * @see {@link https://docs.monerium.com/api#tag/orders/operation/supporting-document | API Documentation}
1319
+ * @group Files
1320
+ * @see {@link https://docs.monerium.com/api/#tag/files | API Documentation}
839
1321
  */
840
1322
  uploadSupportingDocument(document: File): Promise<SupportingDoc>;
841
1323
  /**
1324
+ * @deprecated Web sockets will be removed in v4 - use webhooks instead.
842
1325
  * Connects to the order notifications socket
843
1326
  *
844
1327
  * @group Orders
@@ -853,6 +1336,8 @@ declare class MoneriumClient {
853
1336
  onError?: (err: Event) => void;
854
1337
  }): WebSocket | undefined;
855
1338
  /**
1339
+ * @deprecated Web sockets will be removed in v4 - use webhooks instead.
1340
+ *
856
1341
  * Closes the order notifications sockets
857
1342
  *
858
1343
  * @group Orders
@@ -861,12 +1346,15 @@ declare class MoneriumClient {
861
1346
  */
862
1347
  unsubscribeOrderNotifications(params?: OrderNotificationQueryParams): void;
863
1348
  /**
1349
+ * @deprecated will be removed in v4, caller will manage state
1350
+ *
864
1351
  * Cleanups the localstorage and websocket connections
865
1352
  *
866
1353
  * @group Authentication
867
1354
  */
868
1355
  disconnect(): Promise<void>;
869
1356
  /**
1357
+ * @deprecated will be removed in v4, caller will manage state
870
1358
  * Revokes access
871
1359
  *
872
1360
  * @group Authentication
@@ -971,6 +1459,7 @@ declare const shortenAddress: (address?: string) => string | undefined;
971
1459
  * @packageDocumentation
972
1460
  * A library to interact with Monerium API.
973
1461
  *
1462
+ * ![npm version](https://img.shields.io/npm/v/@monerium/sdk)
974
1463
  *
975
1464
  * ## Installation
976
1465
  *
@@ -979,14 +1468,14 @@ declare const shortenAddress: (address?: string) => string | undefined;
979
1468
  * ```
980
1469
  *
981
1470
  * @example
982
- * ```tsx
1471
+ * ```ts
1472
+ * // Current version - Deprecated in v4
983
1473
  * import { MoneriumClient } from '@monerium/sdk';
984
- *
985
1474
  * const monerium = new MoneriumClient({
986
1475
  * clientId: '...',
987
1476
  * redirectUri: '...',
988
1477
  * environment: 'sandbox',
989
- * })
1478
+ * });
990
1479
  *
991
1480
  * // Will redirect the user to Monerium's authentication code flow.
992
1481
  * await monerium.authorize();
@@ -1000,6 +1489,69 @@ declare const shortenAddress: (address?: string) => string | undefined;
1000
1489
  * // Retrieve profiles the client has access to.
1001
1490
  * await monerium.getProfiles();
1002
1491
  * ```
1492
+ * ```ts
1493
+ * // Upcoming v4 — factory function
1494
+ * import {
1495
+ * randomPKCECodeVerifier,
1496
+ * calculatePKCECodeChallenge,
1497
+ * buildAuthorizationUrl,
1498
+ * authorizationCodeGrant,
1499
+ * refreshTokenGrant,
1500
+ * createMoneriumClient,
1501
+ * } from '@monerium/sdk';
1502
+ *
1503
+ * // --- Initiate login ---
1504
+ * const codeVerifier = randomPKCECodeVerifier();
1505
+ * const codeChallenge = calculatePKCECodeChallenge(codeVerifier);
1506
+ * session.set('pkce_verifier', codeVerifier); // server-side session
1507
+ *
1508
+ * const url = buildAuthorizationUrl({
1509
+ * environment: 'sandbox',
1510
+ * clientId: 'your-client-id',
1511
+ * redirectUri: 'https://your-app.com/callback',
1512
+ * codeChallenge,
1513
+ * });
1514
+ * res.redirect(url);
1515
+ *
1516
+ * // --- On the callback page ---
1517
+ * const { code } = parseAuthorizationResponse(
1518
+ * new URL(req.url, 'https://your-app.com')
1519
+ * );
1520
+ * const codeVerifier = session.get('pkce_verifier');
1521
+ * session.delete('pkce_verifier');
1522
+ *
1523
+ * const bearerProfile = await authorizationCodeGrant({
1524
+ * environment: 'sandbox',
1525
+ * clientId: 'your-client-id',
1526
+ * redirectUri: 'https://your-app.com/callback',
1527
+ * code,
1528
+ * codeVerifier,
1529
+ * });
1530
+ *
1531
+ * req.session.accessToken = bearerProfile.access_token;
1532
+ * req.session.refreshToken = bearerProfile.refresh_token;
1533
+ * req.session.accessExpiry = Date.now() + bearerProfile.expires_in * 1000;
1534
+ *
1535
+ * // --- Use the API ---
1536
+ * const client = createMoneriumClient({
1537
+ * environment: 'sandbox',
1538
+ * getAccessToken: async () => {
1539
+ * if (Date.now() > session.accessExpiry) {
1540
+ * const newProfile = await refreshTokenGrant({
1541
+ * environment: 'sandbox',
1542
+ * clientId: 'your-client-id',
1543
+ * refreshToken: session.refreshToken,
1544
+ * });
1545
+ * session.accessToken = newProfile.access_token;
1546
+ * session.accessExpiry = Date.now() + newProfile.expires_in * 1000;
1547
+ * return newProfile.access_token;
1548
+ * }
1549
+ * return session.accessToken;
1550
+ * },
1551
+ * });
1552
+ *
1553
+ * const profiles = await client.getProfiles();
1554
+ * ```
1003
1555
  */
1004
1556
 
1005
- export { AccountState, type Address, type AddressesQueryParams, type AddressesResponse, type AuthArgs, type AuthCodePayload, type AuthContext, type AuthFlowOptions, type AuthFlowOptionsShared, type AuthFlowSIWEOptions, type AuthorizationCodeCredentials, type Balances, type BankAccountIdentifier, type BearerProfile, type BearerTokenCredentials, type Beneficiary, type Chain, type ChainId, type ClassOptions, type ClientCredentials, type ClientCredentialsPayload, type Config, type CorporateProfileDetails, type CorporateProfileDetailsRequest, type Corporation, type CosmosChainId, type Counterpart, type CounterpartBank, type CounterpartDetails, type CrossChainIdentifier, Currency, type CurrencyBalance, type CurrencyCode, type Director, type ENV, type Environment, type EvmChainId, type Fee, type IBAN, type IBANIdentifier, type IBANsResponse, type IbansQueryParams, IdDocumentKind, type Identifier, type Individual, type Issuer, type KYC, KYCOutcome, KYCState, type LinkAddress, type LinkedAddress, Method, MoneriumClient, type MoveIbanPayload, type NewOrder, type NewOrderByAccountId, type NewOrderByAddress, type NewOrderCommon, type Order, type OrderFilter, OrderKind, type OrderMetadata, type OrderNotificationQueryParams, OrderState, type OrdersResponse, type PKCERSIWERequestArgs, type PKCERequest, type PKCERequestArgs, type PKCERequestShared, type PKCESIWERequest, PaymentStandard, type PendingLinkAddressSignature, type PendingOrderSignature, type PendingSignature, type PendingSignatureKind, Permission, type PersonalProfileDetails, type PersonalProfileDetailsRequest, type ProductionChain, type Profile, type ProfilePermissions, ProfileState, ProfileType, type ProfilesQueryParams, type ProfilesResponse, type RefreshTokenPayload, type Representative, type RequestIbanPayload, type ResponseStatus, type SCANIdentifier, type SandboxChain, type SignaturesQueryParams, type SignaturesResponse, type SubmitProfileDetailsPayload, type SupportingDoc, type SupportingDocMetadata, type Ticker, type Token, type TokenSymbol, _default as constants, MoneriumClient as default, getChain, parseChain, placeOrderMessage, rfc3339, shortenAddress, shortenIban, siweMessage };
1557
+ export { AccountState, type Address, type AddressesQueryParams, type AddressesResponse, type AuthArgs, type AuthCodePayload, type AuthContext, type AuthFlowOptions, type AuthFlowOptionsShared, type AuthFlowSIWEOptions, type AuthorizationCodeCredentials, type AuthorizationCodeGrantOptions, type Balances, type BankAccountIdentifier, type BearerProfile, type BearerTokenCredentials, type Beneficiary, type BuildAuthorizationUrlOptions, type BuildSiweAuthorizationUrlOptions, type Chain, type ChainId, type ClassOptions, type ClientCredentials, type ClientCredentialsGrantOptions, type ClientCredentialsPayload, type Config, type CorporateProfileDetails, type CorporateProfileDetailsRequest, type Corporation, type CosmosChainId, type Counterpart, type CounterpartBank, type CounterpartDetails, type CrossChainIdentifier, Currency, type CurrencyBalance, type CurrencyCode, type Director, type ENV, type Environment, type EvmChainId, type Fee, type IBAN, type IBANIdentifier, type IBANsResponse, type IbansQueryParams, IdDocumentKind, type Identifier, type Individual, type Issuer, type KYC, KYCOutcome, KYCState, type LinkAddress, type LinkedAddress, Method, MoneriumApiError, MoneriumClient, type MoneriumClientOptions, MoneriumSdkError, type MoneriumSdkErrorType, type MoveIbanPayload, type NewOrder, type NewOrderByAccountId, type NewOrderByAddress, type NewOrderCommon, type Order, type OrderFilter, OrderKind, type OrderMetadata, type OrderNotificationQueryParams, OrderState, type OrdersResponse, type PKCERSIWERequestArgs, type PKCERequest, type PKCERequestArgs, type PKCERequestShared, type PKCESIWERequest, type ParsedAuthorizationResponse, PaymentStandard, type PendingLinkAddressSignature, type PendingOrderSignature, type PendingSignature, type PendingSignatureKind, Permission, type PersonalProfileDetails, type PersonalProfileDetailsRequest, type ProductionChain, type Profile, type ProfilePermissions, ProfileState, ProfileType, type ProfilesQueryParams, type ProfilesResponse, type RefreshTokenGrantOptions, type RefreshTokenPayload, type Representative, type RequestIbanPayload, type ResponseStatus, type SCANIdentifier, type SandboxChain, type SignaturesQueryParams, type SignaturesResponse, type SubmitProfileDetailsPayload, type SupportingDoc, type SupportingDocMetadata, type Ticker, type Token, type TokenSymbol, type Transport, type TransportRequest, type TransportResponse, authorizationCodeGrant, buildAuthorizationUrl, buildSiweAuthorizationUrl, calculatePKCECodeChallenge, clientCredentialsGrant, _default as constants, createMoneriumClient, MoneriumClient as default, getChain, parseAuthorizationResponse, parseChain, placeOrderMessage, randomPKCECodeVerifier, refreshTokenGrant, rfc3339, shortenAddress, shortenIban, siweMessage };
package/dist/index.js CHANGED
@@ -1,15 +1,16 @@
1
- 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var z=require('crypto-js/enc-base64url.js'),q=require('crypto-js/sha256.js');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var z__default=/*#__PURE__*/_interopDefault(z);var q__default=/*#__PURE__*/_interopDefault(q);var x={environments:{production:{name:"production",api:"https://api.monerium.app",web:"https://monerium.app",wss:"wss://api.monerium.app"},sandbox:{name:"sandbox",api:"https://api.monerium.dev",web:"https://sandbox.monerium.dev",wss:"wss://api.monerium.dev"}}};var f={LINK_MESSAGE:"I hereby declare that I am the address owner.",STORAGE_CODE_VERIFIER:"monerium.sdk.code_verifier",STORAGE_ACCESS_TOKEN:"monerium.sdk.access_token",STORAGE_ACCESS_EXPIRY:"monerium.sdk.access_expiry"};var A=()=>{let t="",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",r=e.length,n=0;for(;n<128;)t+=e.charAt(Math.floor(Math.random()*r)),n+=1;return t},j=t=>z__default.default.stringify(q__default.default(t)),S=()=>{let t=A(),e=j(t);return localStorage.setItem(f.STORAGE_CODE_VERIFIER,t||""),e},k=()=>{let t=window.location.href;if(!t||!t?.includes("?"))return;let[e,r]=t.split("?");r&&window.history.replaceState(null,"",e);},R=t=>t.code!=null,$=t=>t.refresh_token!=null,v=t=>t.client_secret!=null;var _=async(t,e,r,n)=>{let i=await fetch(`${t}`,{method:e,headers:n,body:r}),s,a=await i.text();try{if(s=JSON.parse(a),Object.keys(s).length===0&&s.constructor===Object)switch(i.status){case 201:case 202:return {status:i.status,statusText:i.statusText}}}catch{throw a}if(!i.ok)throw s;return s};var u=t=>{if(!t)return "";let e=Object.entries(t).filter(([r,n])=>n!==""&&n!==void 0&&n!==null).map(([r,n])=>`${encodeURIComponent(r)}=${encodeURIComponent(n)}`).join("&");return e?"?"+e:""};var N=t=>t?e=>{console.log("%c [MONERIUM:DEBUG]:","color:orange;",e);}:()=>{};var E=t=>Object.entries(t).filter(([r,n])=>n!=null).map(([r,n])=>`${r}-${n}`).join("-");var B=(i=>(i.eur="eur",i.usd="usd",i.gbp="gbp",i.isk="isk",i))(B||{}),K=(s=>(s.password="password",s.resource="resource",s.jwt="jwt",s.apiKey="apiKey",s.bearer="bearer",s))(K||{}),M=(r=>(r.corporate="corporate",r.personal="personal",r))(M||{}),F=(r=>(r.read="read",r.write="write",r))(F||{}),L=(s=>(s.created="created",s.pending="pending",s.approved="approved",s.rejected="rejected",s.blocked="blocked",s))(L||{}),Q=(i=>(i.absent="absent",i.submitted="submitted",i.pending="pending",i.confirmed="confirmed",i))(Q||{}),W=(n=>(n.approved="approved",n.rejected="rejected",n.unknown="unknown",n))(W||{}),V=(s=>(s.requested="requested",s.approved="approved",s.pending="pending",s.rejected="rejected",s.closed="closed",s))(V||{}),G=(i=>(i.iban="iban",i.scan="scan",i.chain="chain",i.account="account",i))(G||{}),J=(n=>(n.passport="passport",n.nationalIdentityCard="nationalIdentityCard",n.drivingLicense="drivingLicense",n))(J||{}),H=(r=>(r.redeem="redeem",r.issue="issue",r))(H||{}),X=(i=>(i.placed="placed",i.pending="pending",i.processed="processed",i.rejected="rejected",i))(X||{});var P=t=>{if(t.toString()==="Invalid Date")throw t;let e=n=>n<10?"0"+n:n,r=n=>{if(n===0)return "Z";let i=n>0?"-":"+";return n=Math.abs(n),i+e(Math.floor(n/60))+":"+e(n%60)};return t.getFullYear()+"-"+e(t.getMonth()+1)+"-"+e(t.getDate())+"T"+e(t.getHours())+":"+e(t.getMinutes())+":"+e(t.getSeconds())+r(t.getTimezoneOffset())},Z=t=>{switch(t){case "noble":case "noble-1":case "grand":case "grand-1":return true;default:return false}},Y=t=>{switch(t){case "ethereum":case "sepolia":case "polygon":case "amoy":case "gnosis":case "chiado":case "arbitrum":case "arbitrumsepolia":case "linea":case "lineasepolia":case "scroll":case "scrollsepolia":case "camino":case "columbus":return true;default:return false}},b=t=>{if(typeof t=="number")return O(t);if(Z(t))return t.split("-")[0];if(Y(t))return t;try{return O(parseInt(t))}catch{throw new Error(`Chain not supported: ${t}`)}},g=(t,e)=>b(T(e,t)),ee=(t,e,r,n)=>{let i=`${e?.toUpperCase()||"EUR"}`;return n?`Send ${i} ${t} to ${r} on ${b(n)} at ${P(new Date)}`:i==="EUR"?`Send ${i} ${t} to ${D(r)} at ${P(new Date)}`:`Send ${i} ${t} to ${r} at ${P(new Date)}`},te=({domain:t,address:e,appName:r,redirectUri:n,chainId:i,issuedAt:s=new Date().toISOString(),expiryAt:a=new Date(Date.now()+1e3*60*5).toISOString(),privacyPolicyUrl:o,termsOfServiceUrl:l})=>`${t} wants you to sign in with your Ethereum account:
1
+ 'use strict';Object.defineProperty(exports,'__esModule',{value:true});var G=require('crypto-js/enc-base64url.js'),Y=require('crypto-js/lib-typedarrays.js'),ee=require('crypto-js/sha256.js');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var G__default=/*#__PURE__*/_interopDefault(G);var Y__default=/*#__PURE__*/_interopDefault(Y);var ee__default=/*#__PURE__*/_interopDefault(ee);var g=class extends Error{code;status;errors;details;constructor(e){super(e.message),this.name="MoneriumApiError",this.code=e.code,this.status=e.status,this.errors=e.errors,this.details=e.details;}},x=class extends Error{type;cause;constructor(e,t,n){super(t),this.name="MoneriumSdkError",this.type=e,this.cause=n;}};var V=()=>{let r="",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t=e.length,n=0;for(;n<128;)r+=e.charAt(Math.floor(Math.random()*t)),n+=1;return r};var O=()=>{let r=window.location.href;if(!r||!r?.includes("?"))return;let[e,t]=r.split("?");t&&window.history.replaceState(null,"",e);},N=r=>r.code!=null,K=r=>r.refresh_token!=null,j=r=>r.client_secret!=null,$=()=>{let r=new Uint8Array(32);return crypto.getRandomValues(r),G__default.default.stringify(Y__default.default.create(r))},B=r=>G__default.default.stringify(ee__default.default(r));var D=async(r,e,t,n)=>{let i=await fetch(`${r}`,{method:e,headers:n,body:t}),s,o=await i.text();try{if(s=JSON.parse(o),Object.keys(s).length===0&&s.constructor===Object)switch(i.status){case 201:case 202:return {status:i.status,statusText:i.statusText}}}catch{throw o}if(!i.ok)throw s;return s};var U=[{production:{id:"ethereum",chainId:1},sandbox:{id:"sepolia",chainId:11155111}},{production:{id:"gnosis",chainId:100},sandbox:{id:"chiado",chainId:10200}},{production:{id:"polygon",chainId:137},sandbox:{id:"amoy",chainId:80002}},{production:{id:"arbitrum",chainId:42161},sandbox:{id:"arbitrumsepolia",chainId:421614}},{production:{id:"linea",chainId:59144},sandbox:{id:"lineasepolia",chainId:59141}},{production:{id:"scroll",chainId:534352},sandbox:{id:"scrollsepolia",chainId:534351}},{production:{id:"base",chainId:8453},sandbox:{id:"basesepolia",chainId:84532}},{production:{id:"camino",chainId:500},sandbox:{id:"columbus",chainId:501}}],F=new Map(U.flatMap(({production:r,sandbox:e})=>[[r.chainId,r.id],[e.chainId,e.id]])),Q=new Set(U.flatMap(({production:r,sandbox:e})=>[r.id,e.id])),L=new Map(U.map(({production:r,sandbox:e})=>[r.id,e.id]));var W=(i=>(i.eur="eur",i.usd="usd",i.gbp="gbp",i.isk="isk",i))(W||{}),re=(s=>(s.password="password",s.resource="resource",s.jwt="jwt",s.apiKey="apiKey",s.bearer="bearer",s))(re||{}),te=(t=>(t.corporate="corporate",t.personal="personal",t))(te||{}),ne=(t=>(t.read="read",t.write="write",t))(ne||{}),se=(s=>(s.created="created",s.pending="pending",s.approved="approved",s.rejected="rejected",s.blocked="blocked",s))(se||{}),ie=(i=>(i.absent="absent",i.submitted="submitted",i.pending="pending",i.confirmed="confirmed",i))(ie||{}),oe=(n=>(n.approved="approved",n.rejected="rejected",n.unknown="unknown",n))(oe||{}),ae=(s=>(s.requested="requested",s.approved="approved",s.pending="pending",s.rejected="rejected",s.closed="closed",s))(ae||{}),de=(i=>(i.iban="iban",i.scan="scan",i.chain="chain",i.account="account",i))(de||{}),ce=(n=>(n.passport="passport",n.nationalIdentityCard="nationalIdentityCard",n.drivingLicense="drivingLicense",n))(ce||{}),ue=(t=>(t.redeem="redeem",t.issue="issue",t))(ue||{}),le=(i=>(i.placed="placed",i.pending="pending",i.processed="processed",i.rejected="rejected",i))(le||{});var R=r=>{if(r.toString()==="Invalid Date")throw r;let e=n=>n<10?"0"+n:n,t=n=>{if(n===0)return "Z";let i=n>0?"-":"+";return n=Math.abs(n),i+e(Math.floor(n/60))+":"+e(n%60)};return r.getFullYear()+"-"+e(r.getMonth()+1)+"-"+e(r.getDate())+"T"+e(r.getHours())+":"+e(r.getMinutes())+":"+e(r.getSeconds())+t(r.getTimezoneOffset())},pe=r=>{switch(r){case "noble":case "noble-1":case "grand":case "grand-1":return true;default:return false}},ge=r=>Q.has(r),h=r=>{if(typeof r=="number")return z(r);if(pe(r))return r.split("-")[0];if(ge(r))return r;try{return z(parseInt(r))}catch{throw new Error(`Chain not supported: ${r}`)}},w=(r,e)=>h(J(e,r)),he=(r,e,t,n)=>{let i=`${e?.toUpperCase()||"EUR"}`;return n?`Send ${i} ${r} to ${t} on ${h(n)} at ${R(new Date)}`:i==="EUR"?`Send ${i} ${r} to ${H(t)} at ${R(new Date)}`:`Send ${i} ${r} to ${t} at ${R(new Date)}`},me=({domain:r,address:e,appName:t,redirectUri:n,chainId:i,issuedAt:s=new Date().toISOString(),expiryAt:o=new Date(Date.now()+1e3*60*5).toISOString(),privacyPolicyUrl:a,termsOfServiceUrl:d})=>`${r} wants you to sign in with your Ethereum account:
2
2
  ${e}
3
3
 
4
- Allow ${r} to access my data on Monerium
4
+ Allow ${t} to access my data on Monerium
5
5
 
6
6
  URI: ${n}
7
7
  Version: 1
8
8
  Chain ID: ${i}
9
- Nonce: ${A().slice(0,16)}
9
+ Nonce: ${V().slice(0,16)}
10
10
  Issued At: ${s}
11
- Expiration Time: ${a}
11
+ Expiration Time: ${o}
12
12
  Resources:
13
13
  - https://monerium.com/siwe
14
- - ${o}
15
- - ${l}`,C=t=>t&&Object.entries(t)?.length>0?Object.entries(t).filter(([e,r])=>r!==void 0).map(([e,r])=>`${encodeURIComponent(e)}=${encodeURIComponent(r)}`).join("&"):"",O=t=>{switch(t){case 1:return "ethereum";case 11155111:return "sepolia";case 100:return "gnosis";case 10200:return "chiado";case 137:return "polygon";case 80002:return "amoy";case 42161:return "arbitrum";case 421614:return "arbitrumsepolia";case 59144:return "linea";case 59141:return "lineasepolia";case 534352:return "scroll";case 534351:return "scrollsepolia";case 501:return "columbus";case 500:return "camino";default:throw new Error(`Chain not supported: ${t}`)}},D=t=>{if(typeof t!="string"||!t?.length)return t;let e=t.replace(/\s/g,"");return t?.length>11?`${e.substring(0,4)}...${e.substring(e.length-4)}`:t},re=t=>typeof t!="string"||!t?.length?t:t?.length>11?`${t.substring(0,7)}...${t.substring(t.length-5)}`:t;var T=(t,e)=>{if(e==="sandbox")switch(t){case "ethereum":return "sepolia";case "polygon":return "amoy";case "gnosis":return "chiado";case "arbitrum":return "arbitrumsepolia";case "linea":return "lineasepolia";case "scroll":return "scrollsepolia";case "camino":return "columbus";case "noble":return "noble";default:return t}return t},p=(t,e)=>{if(e?.chain){let{chain:r,...n}=e;return {...n,chain:b(T(r,t))}}return e};var {STORAGE_CODE_VERIFIER:w,STORAGE_ACCESS_TOKEN:h,STORAGE_ACCESS_EXPIRY:m}=f,d=typeof window>"u",I=class{#e;#s;bearerProfile;#i=new Map;isAuthorized=!!this.bearerProfile;#r=()=>{};#n;state;constructor(e){if(!e){this.#e=x.environments.sandbox;return}if(typeof e=="string")this.#e=x.environments[e];else if(this.#r=N(e.debug??false),this.#e=x.environments[e.environment||"sandbox"],!d&&!e?.clientSecret){let{clientId:r,redirectUri:n}=e;this.#n={clientId:r,redirectUri:n};}else if(d&&e?.clientSecret){this.#r("Client credentials detected");let{clientId:r,clientSecret:n}=e;this.#n={clientId:r,clientSecret:n};}}async authorize(e){let r=S(),n=e?.address?{address:e?.address,signature:e?.signature,chain:e?.chain?g(this.#e.name,e?.chain):void 0}:{},i=C({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,code_challenge:r,code_challenge_method:"S256",response_type:"code",state:e?.state,skip_create_account:e?.skipCreateAccount,skip_kyc:e?.skipKyc,email:e?.email,...n}),s=`${this.#e.api}/auth?${i}`;this.#r(`Auth flow URL: ${s}`),window.location.assign(s);}async siwe(e){let r=S(),n=C({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,message:e.message,signature:e.signature,code_challenge:r,code_challenge_method:"S256",authentication_method:"siwe",state:e?.state}),i=`${this.#e.api}/auth?${n}`;this.#r(`Auth flow SIWE URL: ${i}`),window.location.assign(i);}async getAccess(e){let r=this.#n?.clientId;if(this.#n?.clientSecret){if(d)return await this.#c(this.#n),!!this?.bearerProfile;console.error("\x1B[31m%s\x1B[0m","Use client credentials only on the server where the secret is secure!");}let i=this.#n?.redirectUri;if(!r)throw new Error("Missing ClientId");if(d)throw new Error("This only works client side");let s=new URLSearchParams(window.location.search).get("error")||void 0,a=new URLSearchParams(window.location.search).get("error_description")||void 0;if(s||a)throw new Error(a);let o=new URLSearchParams(window.location.search).get("code")||void 0,l=new URLSearchParams(window.location.search).get("state")||void 0,c=window.localStorage.getItem(h),y=window.localStorage.getItem(m);if(o)return this.#r("Using auth code from auth flow to authorize"),await this.#a(r,i,o,l),this.#r(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(e)return this.#r("Using refresh token to authorize"),await this.#d(r,e),this.#r(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(c&&y){let U=new Date;if(parseInt(y)<U.getTime())throw window.localStorage.removeItem(h),window.localStorage.removeItem(m),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token has expired");this.#r("Access token should still be valid, checking if it is authorized...");try{return this.#s=`Bearer ${c}`,this.isAuthorized=!0,await this.getTokens(),this.#r("Authorized"),!0}catch{throw this.#r("Access token is invalid."),window.localStorage.removeItem(h),window.localStorage.removeItem(m),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token is invalid.")}}return this.#r(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile}async#o(e){let r;if(R(e))r={...e,grant_type:"authorization_code"};else if($(e))r={...e,grant_type:"refresh_token"};else if(v(e))r={...e,grant_type:"client_credentials"};else throw new Error("Authorization grant type could not be detected.");return await this.#t("post","auth/token",r,true).then(n=>{if(this.bearerProfile=n,this.isAuthorized=!!n,this.#s=`Bearer ${n?.access_token}`,!d){let s=new Date().getTime()+n?.expires_in*1e3;window.localStorage.setItem(h,n?.access_token||""),window.localStorage.setItem(m,s?.toString());}}).catch(n=>{throw d||(localStorage.removeItem(w),localStorage.removeItem(h),localStorage.removeItem(m),k()),new Error(n?.message)}),R(e)&&k(),this.bearerProfile}getAuthContext(){return this.#t("get","auth/context")}getProfile(e){return this.#t("get",`profiles/${e}`)}getProfiles(e){return this.#t("get",`profiles${u(e)}`)}getAddress(e){return this.#t("get",`addresses/${e}`)}getAddresses(e){e=p(this.#e.name,e);let r=e?C(e):void 0,n=r?`addresses?${r}`:"addresses";return this.#t("get",n)}getBalances(e,r,n){let i=Array.isArray(n)?n.map(a=>`currency=${a}`).join("&"):n?`currency=${n}`:"",s=g(this.#e.name,r);return this.#t("get",`balances/${s}/${e}${i?`?${i}`:""}`)}getIban(e){return this.#t("get",`ibans/${encodeURI(e)}`)}getIbans(e){let{profile:r,chain:n}=e||{},i=u({profile:r,chain:n?g(this.#e.name,n):""});return this.#t("get",`ibans${i}`)}getOrders(e){return this.#t("get",`orders${u(e)}`)}getOrder(e){return this.#t("get",`orders/${e}`)}getTokens(){return this.#t("get","tokens")}getSignatures(e){let r=e?p(this.#e.name,e):void 0;return this.#t("get",`signatures${u(r)}`)}linkAddress(e){return e=p(this.#e.name,e),this.#t("post","addresses",JSON.stringify(e))}placeOrder(e){let r={kind:"redeem",...p(this.#e.name,e),counterpart:{...e.counterpart,identifier:p(this.#e.name,e.counterpart.identifier)}};return this.#t("post","orders",JSON.stringify(r))}moveIban(e,{address:r,chain:n}){return this.#t("patch",`ibans/${e}`,JSON.stringify({address:r,chain:g(this.#e.name,n)}))}requestIban({address:e,chain:r,emailNotifications:n=true}){return this.#t("post","ibans",JSON.stringify({address:e,chain:g(this.#e.name,r),emailNotifications:n}))}submitProfileDetails(e,r){return this.#t("put",`profiles/${e}/details`,JSON.stringify(r))}uploadSupportingDocument(e){let r=new FormData;return r.append("file",e),_(`${this.#e.api}/files`,"post",r,{Authorization:this.#s||""})}async#t(e,r,n,i){let s={Authorization:this.#s||"",Accept:"application/vnd.monerium.api-v2+json","Content-Type":`application/${i?"x-www-form-urlencoded":"json"}`};return _(`${this.#e.api}/${r}`,e.toUpperCase(),i?C(n):n,s)}#a=async(e,r,n,i)=>{let s=localStorage.getItem(w)||"";if(!s)throw new Error("Code verifier not found");return this.#r("Use code verifier to authorize"),this.state=i,localStorage.removeItem(w),await this.#o({code:n,redirect_uri:r,client_id:e,code_verifier:s})};#c=async({clientId:e,clientSecret:r})=>await this.#o({client_id:e,client_secret:r});#d=async(e,r)=>await this.#o({refresh_token:r,client_id:e});subscribeOrderNotifications({filter:e,onMessage:r,onError:n}={}){if(!this.bearerProfile?.access_token)return;let{profile:i,state:s}=e||{},a=u({access_token:this.bearerProfile?.access_token,profile:i,state:s}),o,l=E({profile:i,state:s});if(this.#i?.has(l))o=this.#i.get(l);else {let c=`${this.#e.wss}/orders${a}`;o=new WebSocket(c),this.#i?.set(l,o);}return o.onopen=()=>{console.log("Connected to WebSocket server");},o.onmessage=c=>{let y=JSON.parse(c.data);r&&r(y);},o.onclose=()=>{console.log("WebSocket connection closed"),this.#i?.delete(a);},o.onerror=c=>{n&&n(c),console.error("WebSocket error:",c);},o}unsubscribeOrderNotifications(e){if(e){let r=E({profile:e?.profile,state:e?.state}),n=this.#i?.get(r);n&&(n.close(),this.#i?.delete(r));}else this.#i?.forEach(r=>{r?.close();}),this.#i?.clear(),this.#i=void 0;}async disconnect(){d||localStorage.removeItem(w),this.unsubscribeOrderNotifications(),this.#s=void 0,this.bearerProfile=void 0;}async revokeAccess(){d||(localStorage.removeItem(h),localStorage.removeItem(m)),this.disconnect();}getEnvironment=()=>this.#e};var De=I;exports.AccountState=V;exports.Currency=B;exports.IdDocumentKind=J;exports.KYCOutcome=W;exports.KYCState=Q;exports.Method=K;exports.MoneriumClient=I;exports.OrderKind=H;exports.OrderState=X;exports.PaymentStandard=G;exports.Permission=F;exports.ProfileState=L;exports.ProfileType=M;exports.constants=f;exports.default=De;exports.getChain=O;exports.parseChain=b;exports.placeOrderMessage=ee;exports.rfc3339=P;exports.shortenAddress=re;exports.shortenIban=D;exports.siweMessage=te;
14
+ - ${a}
15
+ - ${d}`,m=r=>r&&Object.entries(r)?.length>0?Object.entries(r).filter(([e,t])=>t!==""&&t!==void 0&&t!==null).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(t)}`).join("&"):"",z=r=>{let e=F.get(r);if(!e)throw new Error(`Chain not supported: ${r}`);return e},H=r=>{if(typeof r!="string"||!r?.length)return r;let e=r.replace(/\s/g,"");return r?.length>11?`${e.substring(0,4)}...${e.substring(e.length-4)}`:r},fe=r=>typeof r!="string"||!r?.length?r:r?.length>11?`${r.substring(0,7)}...${r.substring(r.length-5)}`:r;var J=(r,e)=>e==="sandbox"&&typeof r=="string"?L.get(r)??r:r,A=(r,e)=>{if(e?.chain){let{chain:t,...n}=e;return {...n,chain:h(J(t,r))}}return e};var u=r=>{if(!r)return "";let e=m(r);return e?`?${e}`:""};var b={environments:{production:{name:"production",api:"https://api.monerium.app",web:"https://monerium.app",wss:"wss://api.monerium.app"},sandbox:{name:"sandbox",api:"https://api.monerium.dev",web:"https://sandbox.monerium.dev",wss:"wss://api.monerium.dev"}}};var M=r=>Object.entries(r).filter(([t,n])=>n!=null).map(([t,n])=>`${t}-${n}`).join("-");function C(r="sandbox"){return b.environments[r]}var E=async({method:r,url:e,headers:t,body:n,signal:i})=>{let s;try{s=await fetch(e,{method:r,headers:t,body:n,signal:i});}catch(a){throw new x("network_error","Network request failed",a)}let o=await s.text();return {status:s.status,bodyText:o}};function I(r){return r?.chain!==void 0?{...r,chain:h(r.chain)}:r}function Ce(r){let e=C(r.environment),t=r.transport??E;async function n(){return "getAccessToken"in r&&r.getAccessToken?r.getAccessToken():"accessToken"in r&&r.accessToken?r.accessToken:null}async function i(o,a,d){let c=await n(),l={Accept:"application/vnd.monerium.api-v2+json"};c&&(l.Authorization=`Bearer ${c}`);let{status:p,bodyText:f}=await t({method:o.toUpperCase(),url:`${e.api}/${a}`,headers:l,body:d});if(!f)return {status:p};let P;try{P=JSON.parse(f);}catch{throw new g({code:p,status:"Parse Error",message:f})}if(p<200||p>=300)throw new g(P);return P}async function s(o,a,d){let c=await n(),l={Accept:"application/vnd.monerium.api-v2+json","Content-Type":"application/json"};if(c)l.Authorization=`Bearer ${c}`;else if(a!=="tokens")throw new x("authentication_required","No access token provided for authenticated endpoint");let{status:p,bodyText:f}=await t({method:o.toUpperCase(),url:`${e.api}/${a}`,headers:l,body:d?JSON.stringify(d):void 0});if(!f)return {status:p};let P;try{P=JSON.parse(f);}catch{throw new g({code:p,status:"Parse Error",message:f})}if(p<200||p>=300)throw new g(P);return P}return {getAuthContext:()=>s("GET","auth/context"),getProfile:o=>s("GET",`profiles/${o}`),getProfiles:o=>s("GET",`profiles${u(o)}`),submitProfileDetails:(o,a)=>s("PATCH",`profiles/${o}/details`,a),getAddress:o=>s("GET",`addresses/${o}`),getAddresses:o=>s("GET",`addresses${u(o?I(o):void 0)}`),getBalances:(o,a,d)=>{let c=h(a),l=Array.isArray(d)?d.map(p=>`currency=${p}`).join("&"):d?`currency=${d}`:"";return s("GET",`balances/${c}/${o}${l?`?${l}`:""}`)},linkAddress:o=>s("POST","addresses",I(o)),getIban:o=>s("GET",`ibans/${encodeURI(o)}`),getIbans:o=>{let a=o?I(o):void 0;return s("GET",`ibans${u(a)}`)},requestIban:({address:o,chain:a,emailNotifications:d=true})=>s("POST","ibans",{address:o,chain:h(a),emailNotifications:d}),moveIban:(o,{address:a,chain:d})=>s("PATCH",`ibans/${o}`,{address:a,chain:h(d)}),getOrder:o=>s("GET",`orders/${o}`),getOrders:o=>s("GET",`orders${u(o)}`),placeOrder:o=>{let a={kind:"redeem",...I(o),...o.counterpart&&{counterpart:{...o.counterpart,identifier:I(o.counterpart.identifier)}}};return s("POST","orders",a)},getTokens:()=>s("GET","tokens"),getSignatures:o=>{let a=o?I(o):void 0;return s("GET",`signatures${u(a)}`)},uploadSupportingDocument:(o,a)=>{let d=o instanceof Blob?o:new Blob([o]),c=new FormData;return c.append("file",d,a),i("POST","files",c)}}}var ye=r=>{let e=C(r.environment),t=u({client_id:r.clientId,redirect_uri:r.redirectUri,code_challenge:r.codeChallenge,code_challenge_method:"S256",response_type:"code",state:r.state,skip_kyc:r.skipKyc,email:r.email,address:r.address,signature:r.signature,chain:r.chain});return `${e.api}/auth${t}`},Pe=r=>{let e=C(r.environment),t=u({client_id:r.clientId,redirect_uri:r.redirectUri,message:r.message,signature:r.signature,code_challenge:r.codeChallenge,code_challenge_method:"S256",authentication_method:"siwe",state:r.state});return `${e.api}/auth${t}`};async function q(r,e,t=E){let n=m(Object.fromEntries(Object.entries(e).filter(([,a])=>a!==void 0))),{status:i,bodyText:s}=await t({method:"POST",url:r,headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/vnd.monerium.api-v2+json"},body:n}),o;try{o=JSON.parse(s);}catch{throw new g({code:i,status:"Parse Error",message:s})}if(i<200||i>=300)throw new g(o);return o}var xe=r=>{let e=C(r.environment);return q(`${e.api}/auth/token`,{grant_type:"authorization_code",client_id:r.clientId,redirect_uri:r.redirectUri,code:r.code,code_verifier:r.codeVerifier},r.transport)},we=r=>{let e=C(r.environment);return q(`${e.api}/auth/token`,{grant_type:"refresh_token",client_id:r.clientId,refresh_token:r.refreshToken},r.transport)},Ae=r=>{let e=C(r.environment);return q(`${e.api}/auth/token`,{grant_type:"client_credentials",client_id:r.clientId,client_secret:r.clientSecret},r.transport)},be=r=>{if(typeof r!="string")return {};let e=r,t=e.includes("?")?e.split("?")[1]:e;if(!t)return {};let n={};for(let s of t.split("&")){let o=s.indexOf("=");if(o===-1)continue;let a=decodeURIComponent(s.slice(0,o)),d=decodeURIComponent(s.slice(o+1).replace(/\+/g," "));n[a]=d;}let i={};return n.code&&(i.code=n.code),n.state&&(i.state=n.state),n.error&&(i.error=n.error),n.error_description&&(i.errorDescription=n.error_description),i};var T={LINK_MESSAGE:"I hereby declare that I am the address owner.",STORAGE_CODE_VERIFIER:"monerium.sdk.code_verifier",STORAGE_ACCESS_TOKEN:"monerium.sdk.access_token",STORAGE_ACCESS_EXPIRY:"monerium.sdk.access_expiry"};var X=r=>r?e=>{console.log("%c [MONERIUM:DEBUG]:","color:orange;",e);}:()=>{};var {STORAGE_CODE_VERIFIER:_,STORAGE_ACCESS_TOKEN:k,STORAGE_ACCESS_EXPIRY:S}=T,y=typeof window>"u",v=class{#e;#i;bearerProfile;#s=new Map;isAuthorized=!!this.bearerProfile;#t=()=>{};#n;state;constructor(e){if(!e){this.#e=b.environments.sandbox;return}if(typeof e=="string")this.#e=b.environments[e];else if(this.#t=X(e.debug??false),this.#e=b.environments[e.environment||"sandbox"],!y&&!e?.clientSecret){let{clientId:t,redirectUri:n}=e;this.#n={clientId:t,redirectUri:n};}else if(y&&e?.clientSecret){this.#t("Client credentials detected");let{clientId:t,clientSecret:n}=e;this.#n={clientId:t,clientSecret:n};}}async authorize(e){let t=Z(),n=e?.address?{address:e?.address,signature:e?.signature,chain:e?.chain?w(this.#e.name,e?.chain):void 0}:{},i=m({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,code_challenge:t,code_challenge_method:"S256",response_type:"code",state:e?.state,skip_kyc:e?.skipKyc,email:e?.email,...n}),s=`${this.#e.api}/auth?${i}`;this.#t(`Auth flow URL: ${s}`),window.location.assign(s);}async siwe(e){let t=Z(),n=m({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,message:e.message,signature:e.signature,code_challenge:t,code_challenge_method:"S256",authentication_method:"siwe",state:e?.state}),i=`${this.#e.api}/auth?${n}`;this.#t(`Auth flow SIWE URL: ${i}`),window.location.assign(i);}async getAccess(e){let t=this.#n?.clientId;if(this.#n?.clientSecret){if(y)return await this.#d(this.#n),!!this?.bearerProfile;console.error("\x1B[31m%s\x1B[0m","Use client credentials only on the server where the secret is secure!");}let i=this.#n?.redirectUri;if(!t)throw new Error("Missing ClientId");if(y)throw new Error("This only works client side");let s=new URLSearchParams(window.location.search).get("error")||void 0,o=new URLSearchParams(window.location.search).get("error_description")||void 0;if(s||o)throw new Error(o);let a=new URLSearchParams(window.location.search).get("code")||void 0,d=new URLSearchParams(window.location.search).get("state")||void 0,c=window.localStorage.getItem(k),l=window.localStorage.getItem(S);if(a)return this.#t("Using auth code from auth flow to authorize"),await this.#a(t,i,a,d),this.#t(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(e)return this.#t("Using refresh token to authorize"),await this.#c(t,e),this.#t(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(c&&l){let p=new Date;if(parseInt(l)<p.getTime())throw window.localStorage.removeItem(k),window.localStorage.removeItem(S),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token has expired");this.#t("Access token should still be valid, checking if it is authorized...");try{return this.#i=`Bearer ${c}`,this.isAuthorized=!0,await this.getTokens(),this.#t("Authorized"),!0}catch{throw this.#t("Access token is invalid."),window.localStorage.removeItem(k),window.localStorage.removeItem(S),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token is invalid.")}}return this.#t(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile}async#o(e){let t;if(N(e))t={...e,grant_type:"authorization_code"};else if(K(e))t={...e,grant_type:"refresh_token"};else if(j(e))t={...e,grant_type:"client_credentials"};else throw new Error("Authorization grant type could not be detected.");return await this.#r("post","auth/token",t,true).then(n=>{if(this.bearerProfile=n,this.isAuthorized=!!n,this.#i=`Bearer ${n?.access_token}`,!y){let s=new Date().getTime()+n?.expires_in*1e3;window.localStorage.setItem(k,n?.access_token||""),window.localStorage.setItem(S,s?.toString());}}).catch(n=>{throw y||(localStorage.removeItem(_),localStorage.removeItem(k),localStorage.removeItem(S),O()),new Error(n?.message)}),N(e)&&O(),this.bearerProfile}getAuthContext(){return this.#r("get","auth/context")}getProfile(e){return this.#r("get",`profiles/${e}`)}getProfiles(e){return this.#r("get",`profiles${u(e)}`)}getAddress(e){return this.#r("get",`addresses/${e}`)}getAddresses(e){e=A(this.#e.name,e);let t=e?m(e):void 0,n=t?`addresses?${t}`:"addresses";return this.#r("get",n)}getBalances(e,t,n){let i=Array.isArray(n)?n.map(o=>`currency=${o}`).join("&"):n?`currency=${n}`:"",s=w(this.#e.name,t);return this.#r("get",`balances/${s}/${e}${i?`?${i}`:""}`)}getIban(e){return this.#r("get",`ibans/${encodeURI(e)}`)}getIbans(e){let{profile:t,chain:n}=e||{},i=u({profile:t,chain:n?w(this.#e.name,n):""});return this.#r("get",`ibans${i}`)}getOrders(e){return this.#r("get",`orders${u(e)}`)}getOrder(e){return this.#r("get",`orders/${e}`)}getTokens(){return this.#r("get","tokens")}getSignatures(e){let t=e?A(this.#e.name,e):void 0;return this.#r("get",`signatures${u(t)}`)}linkAddress(e){return e=A(this.#e.name,e),this.#r("post","addresses",JSON.stringify(e))}placeOrder(e){let t={kind:"redeem",...A(this.#e.name,e),counterpart:{...e.counterpart,identifier:A(this.#e.name,e.counterpart.identifier)}};return this.#r("post","orders",JSON.stringify(t))}moveIban(e,{address:t,chain:n}){return this.#r("patch",`ibans/${e}`,JSON.stringify({address:t,chain:w(this.#e.name,n)}))}requestIban({address:e,chain:t,emailNotifications:n=true}){return this.#r("post","ibans",JSON.stringify({address:e,chain:w(this.#e.name,t),emailNotifications:n}))}submitProfileDetails(e,t){return this.#r("put",`profiles/${e}/details`,JSON.stringify(t))}uploadSupportingDocument(e){let t=new FormData;return t.append("file",e),D(`${this.#e.api}/files`,"post",t,{Authorization:this.#i||""})}async#r(e,t,n,i){let s={Authorization:this.#i||"",Accept:"application/vnd.monerium.api-v2+json","Content-Type":`application/${i?"x-www-form-urlencoded":"json"}`};return D(`${this.#e.api}/${t}`,e.toUpperCase(),i?m(n):n,s)}#a=async(e,t,n,i)=>{let s=localStorage.getItem(_)||"";if(!s)throw new Error("Code verifier not found");return this.#t("Use code verifier to authorize"),this.state=i,localStorage.removeItem(_),await this.#o({code:n,redirect_uri:t,client_id:e,code_verifier:s})};#d=async({clientId:e,clientSecret:t})=>await this.#o({client_id:e,client_secret:t});#c=async(e,t)=>await this.#o({refresh_token:t,client_id:e});subscribeOrderNotifications({filter:e,onMessage:t,onError:n}={}){if(!this.bearerProfile?.access_token)return;let{profile:i,state:s}=e||{},o=u({access_token:this.bearerProfile?.access_token,profile:i,state:s}),a,d=M({profile:i,state:s});if(this.#s?.has(d))a=this.#s.get(d);else {let c=`${this.#e.wss}/orders${o}`;a=new WebSocket(c),this.#s?.set(d,a);}return a.onopen=()=>{console.log("Connected to WebSocket server");},a.onmessage=c=>{let l=JSON.parse(c.data);t&&t(l);},a.onclose=()=>{console.log("WebSocket connection closed"),this.#s?.delete(o);},a.onerror=c=>{n&&n(c),console.error("WebSocket error:",c);},a}unsubscribeOrderNotifications(e){if(e){let t=M({profile:e?.profile,state:e?.state}),n=this.#s?.get(t);n&&(n.close(),this.#s?.delete(t));}else this.#s?.forEach(t=>{t?.close();}),this.#s?.clear(),this.#s=void 0;}async disconnect(){y||localStorage.removeItem(_),this.unsubscribeOrderNotifications(),this.#i=void 0,this.bearerProfile=void 0;}async revokeAccess(){y||(localStorage.removeItem(k),localStorage.removeItem(S)),this.disconnect();}getEnvironment=()=>this.#e},Z=()=>{let r=$(),e=B(r);return localStorage.setItem(T.STORAGE_CODE_VERIFIER,r),e};var xr=v;
16
+ exports.AccountState=ae;exports.Currency=W;exports.IdDocumentKind=ce;exports.KYCOutcome=oe;exports.KYCState=ie;exports.Method=re;exports.MoneriumApiError=g;exports.MoneriumClient=v;exports.MoneriumSdkError=x;exports.OrderKind=ue;exports.OrderState=le;exports.PaymentStandard=de;exports.Permission=ne;exports.ProfileState=se;exports.ProfileType=te;exports.authorizationCodeGrant=xe;exports.buildAuthorizationUrl=ye;exports.buildSiweAuthorizationUrl=Pe;exports.calculatePKCECodeChallenge=B;exports.clientCredentialsGrant=Ae;exports.constants=T;exports.createMoneriumClient=Ce;exports.default=xr;exports.getChain=z;exports.parseAuthorizationResponse=be;exports.parseChain=h;exports.placeOrderMessage=he;exports.randomPKCECodeVerifier=$;exports.refreshTokenGrant=we;exports.rfc3339=R;exports.shortenAddress=fe;exports.shortenIban=H;exports.siweMessage=me;
package/dist/index.mjs CHANGED
@@ -1,15 +1,16 @@
1
- import z from'crypto-js/enc-base64url.js';import q from'crypto-js/sha256.js';var x={environments:{production:{name:"production",api:"https://api.monerium.app",web:"https://monerium.app",wss:"wss://api.monerium.app"},sandbox:{name:"sandbox",api:"https://api.monerium.dev",web:"https://sandbox.monerium.dev",wss:"wss://api.monerium.dev"}}};var f={LINK_MESSAGE:"I hereby declare that I am the address owner.",STORAGE_CODE_VERIFIER:"monerium.sdk.code_verifier",STORAGE_ACCESS_TOKEN:"monerium.sdk.access_token",STORAGE_ACCESS_EXPIRY:"monerium.sdk.access_expiry"};var A=()=>{let t="",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",r=e.length,n=0;for(;n<128;)t+=e.charAt(Math.floor(Math.random()*r)),n+=1;return t},j=t=>z.stringify(q(t)),S=()=>{let t=A(),e=j(t);return localStorage.setItem(f.STORAGE_CODE_VERIFIER,t||""),e},k=()=>{let t=window.location.href;if(!t||!t?.includes("?"))return;let[e,r]=t.split("?");r&&window.history.replaceState(null,"",e);},R=t=>t.code!=null,$=t=>t.refresh_token!=null,v=t=>t.client_secret!=null;var _=async(t,e,r,n)=>{let i=await fetch(`${t}`,{method:e,headers:n,body:r}),s,a=await i.text();try{if(s=JSON.parse(a),Object.keys(s).length===0&&s.constructor===Object)switch(i.status){case 201:case 202:return {status:i.status,statusText:i.statusText}}}catch{throw a}if(!i.ok)throw s;return s};var u=t=>{if(!t)return "";let e=Object.entries(t).filter(([r,n])=>n!==""&&n!==void 0&&n!==null).map(([r,n])=>`${encodeURIComponent(r)}=${encodeURIComponent(n)}`).join("&");return e?"?"+e:""};var N=t=>t?e=>{console.log("%c [MONERIUM:DEBUG]:","color:orange;",e);}:()=>{};var E=t=>Object.entries(t).filter(([r,n])=>n!=null).map(([r,n])=>`${r}-${n}`).join("-");var B=(i=>(i.eur="eur",i.usd="usd",i.gbp="gbp",i.isk="isk",i))(B||{}),K=(s=>(s.password="password",s.resource="resource",s.jwt="jwt",s.apiKey="apiKey",s.bearer="bearer",s))(K||{}),M=(r=>(r.corporate="corporate",r.personal="personal",r))(M||{}),F=(r=>(r.read="read",r.write="write",r))(F||{}),L=(s=>(s.created="created",s.pending="pending",s.approved="approved",s.rejected="rejected",s.blocked="blocked",s))(L||{}),Q=(i=>(i.absent="absent",i.submitted="submitted",i.pending="pending",i.confirmed="confirmed",i))(Q||{}),W=(n=>(n.approved="approved",n.rejected="rejected",n.unknown="unknown",n))(W||{}),V=(s=>(s.requested="requested",s.approved="approved",s.pending="pending",s.rejected="rejected",s.closed="closed",s))(V||{}),G=(i=>(i.iban="iban",i.scan="scan",i.chain="chain",i.account="account",i))(G||{}),J=(n=>(n.passport="passport",n.nationalIdentityCard="nationalIdentityCard",n.drivingLicense="drivingLicense",n))(J||{}),H=(r=>(r.redeem="redeem",r.issue="issue",r))(H||{}),X=(i=>(i.placed="placed",i.pending="pending",i.processed="processed",i.rejected="rejected",i))(X||{});var P=t=>{if(t.toString()==="Invalid Date")throw t;let e=n=>n<10?"0"+n:n,r=n=>{if(n===0)return "Z";let i=n>0?"-":"+";return n=Math.abs(n),i+e(Math.floor(n/60))+":"+e(n%60)};return t.getFullYear()+"-"+e(t.getMonth()+1)+"-"+e(t.getDate())+"T"+e(t.getHours())+":"+e(t.getMinutes())+":"+e(t.getSeconds())+r(t.getTimezoneOffset())},Z=t=>{switch(t){case "noble":case "noble-1":case "grand":case "grand-1":return true;default:return false}},Y=t=>{switch(t){case "ethereum":case "sepolia":case "polygon":case "amoy":case "gnosis":case "chiado":case "arbitrum":case "arbitrumsepolia":case "linea":case "lineasepolia":case "scroll":case "scrollsepolia":case "camino":case "columbus":return true;default:return false}},b=t=>{if(typeof t=="number")return O(t);if(Z(t))return t.split("-")[0];if(Y(t))return t;try{return O(parseInt(t))}catch{throw new Error(`Chain not supported: ${t}`)}},g=(t,e)=>b(T(e,t)),ee=(t,e,r,n)=>{let i=`${e?.toUpperCase()||"EUR"}`;return n?`Send ${i} ${t} to ${r} on ${b(n)} at ${P(new Date)}`:i==="EUR"?`Send ${i} ${t} to ${D(r)} at ${P(new Date)}`:`Send ${i} ${t} to ${r} at ${P(new Date)}`},te=({domain:t,address:e,appName:r,redirectUri:n,chainId:i,issuedAt:s=new Date().toISOString(),expiryAt:a=new Date(Date.now()+1e3*60*5).toISOString(),privacyPolicyUrl:o,termsOfServiceUrl:l})=>`${t} wants you to sign in with your Ethereum account:
1
+ import G from'crypto-js/enc-base64url.js';import Y from'crypto-js/lib-typedarrays.js';import ee from'crypto-js/sha256.js';var g=class extends Error{code;status;errors;details;constructor(e){super(e.message),this.name="MoneriumApiError",this.code=e.code,this.status=e.status,this.errors=e.errors,this.details=e.details;}},x=class extends Error{type;cause;constructor(e,t,n){super(t),this.name="MoneriumSdkError",this.type=e,this.cause=n;}};var V=()=>{let r="",e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t=e.length,n=0;for(;n<128;)r+=e.charAt(Math.floor(Math.random()*t)),n+=1;return r};var O=()=>{let r=window.location.href;if(!r||!r?.includes("?"))return;let[e,t]=r.split("?");t&&window.history.replaceState(null,"",e);},N=r=>r.code!=null,K=r=>r.refresh_token!=null,j=r=>r.client_secret!=null,$=()=>{let r=new Uint8Array(32);return crypto.getRandomValues(r),G.stringify(Y.create(r))},B=r=>G.stringify(ee(r));var D=async(r,e,t,n)=>{let i=await fetch(`${r}`,{method:e,headers:n,body:t}),s,o=await i.text();try{if(s=JSON.parse(o),Object.keys(s).length===0&&s.constructor===Object)switch(i.status){case 201:case 202:return {status:i.status,statusText:i.statusText}}}catch{throw o}if(!i.ok)throw s;return s};var U=[{production:{id:"ethereum",chainId:1},sandbox:{id:"sepolia",chainId:11155111}},{production:{id:"gnosis",chainId:100},sandbox:{id:"chiado",chainId:10200}},{production:{id:"polygon",chainId:137},sandbox:{id:"amoy",chainId:80002}},{production:{id:"arbitrum",chainId:42161},sandbox:{id:"arbitrumsepolia",chainId:421614}},{production:{id:"linea",chainId:59144},sandbox:{id:"lineasepolia",chainId:59141}},{production:{id:"scroll",chainId:534352},sandbox:{id:"scrollsepolia",chainId:534351}},{production:{id:"base",chainId:8453},sandbox:{id:"basesepolia",chainId:84532}},{production:{id:"camino",chainId:500},sandbox:{id:"columbus",chainId:501}}],F=new Map(U.flatMap(({production:r,sandbox:e})=>[[r.chainId,r.id],[e.chainId,e.id]])),Q=new Set(U.flatMap(({production:r,sandbox:e})=>[r.id,e.id])),L=new Map(U.map(({production:r,sandbox:e})=>[r.id,e.id]));var W=(i=>(i.eur="eur",i.usd="usd",i.gbp="gbp",i.isk="isk",i))(W||{}),re=(s=>(s.password="password",s.resource="resource",s.jwt="jwt",s.apiKey="apiKey",s.bearer="bearer",s))(re||{}),te=(t=>(t.corporate="corporate",t.personal="personal",t))(te||{}),ne=(t=>(t.read="read",t.write="write",t))(ne||{}),se=(s=>(s.created="created",s.pending="pending",s.approved="approved",s.rejected="rejected",s.blocked="blocked",s))(se||{}),ie=(i=>(i.absent="absent",i.submitted="submitted",i.pending="pending",i.confirmed="confirmed",i))(ie||{}),oe=(n=>(n.approved="approved",n.rejected="rejected",n.unknown="unknown",n))(oe||{}),ae=(s=>(s.requested="requested",s.approved="approved",s.pending="pending",s.rejected="rejected",s.closed="closed",s))(ae||{}),de=(i=>(i.iban="iban",i.scan="scan",i.chain="chain",i.account="account",i))(de||{}),ce=(n=>(n.passport="passport",n.nationalIdentityCard="nationalIdentityCard",n.drivingLicense="drivingLicense",n))(ce||{}),ue=(t=>(t.redeem="redeem",t.issue="issue",t))(ue||{}),le=(i=>(i.placed="placed",i.pending="pending",i.processed="processed",i.rejected="rejected",i))(le||{});var R=r=>{if(r.toString()==="Invalid Date")throw r;let e=n=>n<10?"0"+n:n,t=n=>{if(n===0)return "Z";let i=n>0?"-":"+";return n=Math.abs(n),i+e(Math.floor(n/60))+":"+e(n%60)};return r.getFullYear()+"-"+e(r.getMonth()+1)+"-"+e(r.getDate())+"T"+e(r.getHours())+":"+e(r.getMinutes())+":"+e(r.getSeconds())+t(r.getTimezoneOffset())},pe=r=>{switch(r){case "noble":case "noble-1":case "grand":case "grand-1":return true;default:return false}},ge=r=>Q.has(r),h=r=>{if(typeof r=="number")return z(r);if(pe(r))return r.split("-")[0];if(ge(r))return r;try{return z(parseInt(r))}catch{throw new Error(`Chain not supported: ${r}`)}},w=(r,e)=>h(J(e,r)),he=(r,e,t,n)=>{let i=`${e?.toUpperCase()||"EUR"}`;return n?`Send ${i} ${r} to ${t} on ${h(n)} at ${R(new Date)}`:i==="EUR"?`Send ${i} ${r} to ${H(t)} at ${R(new Date)}`:`Send ${i} ${r} to ${t} at ${R(new Date)}`},me=({domain:r,address:e,appName:t,redirectUri:n,chainId:i,issuedAt:s=new Date().toISOString(),expiryAt:o=new Date(Date.now()+1e3*60*5).toISOString(),privacyPolicyUrl:a,termsOfServiceUrl:d})=>`${r} wants you to sign in with your Ethereum account:
2
2
  ${e}
3
3
 
4
- Allow ${r} to access my data on Monerium
4
+ Allow ${t} to access my data on Monerium
5
5
 
6
6
  URI: ${n}
7
7
  Version: 1
8
8
  Chain ID: ${i}
9
- Nonce: ${A().slice(0,16)}
9
+ Nonce: ${V().slice(0,16)}
10
10
  Issued At: ${s}
11
- Expiration Time: ${a}
11
+ Expiration Time: ${o}
12
12
  Resources:
13
13
  - https://monerium.com/siwe
14
- - ${o}
15
- - ${l}`,C=t=>t&&Object.entries(t)?.length>0?Object.entries(t).filter(([e,r])=>r!==void 0).map(([e,r])=>`${encodeURIComponent(e)}=${encodeURIComponent(r)}`).join("&"):"",O=t=>{switch(t){case 1:return "ethereum";case 11155111:return "sepolia";case 100:return "gnosis";case 10200:return "chiado";case 137:return "polygon";case 80002:return "amoy";case 42161:return "arbitrum";case 421614:return "arbitrumsepolia";case 59144:return "linea";case 59141:return "lineasepolia";case 534352:return "scroll";case 534351:return "scrollsepolia";case 501:return "columbus";case 500:return "camino";default:throw new Error(`Chain not supported: ${t}`)}},D=t=>{if(typeof t!="string"||!t?.length)return t;let e=t.replace(/\s/g,"");return t?.length>11?`${e.substring(0,4)}...${e.substring(e.length-4)}`:t},re=t=>typeof t!="string"||!t?.length?t:t?.length>11?`${t.substring(0,7)}...${t.substring(t.length-5)}`:t;var T=(t,e)=>{if(e==="sandbox")switch(t){case "ethereum":return "sepolia";case "polygon":return "amoy";case "gnosis":return "chiado";case "arbitrum":return "arbitrumsepolia";case "linea":return "lineasepolia";case "scroll":return "scrollsepolia";case "camino":return "columbus";case "noble":return "noble";default:return t}return t},p=(t,e)=>{if(e?.chain){let{chain:r,...n}=e;return {...n,chain:b(T(r,t))}}return e};var {STORAGE_CODE_VERIFIER:w,STORAGE_ACCESS_TOKEN:h,STORAGE_ACCESS_EXPIRY:m}=f,d=typeof window>"u",I=class{#e;#s;bearerProfile;#i=new Map;isAuthorized=!!this.bearerProfile;#r=()=>{};#n;state;constructor(e){if(!e){this.#e=x.environments.sandbox;return}if(typeof e=="string")this.#e=x.environments[e];else if(this.#r=N(e.debug??false),this.#e=x.environments[e.environment||"sandbox"],!d&&!e?.clientSecret){let{clientId:r,redirectUri:n}=e;this.#n={clientId:r,redirectUri:n};}else if(d&&e?.clientSecret){this.#r("Client credentials detected");let{clientId:r,clientSecret:n}=e;this.#n={clientId:r,clientSecret:n};}}async authorize(e){let r=S(),n=e?.address?{address:e?.address,signature:e?.signature,chain:e?.chain?g(this.#e.name,e?.chain):void 0}:{},i=C({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,code_challenge:r,code_challenge_method:"S256",response_type:"code",state:e?.state,skip_create_account:e?.skipCreateAccount,skip_kyc:e?.skipKyc,email:e?.email,...n}),s=`${this.#e.api}/auth?${i}`;this.#r(`Auth flow URL: ${s}`),window.location.assign(s);}async siwe(e){let r=S(),n=C({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,message:e.message,signature:e.signature,code_challenge:r,code_challenge_method:"S256",authentication_method:"siwe",state:e?.state}),i=`${this.#e.api}/auth?${n}`;this.#r(`Auth flow SIWE URL: ${i}`),window.location.assign(i);}async getAccess(e){let r=this.#n?.clientId;if(this.#n?.clientSecret){if(d)return await this.#c(this.#n),!!this?.bearerProfile;console.error("\x1B[31m%s\x1B[0m","Use client credentials only on the server where the secret is secure!");}let i=this.#n?.redirectUri;if(!r)throw new Error("Missing ClientId");if(d)throw new Error("This only works client side");let s=new URLSearchParams(window.location.search).get("error")||void 0,a=new URLSearchParams(window.location.search).get("error_description")||void 0;if(s||a)throw new Error(a);let o=new URLSearchParams(window.location.search).get("code")||void 0,l=new URLSearchParams(window.location.search).get("state")||void 0,c=window.localStorage.getItem(h),y=window.localStorage.getItem(m);if(o)return this.#r("Using auth code from auth flow to authorize"),await this.#a(r,i,o,l),this.#r(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(e)return this.#r("Using refresh token to authorize"),await this.#d(r,e),this.#r(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(c&&y){let U=new Date;if(parseInt(y)<U.getTime())throw window.localStorage.removeItem(h),window.localStorage.removeItem(m),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token has expired");this.#r("Access token should still be valid, checking if it is authorized...");try{return this.#s=`Bearer ${c}`,this.isAuthorized=!0,await this.getTokens(),this.#r("Authorized"),!0}catch{throw this.#r("Access token is invalid."),window.localStorage.removeItem(h),window.localStorage.removeItem(m),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token is invalid.")}}return this.#r(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile}async#o(e){let r;if(R(e))r={...e,grant_type:"authorization_code"};else if($(e))r={...e,grant_type:"refresh_token"};else if(v(e))r={...e,grant_type:"client_credentials"};else throw new Error("Authorization grant type could not be detected.");return await this.#t("post","auth/token",r,true).then(n=>{if(this.bearerProfile=n,this.isAuthorized=!!n,this.#s=`Bearer ${n?.access_token}`,!d){let s=new Date().getTime()+n?.expires_in*1e3;window.localStorage.setItem(h,n?.access_token||""),window.localStorage.setItem(m,s?.toString());}}).catch(n=>{throw d||(localStorage.removeItem(w),localStorage.removeItem(h),localStorage.removeItem(m),k()),new Error(n?.message)}),R(e)&&k(),this.bearerProfile}getAuthContext(){return this.#t("get","auth/context")}getProfile(e){return this.#t("get",`profiles/${e}`)}getProfiles(e){return this.#t("get",`profiles${u(e)}`)}getAddress(e){return this.#t("get",`addresses/${e}`)}getAddresses(e){e=p(this.#e.name,e);let r=e?C(e):void 0,n=r?`addresses?${r}`:"addresses";return this.#t("get",n)}getBalances(e,r,n){let i=Array.isArray(n)?n.map(a=>`currency=${a}`).join("&"):n?`currency=${n}`:"",s=g(this.#e.name,r);return this.#t("get",`balances/${s}/${e}${i?`?${i}`:""}`)}getIban(e){return this.#t("get",`ibans/${encodeURI(e)}`)}getIbans(e){let{profile:r,chain:n}=e||{},i=u({profile:r,chain:n?g(this.#e.name,n):""});return this.#t("get",`ibans${i}`)}getOrders(e){return this.#t("get",`orders${u(e)}`)}getOrder(e){return this.#t("get",`orders/${e}`)}getTokens(){return this.#t("get","tokens")}getSignatures(e){let r=e?p(this.#e.name,e):void 0;return this.#t("get",`signatures${u(r)}`)}linkAddress(e){return e=p(this.#e.name,e),this.#t("post","addresses",JSON.stringify(e))}placeOrder(e){let r={kind:"redeem",...p(this.#e.name,e),counterpart:{...e.counterpart,identifier:p(this.#e.name,e.counterpart.identifier)}};return this.#t("post","orders",JSON.stringify(r))}moveIban(e,{address:r,chain:n}){return this.#t("patch",`ibans/${e}`,JSON.stringify({address:r,chain:g(this.#e.name,n)}))}requestIban({address:e,chain:r,emailNotifications:n=true}){return this.#t("post","ibans",JSON.stringify({address:e,chain:g(this.#e.name,r),emailNotifications:n}))}submitProfileDetails(e,r){return this.#t("put",`profiles/${e}/details`,JSON.stringify(r))}uploadSupportingDocument(e){let r=new FormData;return r.append("file",e),_(`${this.#e.api}/files`,"post",r,{Authorization:this.#s||""})}async#t(e,r,n,i){let s={Authorization:this.#s||"",Accept:"application/vnd.monerium.api-v2+json","Content-Type":`application/${i?"x-www-form-urlencoded":"json"}`};return _(`${this.#e.api}/${r}`,e.toUpperCase(),i?C(n):n,s)}#a=async(e,r,n,i)=>{let s=localStorage.getItem(w)||"";if(!s)throw new Error("Code verifier not found");return this.#r("Use code verifier to authorize"),this.state=i,localStorage.removeItem(w),await this.#o({code:n,redirect_uri:r,client_id:e,code_verifier:s})};#c=async({clientId:e,clientSecret:r})=>await this.#o({client_id:e,client_secret:r});#d=async(e,r)=>await this.#o({refresh_token:r,client_id:e});subscribeOrderNotifications({filter:e,onMessage:r,onError:n}={}){if(!this.bearerProfile?.access_token)return;let{profile:i,state:s}=e||{},a=u({access_token:this.bearerProfile?.access_token,profile:i,state:s}),o,l=E({profile:i,state:s});if(this.#i?.has(l))o=this.#i.get(l);else {let c=`${this.#e.wss}/orders${a}`;o=new WebSocket(c),this.#i?.set(l,o);}return o.onopen=()=>{console.log("Connected to WebSocket server");},o.onmessage=c=>{let y=JSON.parse(c.data);r&&r(y);},o.onclose=()=>{console.log("WebSocket connection closed"),this.#i?.delete(a);},o.onerror=c=>{n&&n(c),console.error("WebSocket error:",c);},o}unsubscribeOrderNotifications(e){if(e){let r=E({profile:e?.profile,state:e?.state}),n=this.#i?.get(r);n&&(n.close(),this.#i?.delete(r));}else this.#i?.forEach(r=>{r?.close();}),this.#i?.clear(),this.#i=void 0;}async disconnect(){d||localStorage.removeItem(w),this.unsubscribeOrderNotifications(),this.#s=void 0,this.bearerProfile=void 0;}async revokeAccess(){d||(localStorage.removeItem(h),localStorage.removeItem(m)),this.disconnect();}getEnvironment=()=>this.#e};var De=I;export{V as AccountState,B as Currency,J as IdDocumentKind,W as KYCOutcome,Q as KYCState,K as Method,I as MoneriumClient,H as OrderKind,X as OrderState,G as PaymentStandard,F as Permission,L as ProfileState,M as ProfileType,f as constants,De as default,O as getChain,b as parseChain,ee as placeOrderMessage,P as rfc3339,re as shortenAddress,D as shortenIban,te as siweMessage};
14
+ - ${a}
15
+ - ${d}`,m=r=>r&&Object.entries(r)?.length>0?Object.entries(r).filter(([e,t])=>t!==""&&t!==void 0&&t!==null).map(([e,t])=>`${encodeURIComponent(e)}=${encodeURIComponent(t)}`).join("&"):"",z=r=>{let e=F.get(r);if(!e)throw new Error(`Chain not supported: ${r}`);return e},H=r=>{if(typeof r!="string"||!r?.length)return r;let e=r.replace(/\s/g,"");return r?.length>11?`${e.substring(0,4)}...${e.substring(e.length-4)}`:r},fe=r=>typeof r!="string"||!r?.length?r:r?.length>11?`${r.substring(0,7)}...${r.substring(r.length-5)}`:r;var J=(r,e)=>e==="sandbox"&&typeof r=="string"?L.get(r)??r:r,A=(r,e)=>{if(e?.chain){let{chain:t,...n}=e;return {...n,chain:h(J(t,r))}}return e};var u=r=>{if(!r)return "";let e=m(r);return e?`?${e}`:""};var b={environments:{production:{name:"production",api:"https://api.monerium.app",web:"https://monerium.app",wss:"wss://api.monerium.app"},sandbox:{name:"sandbox",api:"https://api.monerium.dev",web:"https://sandbox.monerium.dev",wss:"wss://api.monerium.dev"}}};var M=r=>Object.entries(r).filter(([t,n])=>n!=null).map(([t,n])=>`${t}-${n}`).join("-");function C(r="sandbox"){return b.environments[r]}var E=async({method:r,url:e,headers:t,body:n,signal:i})=>{let s;try{s=await fetch(e,{method:r,headers:t,body:n,signal:i});}catch(a){throw new x("network_error","Network request failed",a)}let o=await s.text();return {status:s.status,bodyText:o}};function I(r){return r?.chain!==void 0?{...r,chain:h(r.chain)}:r}function Ce(r){let e=C(r.environment),t=r.transport??E;async function n(){return "getAccessToken"in r&&r.getAccessToken?r.getAccessToken():"accessToken"in r&&r.accessToken?r.accessToken:null}async function i(o,a,d){let c=await n(),l={Accept:"application/vnd.monerium.api-v2+json"};c&&(l.Authorization=`Bearer ${c}`);let{status:p,bodyText:f}=await t({method:o.toUpperCase(),url:`${e.api}/${a}`,headers:l,body:d});if(!f)return {status:p};let P;try{P=JSON.parse(f);}catch{throw new g({code:p,status:"Parse Error",message:f})}if(p<200||p>=300)throw new g(P);return P}async function s(o,a,d){let c=await n(),l={Accept:"application/vnd.monerium.api-v2+json","Content-Type":"application/json"};if(c)l.Authorization=`Bearer ${c}`;else if(a!=="tokens")throw new x("authentication_required","No access token provided for authenticated endpoint");let{status:p,bodyText:f}=await t({method:o.toUpperCase(),url:`${e.api}/${a}`,headers:l,body:d?JSON.stringify(d):void 0});if(!f)return {status:p};let P;try{P=JSON.parse(f);}catch{throw new g({code:p,status:"Parse Error",message:f})}if(p<200||p>=300)throw new g(P);return P}return {getAuthContext:()=>s("GET","auth/context"),getProfile:o=>s("GET",`profiles/${o}`),getProfiles:o=>s("GET",`profiles${u(o)}`),submitProfileDetails:(o,a)=>s("PATCH",`profiles/${o}/details`,a),getAddress:o=>s("GET",`addresses/${o}`),getAddresses:o=>s("GET",`addresses${u(o?I(o):void 0)}`),getBalances:(o,a,d)=>{let c=h(a),l=Array.isArray(d)?d.map(p=>`currency=${p}`).join("&"):d?`currency=${d}`:"";return s("GET",`balances/${c}/${o}${l?`?${l}`:""}`)},linkAddress:o=>s("POST","addresses",I(o)),getIban:o=>s("GET",`ibans/${encodeURI(o)}`),getIbans:o=>{let a=o?I(o):void 0;return s("GET",`ibans${u(a)}`)},requestIban:({address:o,chain:a,emailNotifications:d=true})=>s("POST","ibans",{address:o,chain:h(a),emailNotifications:d}),moveIban:(o,{address:a,chain:d})=>s("PATCH",`ibans/${o}`,{address:a,chain:h(d)}),getOrder:o=>s("GET",`orders/${o}`),getOrders:o=>s("GET",`orders${u(o)}`),placeOrder:o=>{let a={kind:"redeem",...I(o),...o.counterpart&&{counterpart:{...o.counterpart,identifier:I(o.counterpart.identifier)}}};return s("POST","orders",a)},getTokens:()=>s("GET","tokens"),getSignatures:o=>{let a=o?I(o):void 0;return s("GET",`signatures${u(a)}`)},uploadSupportingDocument:(o,a)=>{let d=o instanceof Blob?o:new Blob([o]),c=new FormData;return c.append("file",d,a),i("POST","files",c)}}}var ye=r=>{let e=C(r.environment),t=u({client_id:r.clientId,redirect_uri:r.redirectUri,code_challenge:r.codeChallenge,code_challenge_method:"S256",response_type:"code",state:r.state,skip_kyc:r.skipKyc,email:r.email,address:r.address,signature:r.signature,chain:r.chain});return `${e.api}/auth${t}`},Pe=r=>{let e=C(r.environment),t=u({client_id:r.clientId,redirect_uri:r.redirectUri,message:r.message,signature:r.signature,code_challenge:r.codeChallenge,code_challenge_method:"S256",authentication_method:"siwe",state:r.state});return `${e.api}/auth${t}`};async function q(r,e,t=E){let n=m(Object.fromEntries(Object.entries(e).filter(([,a])=>a!==void 0))),{status:i,bodyText:s}=await t({method:"POST",url:r,headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/vnd.monerium.api-v2+json"},body:n}),o;try{o=JSON.parse(s);}catch{throw new g({code:i,status:"Parse Error",message:s})}if(i<200||i>=300)throw new g(o);return o}var xe=r=>{let e=C(r.environment);return q(`${e.api}/auth/token`,{grant_type:"authorization_code",client_id:r.clientId,redirect_uri:r.redirectUri,code:r.code,code_verifier:r.codeVerifier},r.transport)},we=r=>{let e=C(r.environment);return q(`${e.api}/auth/token`,{grant_type:"refresh_token",client_id:r.clientId,refresh_token:r.refreshToken},r.transport)},Ae=r=>{let e=C(r.environment);return q(`${e.api}/auth/token`,{grant_type:"client_credentials",client_id:r.clientId,client_secret:r.clientSecret},r.transport)},be=r=>{if(typeof r!="string")return {};let e=r,t=e.includes("?")?e.split("?")[1]:e;if(!t)return {};let n={};for(let s of t.split("&")){let o=s.indexOf("=");if(o===-1)continue;let a=decodeURIComponent(s.slice(0,o)),d=decodeURIComponent(s.slice(o+1).replace(/\+/g," "));n[a]=d;}let i={};return n.code&&(i.code=n.code),n.state&&(i.state=n.state),n.error&&(i.error=n.error),n.error_description&&(i.errorDescription=n.error_description),i};var T={LINK_MESSAGE:"I hereby declare that I am the address owner.",STORAGE_CODE_VERIFIER:"monerium.sdk.code_verifier",STORAGE_ACCESS_TOKEN:"monerium.sdk.access_token",STORAGE_ACCESS_EXPIRY:"monerium.sdk.access_expiry"};var X=r=>r?e=>{console.log("%c [MONERIUM:DEBUG]:","color:orange;",e);}:()=>{};var {STORAGE_CODE_VERIFIER:_,STORAGE_ACCESS_TOKEN:k,STORAGE_ACCESS_EXPIRY:S}=T,y=typeof window>"u",v=class{#e;#i;bearerProfile;#s=new Map;isAuthorized=!!this.bearerProfile;#t=()=>{};#n;state;constructor(e){if(!e){this.#e=b.environments.sandbox;return}if(typeof e=="string")this.#e=b.environments[e];else if(this.#t=X(e.debug??false),this.#e=b.environments[e.environment||"sandbox"],!y&&!e?.clientSecret){let{clientId:t,redirectUri:n}=e;this.#n={clientId:t,redirectUri:n};}else if(y&&e?.clientSecret){this.#t("Client credentials detected");let{clientId:t,clientSecret:n}=e;this.#n={clientId:t,clientSecret:n};}}async authorize(e){let t=Z(),n=e?.address?{address:e?.address,signature:e?.signature,chain:e?.chain?w(this.#e.name,e?.chain):void 0}:{},i=m({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,code_challenge:t,code_challenge_method:"S256",response_type:"code",state:e?.state,skip_kyc:e?.skipKyc,email:e?.email,...n}),s=`${this.#e.api}/auth?${i}`;this.#t(`Auth flow URL: ${s}`),window.location.assign(s);}async siwe(e){let t=Z(),n=m({client_id:this.#n?.clientId,redirect_uri:this.#n?.redirectUri,message:e.message,signature:e.signature,code_challenge:t,code_challenge_method:"S256",authentication_method:"siwe",state:e?.state}),i=`${this.#e.api}/auth?${n}`;this.#t(`Auth flow SIWE URL: ${i}`),window.location.assign(i);}async getAccess(e){let t=this.#n?.clientId;if(this.#n?.clientSecret){if(y)return await this.#d(this.#n),!!this?.bearerProfile;console.error("\x1B[31m%s\x1B[0m","Use client credentials only on the server where the secret is secure!");}let i=this.#n?.redirectUri;if(!t)throw new Error("Missing ClientId");if(y)throw new Error("This only works client side");let s=new URLSearchParams(window.location.search).get("error")||void 0,o=new URLSearchParams(window.location.search).get("error_description")||void 0;if(s||o)throw new Error(o);let a=new URLSearchParams(window.location.search).get("code")||void 0,d=new URLSearchParams(window.location.search).get("state")||void 0,c=window.localStorage.getItem(k),l=window.localStorage.getItem(S);if(a)return this.#t("Using auth code from auth flow to authorize"),await this.#a(t,i,a,d),this.#t(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(e)return this.#t("Using refresh token to authorize"),await this.#c(t,e),this.#t(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile;if(c&&l){let p=new Date;if(parseInt(l)<p.getTime())throw window.localStorage.removeItem(k),window.localStorage.removeItem(S),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token has expired");this.#t("Access token should still be valid, checking if it is authorized...");try{return this.#i=`Bearer ${c}`,this.isAuthorized=!0,await this.getTokens(),this.#t("Authorized"),!0}catch{throw this.#t("Access token is invalid."),window.localStorage.removeItem(k),window.localStorage.removeItem(S),this.isAuthorized=false,this.bearerProfile=void 0,new Error("Access token is invalid.")}}return this.#t(this.bearerProfile?"Authorized":"Not authorized"),!!this.bearerProfile}async#o(e){let t;if(N(e))t={...e,grant_type:"authorization_code"};else if(K(e))t={...e,grant_type:"refresh_token"};else if(j(e))t={...e,grant_type:"client_credentials"};else throw new Error("Authorization grant type could not be detected.");return await this.#r("post","auth/token",t,true).then(n=>{if(this.bearerProfile=n,this.isAuthorized=!!n,this.#i=`Bearer ${n?.access_token}`,!y){let s=new Date().getTime()+n?.expires_in*1e3;window.localStorage.setItem(k,n?.access_token||""),window.localStorage.setItem(S,s?.toString());}}).catch(n=>{throw y||(localStorage.removeItem(_),localStorage.removeItem(k),localStorage.removeItem(S),O()),new Error(n?.message)}),N(e)&&O(),this.bearerProfile}getAuthContext(){return this.#r("get","auth/context")}getProfile(e){return this.#r("get",`profiles/${e}`)}getProfiles(e){return this.#r("get",`profiles${u(e)}`)}getAddress(e){return this.#r("get",`addresses/${e}`)}getAddresses(e){e=A(this.#e.name,e);let t=e?m(e):void 0,n=t?`addresses?${t}`:"addresses";return this.#r("get",n)}getBalances(e,t,n){let i=Array.isArray(n)?n.map(o=>`currency=${o}`).join("&"):n?`currency=${n}`:"",s=w(this.#e.name,t);return this.#r("get",`balances/${s}/${e}${i?`?${i}`:""}`)}getIban(e){return this.#r("get",`ibans/${encodeURI(e)}`)}getIbans(e){let{profile:t,chain:n}=e||{},i=u({profile:t,chain:n?w(this.#e.name,n):""});return this.#r("get",`ibans${i}`)}getOrders(e){return this.#r("get",`orders${u(e)}`)}getOrder(e){return this.#r("get",`orders/${e}`)}getTokens(){return this.#r("get","tokens")}getSignatures(e){let t=e?A(this.#e.name,e):void 0;return this.#r("get",`signatures${u(t)}`)}linkAddress(e){return e=A(this.#e.name,e),this.#r("post","addresses",JSON.stringify(e))}placeOrder(e){let t={kind:"redeem",...A(this.#e.name,e),counterpart:{...e.counterpart,identifier:A(this.#e.name,e.counterpart.identifier)}};return this.#r("post","orders",JSON.stringify(t))}moveIban(e,{address:t,chain:n}){return this.#r("patch",`ibans/${e}`,JSON.stringify({address:t,chain:w(this.#e.name,n)}))}requestIban({address:e,chain:t,emailNotifications:n=true}){return this.#r("post","ibans",JSON.stringify({address:e,chain:w(this.#e.name,t),emailNotifications:n}))}submitProfileDetails(e,t){return this.#r("put",`profiles/${e}/details`,JSON.stringify(t))}uploadSupportingDocument(e){let t=new FormData;return t.append("file",e),D(`${this.#e.api}/files`,"post",t,{Authorization:this.#i||""})}async#r(e,t,n,i){let s={Authorization:this.#i||"",Accept:"application/vnd.monerium.api-v2+json","Content-Type":`application/${i?"x-www-form-urlencoded":"json"}`};return D(`${this.#e.api}/${t}`,e.toUpperCase(),i?m(n):n,s)}#a=async(e,t,n,i)=>{let s=localStorage.getItem(_)||"";if(!s)throw new Error("Code verifier not found");return this.#t("Use code verifier to authorize"),this.state=i,localStorage.removeItem(_),await this.#o({code:n,redirect_uri:t,client_id:e,code_verifier:s})};#d=async({clientId:e,clientSecret:t})=>await this.#o({client_id:e,client_secret:t});#c=async(e,t)=>await this.#o({refresh_token:t,client_id:e});subscribeOrderNotifications({filter:e,onMessage:t,onError:n}={}){if(!this.bearerProfile?.access_token)return;let{profile:i,state:s}=e||{},o=u({access_token:this.bearerProfile?.access_token,profile:i,state:s}),a,d=M({profile:i,state:s});if(this.#s?.has(d))a=this.#s.get(d);else {let c=`${this.#e.wss}/orders${o}`;a=new WebSocket(c),this.#s?.set(d,a);}return a.onopen=()=>{console.log("Connected to WebSocket server");},a.onmessage=c=>{let l=JSON.parse(c.data);t&&t(l);},a.onclose=()=>{console.log("WebSocket connection closed"),this.#s?.delete(o);},a.onerror=c=>{n&&n(c),console.error("WebSocket error:",c);},a}unsubscribeOrderNotifications(e){if(e){let t=M({profile:e?.profile,state:e?.state}),n=this.#s?.get(t);n&&(n.close(),this.#s?.delete(t));}else this.#s?.forEach(t=>{t?.close();}),this.#s?.clear(),this.#s=void 0;}async disconnect(){y||localStorage.removeItem(_),this.unsubscribeOrderNotifications(),this.#i=void 0,this.bearerProfile=void 0;}async revokeAccess(){y||(localStorage.removeItem(k),localStorage.removeItem(S)),this.disconnect();}getEnvironment=()=>this.#e},Z=()=>{let r=$(),e=B(r);return localStorage.setItem(T.STORAGE_CODE_VERIFIER,r),e};var xr=v;
16
+ export{ae as AccountState,W as Currency,ce as IdDocumentKind,oe as KYCOutcome,ie as KYCState,re as Method,g as MoneriumApiError,v as MoneriumClient,x as MoneriumSdkError,ue as OrderKind,le as OrderState,de as PaymentStandard,ne as Permission,se as ProfileState,te as ProfileType,xe as authorizationCodeGrant,ye as buildAuthorizationUrl,Pe as buildSiweAuthorizationUrl,B as calculatePKCECodeChallenge,Ae as clientCredentialsGrant,T as constants,Ce as createMoneriumClient,xr as default,z as getChain,be as parseAuthorizationResponse,h as parseChain,he as placeOrderMessage,$ as randomPKCECodeVerifier,we as refreshTokenGrant,R as rfc3339,fe as shortenAddress,H as shortenIban,me as siweMessage};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monerium/sdk",
3
- "version": "3.4.10",
3
+ "version": "3.5.0",
4
4
  "description": "Essential tools to interact with the Monerium API, an electronic money issuer.",
5
5
  "repository": {
6
6
  "type": "git",