squarefi-bff-api-module 1.11.2 → 1.12.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
@@ -107,12 +107,13 @@ Access different API functionalities through the client:
107
107
 
108
108
  ## ⚙️ Environment Variables
109
109
 
110
- | Variable | Description | Required | Example |
111
- | ---------- | --------------------------------- | -------- | -------------------- |
112
- | API_URL | Base URL for the Squarefi BFF API | Yes | `https://api-v1.url` |
113
- | API_V2_URL | Base URL for the Squarefi BFF API | Yes | `https://api-v2.url` |
114
- | TENANT_ID | Your tenant identifier | Yes | `tenant_12345` |
115
- | LOGOUT_URL | Your frontend-app logout route | No | '/auth/logout' |
110
+ | Variable | Description | Required | Example |
111
+ | ------------------------ | --------------------------------------------- | -------- | -------------------- |
112
+ | API_URL | Base URL for the Squarefi BFF API | Yes | `https://api-v1.url` |
113
+ | API_V2_URL | Base URL for the Squarefi BFF API | Yes | `https://api-v2.url` |
114
+ | TENANT_ID | Your tenant identifier | Yes | `tenant_12345` |
115
+ | LOGOUT_URL | Your frontend-app logout route | No | '/auth/logout' |
116
+ | SERVER_PUBLIC_KEY_BASE64 | Server provides base64-encoded PEM format key | Yes | 'example' |
116
117
 
117
118
  ## 🚀 Features
118
119
 
@@ -1,5 +1,5 @@
1
1
  import { API } from './types';
2
- export declare const telegramSignInPath = "/auth/signin/telegram";
2
+ export declare const telegramSignInPath = "/auth/sign-in/telegram";
3
3
  export declare const telegramSignUpPath = "/auth/sign-up/telegram";
4
4
  export declare const refreshTokenPath = "/auth/refresh/refresh-token";
5
5
  export declare const auth: {
package/dist/api/auth.js CHANGED
@@ -14,8 +14,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.auth = exports.refreshTokenPath = exports.telegramSignUpPath = exports.telegramSignInPath = void 0;
15
15
  const apiClientFactory_1 = require("../utils/apiClientFactory");
16
16
  const converters_1 = require("../utils/converters");
17
- // export const telegramSignInPath = '/auth/sign-in/telegram'; V2 path
18
- exports.telegramSignInPath = '/auth/signin/telegram'; // V1 path
17
+ exports.telegramSignInPath = '/auth/sign-in/telegram'; // V2 path
18
+ // export const telegramSignInPath = '/auth/signin/telegram'; // V1 path
19
19
  exports.telegramSignUpPath = '/auth/sign-up/telegram';
20
20
  exports.refreshTokenPath = '/auth/refresh/refresh-token';
21
21
  exports.auth = {
@@ -39,7 +39,7 @@ exports.auth = {
39
39
  });
40
40
  },
41
41
  },
42
- telegram: (data) => apiClientFactory_1.apiClientV1.postRequest(exports.telegramSignInPath, { data }),
42
+ telegram: (data) => apiClientFactory_1.apiClientV2.postRequest(exports.telegramSignInPath, { data }),
43
43
  password: (email, password // check on backend V2
44
44
  ) => apiClientFactory_1.apiClientV2.postRequest('/auth/sign-in/password/email', {
45
45
  data: { email, password },
@@ -13,6 +13,11 @@ export declare const issuing: {
13
13
  getById: (card_id: string) => Promise<API.Cards.IssuingCardDetailItem>;
14
14
  sensitiveData: {
15
15
  get: (card_id: string) => Promise<API.Cards.SensitiveData>;
16
+ encrypted: {
17
+ secretKey: {
18
+ get: (card_id: string) => Promise<any>;
19
+ };
20
+ };
16
21
  otp: {
17
22
  get: (card_id: string) => Promise<API.Cards.OTP>;
18
23
  };
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
36
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
37
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -13,6 +46,7 @@ exports.issuing = void 0;
13
46
  const apiClientFactory_1 = require("../utils/apiClientFactory");
14
47
  const constants_1 = require("../constants");
15
48
  const fiat_accounts_1 = require("./fiat_accounts");
49
+ const common_1 = require("../utils/common");
16
50
  exports.issuing = {
17
51
  cards: {
18
52
  create: {
@@ -34,6 +68,36 @@ exports.issuing = {
34
68
  }),
35
69
  sensitiveData: {
36
70
  get: (card_id) => apiClientFactory_1.apiClientV1.getRequest(`/issuing/cards/${card_id}/sensitive`),
71
+ encrypted: {
72
+ secretKey: {
73
+ get: (card_id) => __awaiter(void 0, void 0, void 0, function* () {
74
+ const serverPublicKey = process.env.SERVER_PUBLIC_KEY_BASE64;
75
+ if (!serverPublicKey) {
76
+ throw new Error('SERVER_PUBLIC_KEY_BASE64 is not set');
77
+ }
78
+ const secretKey = (0, common_1.generate256bitSecretKey)();
79
+ const secretKeyBase64 = (0, common_1.arrayBufferToBase64)(secretKey);
80
+ const JSEncrypt = (yield Promise.resolve().then(() => __importStar(require('jsencrypt')))).default;
81
+ const encrypt = new JSEncrypt();
82
+ const serverPublicKeyPEM = (0, common_1.decodePEMFromBase64)(serverPublicKey);
83
+ encrypt.setPublicKey(serverPublicKeyPEM);
84
+ const payload = {
85
+ key: secretKeyBase64,
86
+ timestamp: Date.now(),
87
+ };
88
+ const encrypted_key = encrypt.encrypt(JSON.stringify(payload));
89
+ const response = yield apiClientFactory_1.apiClientV1.postRequest(`/issuing/cards/${card_id}/sensitive/secretkey`, {
90
+ data: {
91
+ encrypted_key,
92
+ },
93
+ });
94
+ if (response.success && response.encrypted && response.data && response.iv) {
95
+ const decryptedData = yield (0, common_1.decryptSensitiveData)(response.data, response.iv, secretKey);
96
+ return decryptedData;
97
+ }
98
+ }),
99
+ },
100
+ },
37
101
  otp: {
38
102
  // have to update
39
103
  get: (card_id) => apiClientFactory_1.apiClientV1.getRequest(`/vcards/cards/${card_id}/sensitive/otp`),
@@ -287,6 +287,12 @@ export declare namespace API {
287
287
  expiry_year: number;
288
288
  security_code?: string;
289
289
  }
290
+ interface SensitiveDataEncrypted {
291
+ data?: string;
292
+ success?: boolean;
293
+ encrypted?: boolean;
294
+ iv?: string;
295
+ }
290
296
  interface OTP {
291
297
  created_at: number;
292
298
  internal_card_id: string;
@@ -0,0 +1,5 @@
1
+ export declare const generate256bitSecretKey: () => Uint8Array<ArrayBuffer>;
2
+ export declare const arrayBufferToBase64: (buffer: Uint8Array<ArrayBuffer>) => string;
3
+ export declare const decodePEMFromBase64: (base64EncodedPEM: string) => string;
4
+ export declare const base64ToArrayBuffer: (base64: string) => ArrayBuffer;
5
+ export declare const decryptSensitiveData: (encryptedData: string, iv: string, secretKey: BufferSource) => Promise<any>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.decryptSensitiveData = exports.base64ToArrayBuffer = exports.decodePEMFromBase64 = exports.arrayBufferToBase64 = exports.generate256bitSecretKey = void 0;
13
+ const generate256bitSecretKey = () => {
14
+ const array = new Uint8Array(32);
15
+ window.crypto.getRandomValues(array);
16
+ return array;
17
+ };
18
+ exports.generate256bitSecretKey = generate256bitSecretKey;
19
+ const arrayBufferToBase64 = (buffer) => {
20
+ return btoa(String.fromCharCode(...new Uint8Array(buffer)));
21
+ };
22
+ exports.arrayBufferToBase64 = arrayBufferToBase64;
23
+ const decodePEMFromBase64 = (base64EncodedPEM) => {
24
+ return atob(base64EncodedPEM);
25
+ };
26
+ exports.decodePEMFromBase64 = decodePEMFromBase64;
27
+ const base64ToArrayBuffer = (base64) => {
28
+ const binaryString = atob(base64);
29
+ const bytes = new Uint8Array(binaryString.length);
30
+ for (let i = 0; i < binaryString.length; i++) {
31
+ bytes[i] = binaryString.charCodeAt(i);
32
+ }
33
+ return bytes.buffer;
34
+ };
35
+ exports.base64ToArrayBuffer = base64ToArrayBuffer;
36
+ const decryptSensitiveData = (encryptedData, iv, secretKey) => __awaiter(void 0, void 0, void 0, function* () {
37
+ const key = yield window.crypto.subtle.importKey('raw', secretKey, { name: 'AES-CBC' }, false, ['decrypt']);
38
+ const encryptedBuffer = (0, exports.base64ToArrayBuffer)(encryptedData);
39
+ const ivBuffer = (0, exports.base64ToArrayBuffer)(iv);
40
+ const decryptedBuffer = yield window.crypto.subtle.decrypt({
41
+ name: 'AES-CBC',
42
+ iv: ivBuffer,
43
+ }, key, encryptedBuffer);
44
+ const decoder = new TextDecoder();
45
+ const jsonText = decoder.decode(decryptedBuffer);
46
+ return JSON.parse(jsonText);
47
+ });
48
+ exports.decryptSensitiveData = decryptSensitiveData;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squarefi-bff-api-module",
3
- "version": "1.11.2",
3
+ "version": "1.12.0",
4
4
  "description": "Squarefi BFF API client module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,7 +19,8 @@
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
21
  "@telegram-apps/sdk-react": "^3.1.2",
22
- "axios": "^1.6.7"
22
+ "axios": "^1.6.7",
23
+ "jsencrypt": "^3.3.2"
23
24
  },
24
25
  "devDependencies": {
25
26
  "@types/jest": "^29.x.x",
package/src/api/auth.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import { API } from './types';
2
2
 
3
- import { apiClientV1, apiClientV2 } from '../utils/apiClientFactory';
3
+ import { apiClientV2 } from '../utils/apiClientFactory';
4
4
  import { convertPhoneToSupabaseFormat } from '../utils/converters';
5
5
 
6
- // export const telegramSignInPath = '/auth/sign-in/telegram'; V2 path
7
- export const telegramSignInPath = '/auth/signin/telegram'; // V1 path
6
+ export const telegramSignInPath = '/auth/sign-in/telegram'; // V2 path
7
+ // export const telegramSignInPath = '/auth/signin/telegram'; // V1 path
8
8
 
9
9
  export const telegramSignUpPath = '/auth/sign-up/telegram';
10
10
  export const refreshTokenPath = '/auth/refresh/refresh-token';
@@ -32,7 +32,7 @@ export const auth = {
32
32
  }),
33
33
  },
34
34
  telegram: (data: API.Auth.Telegram.Signin) =>
35
- apiClientV1.postRequest<API.Auth.Tokens>(telegramSignInPath, { data }),
35
+ apiClientV2.postRequest<API.Auth.Tokens>(telegramSignInPath, { data }),
36
36
  password: (
37
37
  email: string,
38
38
  password: string // check on backend V2
@@ -4,6 +4,12 @@ import { apiClientV1 } from '../utils/apiClientFactory';
4
4
 
5
5
  import { defaultPaginationParams, SubAccountType } from '../constants';
6
6
  import { fiat_accounts } from './fiat_accounts';
7
+ import {
8
+ arrayBufferToBase64,
9
+ decodePEMFromBase64,
10
+ decryptSensitiveData,
11
+ generate256bitSecretKey,
12
+ } from '../utils/common';
7
13
 
8
14
  export const issuing = {
9
15
  cards: {
@@ -31,6 +37,43 @@ export const issuing = {
31
37
  },
32
38
  sensitiveData: {
33
39
  get: (card_id: string) => apiClientV1.getRequest<API.Cards.SensitiveData>(`/issuing/cards/${card_id}/sensitive`),
40
+ encrypted: {
41
+ secretKey: {
42
+ get: async (card_id: string) => {
43
+ const serverPublicKey = process.env.SERVER_PUBLIC_KEY_BASE64;
44
+ if (!serverPublicKey) {
45
+ throw new Error('SERVER_PUBLIC_KEY_BASE64 is not set');
46
+ }
47
+ const secretKey = generate256bitSecretKey();
48
+ const secretKeyBase64 = arrayBufferToBase64(secretKey);
49
+ const JSEncrypt = (await import('jsencrypt')).default;
50
+ const encrypt = new JSEncrypt();
51
+ const serverPublicKeyPEM = decodePEMFromBase64(serverPublicKey);
52
+ encrypt.setPublicKey(serverPublicKeyPEM);
53
+
54
+ const payload = {
55
+ key: secretKeyBase64,
56
+ timestamp: Date.now(),
57
+ };
58
+
59
+ const encrypted_key = encrypt.encrypt(JSON.stringify(payload));
60
+
61
+ const response = await apiClientV1.postRequest<API.Cards.SensitiveDataEncrypted>(
62
+ `/issuing/cards/${card_id}/sensitive/secretkey`,
63
+ {
64
+ data: {
65
+ encrypted_key,
66
+ },
67
+ }
68
+ );
69
+ if (response.success && response.encrypted && response.data && response.iv) {
70
+ const decryptedData = await decryptSensitiveData(response.data, response.iv, secretKey);
71
+
72
+ return decryptedData;
73
+ }
74
+ },
75
+ },
76
+ },
34
77
  otp: {
35
78
  // have to update
36
79
  get: (card_id: string) => apiClientV1.getRequest<API.Cards.OTP>(`/vcards/cards/${card_id}/sensitive/otp`),
package/src/api/types.ts CHANGED
@@ -335,6 +335,13 @@ export namespace API {
335
335
  security_code?: string;
336
336
  }
337
337
 
338
+ export interface SensitiveDataEncrypted {
339
+ data?: string;
340
+ success?: boolean;
341
+ encrypted?: boolean;
342
+ iv?: string;
343
+ }
344
+
338
345
  export interface OTP {
339
346
  created_at: number;
340
347
  internal_card_id: string;
@@ -0,0 +1,42 @@
1
+ export const generate256bitSecretKey = () => {
2
+ const array = new Uint8Array(32);
3
+ window.crypto.getRandomValues(array);
4
+ return array;
5
+ };
6
+
7
+ export const arrayBufferToBase64 = (buffer: Uint8Array<ArrayBuffer>) => {
8
+ return btoa(String.fromCharCode(...new Uint8Array(buffer)));
9
+ };
10
+
11
+ export const decodePEMFromBase64 = (base64EncodedPEM: string) => {
12
+ return atob(base64EncodedPEM);
13
+ };
14
+
15
+ export const base64ToArrayBuffer = (base64: string) => {
16
+ const binaryString = atob(base64);
17
+ const bytes = new Uint8Array(binaryString.length);
18
+ for (let i = 0; i < binaryString.length; i++) {
19
+ bytes[i] = binaryString.charCodeAt(i);
20
+ }
21
+ return bytes.buffer;
22
+ };
23
+
24
+ export const decryptSensitiveData = async (encryptedData: string, iv: string, secretKey: BufferSource) => {
25
+ const key = await window.crypto.subtle.importKey('raw', secretKey, { name: 'AES-CBC' }, false, ['decrypt']);
26
+
27
+ const encryptedBuffer = base64ToArrayBuffer(encryptedData);
28
+ const ivBuffer = base64ToArrayBuffer(iv);
29
+
30
+ const decryptedBuffer = await window.crypto.subtle.decrypt(
31
+ {
32
+ name: 'AES-CBC',
33
+ iv: ivBuffer,
34
+ },
35
+ key,
36
+ encryptedBuffer
37
+ );
38
+
39
+ const decoder = new TextDecoder();
40
+ const jsonText = decoder.decode(decryptedBuffer);
41
+ return JSON.parse(jsonText);
42
+ };