@alviere/core 0.18.1 → 0.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -149,7 +149,6 @@ class Cryptor {
149
149
  *
150
150
  */
151
151
  constructor(logger) {
152
- this.nonce = new Uint8Array(12);
153
152
  this.logger = logger;
154
153
  this.rsa_key = getRSA_PUB_KEY();
155
154
  this.key = this.generate_key();
@@ -161,14 +160,14 @@ class Cryptor {
161
160
  * @returns
162
161
  */
163
162
  async encrypt(data) {
164
- this.nonce = this.generate_nonce();
163
+ const nonce = this.generate_nonce();
165
164
  const encoded = new TextEncoder().encode(JSON.stringify(data));
166
- const alg = { name: "AES-GCM", iv: this.nonce };
165
+ const alg = { name: "AES-GCM", iv: nonce };
167
166
  const crypto_key = await this.import_key();
168
167
  const cipher = await crypto.subtle.encrypt(alg, crypto_key, encoded);
169
168
  const cipherB64 = btoa(this.bufferToStr(new Uint8Array(cipher)));
170
169
  const keyB64 = btoa(this.bufferToStr(this.key));
171
- const nonceB64 = btoa(this.bufferToStr(this.nonce));
170
+ const nonceB64 = btoa(this.bufferToStr(nonce));
172
171
  this.logger?.debug(`🔐 RSA_KEY: ${this.rsa_key.substring(0, 50)}...`);
173
172
  const publicKey = pki.publicKeyFromPem(this.rsa_key);
174
173
  const keyNonceB64 = btoa(publicKey.encrypt(keyB64 + "::" + nonceB64));
@@ -180,16 +179,17 @@ class Cryptor {
180
179
  this.logger?.debug(
181
180
  `🔐 ENCRYPTED_REQUEST: p=${encrypted_request.p.substring(0, 20)}..., i=${encrypted_request.i}`
182
181
  );
183
- return encrypted_request;
182
+ return { request: encrypted_request, nonce };
184
183
  }
185
184
  /**
186
185
  *
187
186
  * @param data
187
+ * @param nonce the nonce returned by the encrypt() call this response corresponds to
188
188
  * @returns
189
189
  */
190
- async decrypt(data) {
190
+ async decrypt(data, nonce) {
191
191
  const decrypted = await crypto.subtle.decrypt(
192
- { name: "AES-GCM", iv: this.nonce },
192
+ { name: "AES-GCM", iv: nonce },
193
193
  await this.import_key(),
194
194
  Uint8Array.from(atob(data.p), (c) => c.charCodeAt(0))
195
195
  );
@@ -712,6 +712,7 @@ class AlcoreBase {
712
712
  */
713
713
  constructor(jwt, cryptor, logger) {
714
714
  this.endpoint = "/alcore";
715
+ this.responseNonces = /* @__PURE__ */ new WeakMap();
715
716
  this.jwt = jwt;
716
717
  this.cryptor = cryptor;
717
718
  this.domain = getALVIERE_DOMAIN();
@@ -737,8 +738,11 @@ class AlcoreBase {
737
738
  this.logger.debug("DATA TO SEND before encrypt");
738
739
  this.logger.debug(payload);
739
740
  let encryptedData;
741
+ let nonce;
740
742
  try {
741
- encryptedData = await this.cryptor.encrypt(request);
743
+ const encrypted = await this.cryptor.encrypt(request);
744
+ encryptedData = encrypted.request;
745
+ nonce = encrypted.nonce;
742
746
  this.logger.debug("🔐 Encryption successful");
743
747
  } catch (encryptError) {
744
748
  this.logger.debug(
@@ -767,13 +771,14 @@ class AlcoreBase {
767
771
  if (!response.ok) {
768
772
  let error = await response.json();
769
773
  if (error.p) {
770
- error = await this.decrypt(error);
774
+ error = await this.cryptor.decrypt(error, nonce);
771
775
  }
772
776
  const errorCode = response.status === 500 ? AlcoreErrorCodes.UNDERLYING_API_ERROR : error.error_code;
773
777
  const errorDescription = error.error_description || getErrorMessage(errorCode);
774
778
  this.logger.debug(`❌ API Error - Code: ${errorCode}, Description: ${errorDescription}`);
775
779
  throw new AlcoreApiError(errorCode, errorDescription, response.status);
776
780
  }
781
+ this.responseNonces.set(response, nonce);
777
782
  return response;
778
783
  } catch (fetchError) {
779
784
  this.logger.debug(
@@ -785,9 +790,16 @@ class AlcoreBase {
785
790
  /**
786
791
  *
787
792
  * @param data
793
+ * @param response the Response returned by the send() call this data came from
788
794
  */
789
- async decrypt(data) {
790
- return this.cryptor.decrypt(data);
795
+ async decrypt(data, response) {
796
+ const nonce = this.responseNonces.get(response);
797
+ if (!nonce) {
798
+ throw new Error(
799
+ "Cannot decrypt: no nonce recorded for this response. Pass the Response returned by send()."
800
+ );
801
+ }
802
+ return this.cryptor.decrypt(data, nonce);
791
803
  }
792
804
  }
793
805
  function getSanitizedBody(data) {
@@ -883,21 +895,21 @@ class PaymentsGateway extends AlcoreBase {
883
895
  const endpoint = `/accounts/${accountUuid}/payment-methods/cards`;
884
896
  const response = await this.send("POST", endpoint, data);
885
897
  const encrypted = await response.json();
886
- const decrypted = await this.decrypt(encrypted);
898
+ const decrypted = await this.decrypt(encrypted, response);
887
899
  return throwIfApiError(decrypted);
888
900
  }
889
901
  async add_bank_account(accountUuid, data) {
890
902
  const endpoint = `/accounts/${accountUuid}/payment-methods/bank-accounts`;
891
903
  const response = await this.send("POST", endpoint, data);
892
904
  const encrypted = await response.json();
893
- const decrypted = await this.decrypt(encrypted);
905
+ const decrypted = await this.decrypt(encrypted, response);
894
906
  return throwIfApiError(decrypted);
895
907
  }
896
908
  async get_bank_accounts(accountUuid) {
897
909
  const endpoint = `/accounts/${accountUuid}/payment-methods/bank-accounts?limit=100`;
898
910
  const response = await this.send("GET", endpoint, {});
899
911
  const encrypted = await response.json();
900
- const decrypted = await this.decrypt(encrypted);
912
+ const decrypted = await this.decrypt(encrypted, response);
901
913
  return throwIfApiError(decrypted);
902
914
  }
903
915
  async delete_bank_account(accountUuid, uuid) {
@@ -909,7 +921,7 @@ class PaymentsGateway extends AlcoreBase {
909
921
  const endpoint = `/payment-methods/bank-accounts/${uuid}`;
910
922
  const response = await this.send("PATCH", endpoint, data);
911
923
  const encrypted = await response.json();
912
- const decrypted = await this.decrypt(encrypted);
924
+ const decrypted = await this.decrypt(encrypted, response);
913
925
  return throwIfApiError(decrypted);
914
926
  }
915
927
  }
@@ -924,7 +936,7 @@ class WalletsGateway extends AlcoreBase {
924
936
  const endpoint = `/accounts/${accountUuid}/wallets${query}`;
925
937
  const response = await this.send("GET", endpoint, {});
926
938
  const encrypted = await response.json();
927
- const decrypted = await this.decrypt(encrypted);
939
+ const decrypted = await this.decrypt(encrypted, response);
928
940
  return throwIfApiError(decrypted);
929
941
  }
930
942
  // async getWallet(accountUuid: string, walletUuid: string): Promise<WalletResponse> {
@@ -934,7 +946,7 @@ class WalletsGateway extends AlcoreBase {
934
946
  const endpoint = `/wallets/${walletUuid}/load`;
935
947
  const response = await this.send("POST", endpoint, data);
936
948
  const encrypted = await response.json();
937
- const decrypted = await this.decrypt(encrypted);
949
+ const decrypted = await this.decrypt(encrypted, response);
938
950
  return throwIfApiError(decrypted);
939
951
  }
940
952
  // async withdrawFunds(walletUuid: string, data: WithdrawFundsRequest): Promise<WalletTransactionResponse> {
@@ -964,14 +976,14 @@ class PaymentInstrumentsGateway extends AlcoreBase {
964
976
  const endpoint = "/payments/payment-instruments";
965
977
  const response = await this.send("POST", endpoint, data);
966
978
  const encrypted = await response.json();
967
- const decrypted = await this.decrypt(encrypted);
979
+ const decrypted = await this.decrypt(encrypted, response);
968
980
  return throwIfApiError(decrypted);
969
981
  }
970
982
  async getPaymentInstrument(paymentInstrumentUuid) {
971
983
  const endpoint = `/payments/payment-instruments/${paymentInstrumentUuid}`;
972
984
  const response = await this.send("GET", endpoint, {});
973
985
  const encrypted = await response.json();
974
- const decrypted = await this.decrypt(encrypted);
986
+ const decrypted = await this.decrypt(encrypted, response);
975
987
  return throwIfApiError(decrypted);
976
988
  }
977
989
  async deletePaymentInstrument(paymentInstrumentUuid) {
@@ -982,15 +994,17 @@ class PaymentInstrumentsGateway extends AlcoreBase {
982
994
  const endpoint = "/payments/debit";
983
995
  const response = await this.send("POST", endpoint, data);
984
996
  const encrypted = await response.json();
985
- const decrypted = await this.decrypt(encrypted);
997
+ const decrypted = await this.decrypt(encrypted, response);
986
998
  return throwIfApiError(decrypted);
987
999
  }
988
1000
  async listCards(accountUuid, params) {
989
- const query = params ? "?" + new URLSearchParams(Object.entries(params).filter(([_, v]) => v !== void 0)) : "";
1001
+ const query = params ? "?" + new URLSearchParams(
1002
+ Object.entries(params).filter(([_, v]) => v !== void 0)
1003
+ ) : "";
990
1004
  const endpoint = `/accounts/${accountUuid}/payment-methods/cards${query}`;
991
1005
  const response = await this.send("GET", endpoint, {});
992
1006
  const encrypted = await response.json();
993
- const decrypted = await this.decrypt(encrypted);
1007
+ const decrypted = await this.decrypt(encrypted, response);
994
1008
  return throwIfApiError(decrypted);
995
1009
  }
996
1010
  }
@@ -1003,21 +1017,21 @@ class AccountsGateway extends AlcoreBase {
1003
1017
  const endpoint = "/accounts";
1004
1018
  const response = await this.send("POST", endpoint, data);
1005
1019
  const encrypted = await response.json();
1006
- const decrypted = await this.decrypt(encrypted);
1020
+ const decrypted = await this.decrypt(encrypted, response);
1007
1021
  return throwIfApiError(decrypted);
1008
1022
  }
1009
1023
  async getAccount(accountUuid) {
1010
1024
  const endpoint = `/accounts/${accountUuid}`;
1011
1025
  const response = await this.send("GET", endpoint, {});
1012
1026
  const encrypted = await response.json();
1013
- const decrypted = await this.decrypt(encrypted);
1027
+ const decrypted = await this.decrypt(encrypted, response);
1014
1028
  return throwIfApiError(decrypted);
1015
1029
  }
1016
1030
  async updateAccount(accountUuid, data) {
1017
1031
  const endpoint = `/accounts/${accountUuid}`;
1018
1032
  const response = await this.send("PATCH", endpoint, data);
1019
1033
  const encrypted = await response.json();
1020
- const decrypted = await this.decrypt(encrypted);
1034
+ const decrypted = await this.decrypt(encrypted, response);
1021
1035
  return throwIfApiError(decrypted);
1022
1036
  }
1023
1037
  async deleteAccount(accountUuid) {
@@ -1031,7 +1045,7 @@ class AccountsGateway extends AlcoreBase {
1031
1045
  const endpoint = `/accounts${query}`;
1032
1046
  const response = await this.send("GET", endpoint, {});
1033
1047
  const encrypted = await response.json();
1034
- const decrypted = await this.decrypt(encrypted);
1048
+ const decrypted = await this.decrypt(encrypted, response);
1035
1049
  return throwIfApiError(decrypted);
1036
1050
  }
1037
1051
  async activateAccount(accountUuid) {
@@ -1050,7 +1064,7 @@ class AccountsGateway extends AlcoreBase {
1050
1064
  const endpoint = `/accounts/${accountUuid}/addresses`;
1051
1065
  const response = await this.send("POST", endpoint, data);
1052
1066
  const encrypted = await response.json();
1053
- const decrypted = await this.decrypt(encrypted);
1067
+ const decrypted = await this.decrypt(encrypted, response);
1054
1068
  return throwIfApiError(decrypted);
1055
1069
  }
1056
1070
  async getAddresses(accountUuid, params) {
@@ -1060,14 +1074,14 @@ class AccountsGateway extends AlcoreBase {
1060
1074
  const endpoint = `/accounts/${accountUuid}/addresses${query}`;
1061
1075
  const response = await this.send("GET", endpoint, {});
1062
1076
  const encrypted = await response.json();
1063
- const decrypted = await this.decrypt(encrypted);
1077
+ const decrypted = await this.decrypt(encrypted, response);
1064
1078
  return throwIfApiError(decrypted);
1065
1079
  }
1066
1080
  async updateAddress(accountUuid, addressUuid, data) {
1067
1081
  const endpoint = `/accounts/${accountUuid}/addresses/${addressUuid}`;
1068
1082
  const response = await this.send("PATCH", endpoint, data);
1069
1083
  const encrypted = await response.json();
1070
- const decrypted = await this.decrypt(encrypted);
1084
+ const decrypted = await this.decrypt(encrypted, response);
1071
1085
  return throwIfApiError(decrypted);
1072
1086
  }
1073
1087
  async deleteAddress(accountUuid, addressUuid) {
@@ -1078,7 +1092,7 @@ class AccountsGateway extends AlcoreBase {
1078
1092
  const endpoint = `/accounts/${accountUuid}/dossiers`;
1079
1093
  const response = await this.send("POST", endpoint, data);
1080
1094
  const encrypted = await response.json();
1081
- const decrypted = await this.decrypt(encrypted);
1095
+ const decrypted = await this.decrypt(encrypted, response);
1082
1096
  return throwIfApiError(decrypted);
1083
1097
  }
1084
1098
  async getDossiers(accountUuid, params) {
@@ -1088,28 +1102,28 @@ class AccountsGateway extends AlcoreBase {
1088
1102
  const endpoint = `/accounts/${accountUuid}/dossiers${query}`;
1089
1103
  const response = await this.send("GET", endpoint, {});
1090
1104
  const encrypted = await response.json();
1091
- const decrypted = await this.decrypt(encrypted);
1105
+ const decrypted = await this.decrypt(encrypted, response);
1092
1106
  return throwIfApiError(decrypted);
1093
1107
  }
1094
1108
  async getDossier(accountUuid, dossierUuid) {
1095
1109
  const endpoint = `/accounts/${accountUuid}/dossiers/${dossierUuid}`;
1096
1110
  const response = await this.send("GET", endpoint, {});
1097
1111
  const encrypted = await response.json();
1098
- const decrypted = await this.decrypt(encrypted);
1112
+ const decrypted = await this.decrypt(encrypted, response);
1099
1113
  return throwIfApiError(decrypted);
1100
1114
  }
1101
1115
  async updateDossier(accountUuid, dossierUuid, data) {
1102
1116
  const endpoint = `/accounts/${accountUuid}/dossiers/${dossierUuid}`;
1103
1117
  const response = await this.send("PUT", endpoint, data);
1104
1118
  const encrypted = await response.json();
1105
- const decrypted = await this.decrypt(encrypted);
1119
+ const decrypted = await this.decrypt(encrypted, response);
1106
1120
  return throwIfApiError(decrypted);
1107
1121
  }
1108
1122
  async replaceDossier(accountUuid, dossierUuid, data) {
1109
1123
  const endpoint = `/accounts/${accountUuid}/dossiers/${dossierUuid}`;
1110
1124
  const response = await this.send("PATCH", endpoint, data);
1111
1125
  const encrypted = await response.json();
1112
- const decrypted = await this.decrypt(encrypted);
1126
+ const decrypted = await this.decrypt(encrypted, response);
1113
1127
  return throwIfApiError(decrypted);
1114
1128
  }
1115
1129
  async deleteDossier(accountUuid, dossierUuid) {
@@ -1138,7 +1152,8 @@ class AuthGateway extends AlcoreBase {
1138
1152
  this.logger.debug("🌐 Endpoint: /v3/auth");
1139
1153
  this.logger.debug("🌐 Account UUID: " + data.account_uuid);
1140
1154
  const response = await this.send("POST", "/v3/auth", data);
1141
- const decryptedResponse = await this.decrypt(await response.json());
1155
+ const encrypted = await response.json();
1156
+ const decryptedResponse = await this.decrypt(encrypted, response);
1142
1157
  this.logger.debug("✅ Scoped token generated successfully");
1143
1158
  return decryptedResponse;
1144
1159
  }
@@ -1385,7 +1400,7 @@ class BankInfoGateway extends AlcoreBase {
1385
1400
  const endpoint = `/v3/bank-info?routing_number=${routingNumber}`;
1386
1401
  const response = await this.send("GET", endpoint, {});
1387
1402
  const encrypted = await response.json();
1388
- const decrypted = await this.decrypt(encrypted);
1403
+ const decrypted = await this.decrypt(encrypted, response);
1389
1404
  return throwIfApiError(decrypted);
1390
1405
  }
1391
1406
  }
@@ -1403,7 +1418,7 @@ class LegalTextsGateway extends AlcoreBase {
1403
1418
  this.logger.debug(`endpoint -> ${endpoint}`);
1404
1419
  const response = await this.send("GET", endpoint, {});
1405
1420
  const encrypted = await response.json();
1406
- const decrypted = await this.decrypt(encrypted);
1421
+ const decrypted = await this.decrypt(encrypted, response);
1407
1422
  return throwIfApiError(decrypted);
1408
1423
  }
1409
1424
  }