squarefi-bff-api-module 1.21.9 → 1.22.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.
@@ -1107,7 +1107,6 @@ export interface components {
1107
1107
  kyc_status: "APPROVED" | "DECLINED" | "PENDING" | "HOLD" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | null;
1108
1108
  referral_name: string | null;
1109
1109
  tenant_id: string;
1110
- turnover_limit: number;
1111
1110
  user_id: string;
1112
1111
  default_currency: string;
1113
1112
  user_groups_id: string | null;
@@ -0,0 +1,20 @@
1
+ import { API } from '../api/types/types';
2
+ export type OrderCalcHandlerProps = Omit<API.Orders.V2.Calc.Request, 'order_type'>;
3
+ export type UseOrderCalcProps = {
4
+ from_currency_id: string | null | undefined;
5
+ to_currency_id: string | null | undefined;
6
+ calcHandler: (props: OrderCalcHandlerProps) => Promise<API.Orders.V2.Calc.Response>;
7
+ disableCalculation?: boolean;
8
+ to_address?: string;
9
+ };
10
+ export type UseOrderCalcData = {
11
+ calcData: API.Orders.V2.Calc.Response | null;
12
+ sellingAmount: number;
13
+ setSellingAmount: (value: number) => void;
14
+ buyingAmount: number;
15
+ setBuyingAmount: (value: number) => void;
16
+ isSellingValuePending: boolean;
17
+ isBuyingValuePending: boolean;
18
+ };
19
+ export type UseOrderCalc = (props: UseOrderCalcProps) => UseOrderCalcData;
20
+ export declare const useOrderCalc: UseOrderCalc;
@@ -0,0 +1,127 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.useOrderCalc = void 0;
16
+ const lodash_debounce_1 = __importDefault(require("lodash.debounce"));
17
+ const react_1 = require("react");
18
+ const useOrderCalc = (props) => {
19
+ var _a, _b, _c;
20
+ const { from_currency_id, to_currency_id, calcHandler, disableCalculation, to_address } = props;
21
+ const [sellingAmount, setSellingAmount] = (0, react_1.useState)(0);
22
+ const [buyingAmount, setBuyingAmount] = (0, react_1.useState)(0);
23
+ const [calcData, setCalcData] = (0, react_1.useState)(null);
24
+ const [isSellingValuePending, setIsSellingValuePending] = (0, react_1.useState)(false);
25
+ const [isBuyingValuePending, setIsBuyingValuePending] = (0, react_1.useState)(false);
26
+ const abortControllerRef = (0, react_1.useRef)(null);
27
+ const resetOrderCalc = () => {
28
+ setCalcData(null);
29
+ setIsSellingValuePending(false);
30
+ setIsBuyingValuePending(false);
31
+ setSellingAmount(0);
32
+ setBuyingAmount(0);
33
+ };
34
+ const abortCurrentCalculation = () => {
35
+ if (abortControllerRef.current) {
36
+ abortControllerRef.current.abort();
37
+ }
38
+ };
39
+ const updateCalculations = (_a) => __awaiter(void 0, [_a], void 0, function* ({ is_reverse = false }) {
40
+ if (disableCalculation) {
41
+ return;
42
+ }
43
+ abortControllerRef.current = new AbortController();
44
+ if (!from_currency_id || !to_currency_id) {
45
+ throw new Error('From currency or to currency is not defined');
46
+ }
47
+ if (sellingAmount === 0 && buyingAmount === 0 && !calcData) {
48
+ resetOrderCalc();
49
+ return;
50
+ }
51
+ const calcParams = {
52
+ from_currency_id,
53
+ to_currency_id,
54
+ amount: is_reverse ? buyingAmount : sellingAmount,
55
+ is_reverse,
56
+ to_address,
57
+ signal: abortControllerRef.current.signal,
58
+ };
59
+ if (!calcParams.amount) {
60
+ resetOrderCalc();
61
+ return;
62
+ }
63
+ try {
64
+ is_reverse ? setIsSellingValuePending(true) : setIsBuyingValuePending(true);
65
+ const data = yield calcHandler(calcParams);
66
+ setCalcData(data);
67
+ setSellingAmount(data.from_amount);
68
+ setBuyingAmount(data.result_amount);
69
+ abortControllerRef.current = null;
70
+ is_reverse ? setIsSellingValuePending(false) : setIsBuyingValuePending(false);
71
+ }
72
+ catch (error) {
73
+ if (error.code === 'ERR_CANCELED') {
74
+ return;
75
+ }
76
+ is_reverse ? setIsSellingValuePending(false) : setIsBuyingValuePending(false);
77
+ if (error.status === 404) {
78
+ // eslint-disable-next-line no-console
79
+ console.error('Rate not found');
80
+ resetOrderCalc();
81
+ }
82
+ throw error;
83
+ }
84
+ });
85
+ const onSellingValueUpdate = (0, lodash_debounce_1.default)((value) => {
86
+ if (value !== (calcData === null || calcData === void 0 ? void 0 : calcData.from_amount) || isBuyingValuePending) {
87
+ updateCalculations({ is_reverse: false });
88
+ }
89
+ }, ((_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.signal) ? undefined : 1000);
90
+ const onBuyingValueUpdate = (0, lodash_debounce_1.default)((value) => {
91
+ if (value !== (calcData === null || calcData === void 0 ? void 0 : calcData.result_amount) || isSellingValuePending) {
92
+ updateCalculations({ is_reverse: true });
93
+ }
94
+ }, ((_b = abortControllerRef.current) === null || _b === void 0 ? void 0 : _b.signal) ? undefined : 1000);
95
+ const onToAddressUpdate = (0, lodash_debounce_1.default)(() => {
96
+ updateCalculations({ is_reverse: false });
97
+ }, ((_c = abortControllerRef.current) === null || _c === void 0 ? void 0 : _c.signal) ? undefined : 1000);
98
+ (0, react_1.useEffect)(() => {
99
+ abortCurrentCalculation();
100
+ updateCalculations({ is_reverse: false });
101
+ }, [from_currency_id, to_currency_id]);
102
+ (0, react_1.useEffect)(() => {
103
+ abortCurrentCalculation();
104
+ onSellingValueUpdate(sellingAmount);
105
+ return onSellingValueUpdate.cancel;
106
+ }, [sellingAmount]);
107
+ (0, react_1.useEffect)(() => {
108
+ abortCurrentCalculation();
109
+ onBuyingValueUpdate(buyingAmount);
110
+ return onBuyingValueUpdate.cancel;
111
+ }, [buyingAmount]);
112
+ (0, react_1.useEffect)(() => {
113
+ abortCurrentCalculation();
114
+ onToAddressUpdate();
115
+ return onToAddressUpdate.cancel;
116
+ }, [to_address]);
117
+ return {
118
+ sellingAmount,
119
+ setSellingAmount,
120
+ buyingAmount,
121
+ setBuyingAmount,
122
+ calcData,
123
+ isSellingValuePending,
124
+ isBuyingValuePending,
125
+ };
126
+ };
127
+ exports.useOrderCalc = useOrderCalc;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "squarefi-bff-api-module",
3
- "version": "1.21.9",
3
+ "version": "1.22.0",
4
4
  "description": "Squarefi BFF API client module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -25,12 +25,15 @@
25
25
  "dependencies": {
26
26
  "@telegram-apps/sdk-react": "^3.1.2",
27
27
  "axios": "^1.6.7",
28
+ "lodash.debounce": "^4.0.8",
28
29
  "node-rsa": "^1.1.1"
29
30
  },
30
31
  "devDependencies": {
31
32
  "@types/jest": "^29.x.x",
33
+ "@types/lodash.debounce": "^4.0.9",
32
34
  "@types/node": "^20.17.47",
33
35
  "@types/node-rsa": "^1.1.4",
36
+ "@types/react": "^19.1.8",
34
37
  "dotenv": "^16.5.0",
35
38
  "husky": "^9.1.7",
36
39
  "jest": "^29.x.x",
@@ -1108,7 +1108,6 @@ export interface components {
1108
1108
  kyc_status: "APPROVED" | "DECLINED" | "PENDING" | "HOLD" | "DOUBLE" | "SOFT_REJECT" | "REJECT" | "UNVERIFIED" | "WAITING_ON_UBOS" | null;
1109
1109
  referral_name: string | null;
1110
1110
  tenant_id: string;
1111
- turnover_limit: number;
1112
1111
  user_id: string;
1113
1112
  default_currency: string;
1114
1113
  user_groups_id: string | null;
@@ -0,0 +1,166 @@
1
+ import debounce from 'lodash.debounce';
2
+ import { useEffect, useRef, useState } from 'react';
3
+ import { API } from '../api/types/types';
4
+
5
+ export type OrderCalcHandlerProps = Omit<API.Orders.V2.Calc.Request, 'order_type'>;
6
+
7
+ export type UseOrderCalcProps = {
8
+ from_currency_id: string | null | undefined;
9
+ to_currency_id: string | null | undefined;
10
+ calcHandler: (props: OrderCalcHandlerProps) => Promise<API.Orders.V2.Calc.Response>;
11
+ disableCalculation?: boolean;
12
+ to_address?: string;
13
+ };
14
+
15
+ export type UseOrderCalcData = {
16
+ calcData: API.Orders.V2.Calc.Response | null;
17
+ sellingAmount: number;
18
+ setSellingAmount: (value: number) => void;
19
+ buyingAmount: number;
20
+ setBuyingAmount: (value: number) => void;
21
+ isSellingValuePending: boolean;
22
+ isBuyingValuePending: boolean;
23
+ };
24
+
25
+ export type UseOrderCalc = (props: UseOrderCalcProps) => UseOrderCalcData;
26
+
27
+ export const useOrderCalc: UseOrderCalc = (props: UseOrderCalcProps) => {
28
+ const { from_currency_id, to_currency_id, calcHandler, disableCalculation, to_address } = props;
29
+
30
+ const [sellingAmount, setSellingAmount] = useState(0);
31
+ const [buyingAmount, setBuyingAmount] = useState(0);
32
+ const [calcData, setCalcData] = useState<API.Orders.V2.Calc.Response | null>(null);
33
+ const [isSellingValuePending, setIsSellingValuePending] = useState(false);
34
+ const [isBuyingValuePending, setIsBuyingValuePending] = useState(false);
35
+
36
+ const abortControllerRef = useRef<AbortController | null>(null);
37
+
38
+ const resetOrderCalc = () => {
39
+ setCalcData(null);
40
+ setIsSellingValuePending(false);
41
+ setIsBuyingValuePending(false);
42
+ setSellingAmount(0);
43
+ setBuyingAmount(0);
44
+ };
45
+
46
+ const abortCurrentCalculation = () => {
47
+ if (abortControllerRef.current) {
48
+ abortControllerRef.current.abort();
49
+ }
50
+ };
51
+
52
+ const updateCalculations = async ({ is_reverse = false }) => {
53
+ if (disableCalculation) {
54
+ return;
55
+ }
56
+
57
+ abortControllerRef.current = new AbortController();
58
+
59
+ if (!from_currency_id || !to_currency_id) {
60
+ throw new Error('From currency or to currency is not defined');
61
+ }
62
+
63
+ if (sellingAmount === 0 && buyingAmount === 0 && !calcData) {
64
+ resetOrderCalc();
65
+ return;
66
+ }
67
+
68
+ const calcParams: OrderCalcHandlerProps = {
69
+ from_currency_id,
70
+ to_currency_id,
71
+ amount: is_reverse ? buyingAmount : sellingAmount,
72
+ is_reverse,
73
+ to_address,
74
+ signal: abortControllerRef.current.signal,
75
+ };
76
+
77
+ if (!calcParams.amount) {
78
+ resetOrderCalc();
79
+ return;
80
+ }
81
+
82
+ try {
83
+ is_reverse ? setIsSellingValuePending(true) : setIsBuyingValuePending(true);
84
+ const data = await calcHandler(calcParams);
85
+ setCalcData(data);
86
+
87
+ setSellingAmount(data.from_amount);
88
+
89
+ setBuyingAmount(data.result_amount);
90
+ abortControllerRef.current = null;
91
+ is_reverse ? setIsSellingValuePending(false) : setIsBuyingValuePending(false);
92
+ } catch (error: any) {
93
+ if (error.code === 'ERR_CANCELED') {
94
+ return;
95
+ }
96
+
97
+ is_reverse ? setIsSellingValuePending(false) : setIsBuyingValuePending(false);
98
+
99
+ if (error.status === 404) {
100
+ // eslint-disable-next-line no-console
101
+ console.error('Rate not found');
102
+ resetOrderCalc();
103
+ }
104
+
105
+ throw error;
106
+ }
107
+ };
108
+
109
+ const onSellingValueUpdate = debounce(
110
+ (value: number) => {
111
+ if (value !== calcData?.from_amount || isBuyingValuePending) {
112
+ updateCalculations({ is_reverse: false });
113
+ }
114
+ },
115
+ abortControllerRef.current?.signal ? undefined : 1000
116
+ );
117
+
118
+ const onBuyingValueUpdate = debounce(
119
+ (value: number) => {
120
+ if (value !== calcData?.result_amount || isSellingValuePending) {
121
+ updateCalculations({ is_reverse: true });
122
+ }
123
+ },
124
+ abortControllerRef.current?.signal ? undefined : 1000
125
+ );
126
+
127
+ const onToAddressUpdate = debounce(
128
+ () => {
129
+ updateCalculations({ is_reverse: false });
130
+ },
131
+ abortControllerRef.current?.signal ? undefined : 1000
132
+ );
133
+
134
+ useEffect(() => {
135
+ abortCurrentCalculation();
136
+ updateCalculations({ is_reverse: false });
137
+ }, [from_currency_id, to_currency_id]);
138
+
139
+ useEffect(() => {
140
+ abortCurrentCalculation();
141
+ onSellingValueUpdate(sellingAmount);
142
+ return onSellingValueUpdate.cancel;
143
+ }, [sellingAmount]);
144
+
145
+ useEffect(() => {
146
+ abortCurrentCalculation();
147
+ onBuyingValueUpdate(buyingAmount);
148
+ return onBuyingValueUpdate.cancel;
149
+ }, [buyingAmount]);
150
+
151
+ useEffect(() => {
152
+ abortCurrentCalculation();
153
+ onToAddressUpdate();
154
+ return onToAddressUpdate.cancel;
155
+ }, [to_address]);
156
+
157
+ return {
158
+ sellingAmount,
159
+ setSellingAmount,
160
+ buyingAmount,
161
+ setBuyingAmount,
162
+ calcData,
163
+ isSellingValuePending,
164
+ isBuyingValuePending,
165
+ };
166
+ };