@subwallet/extension-base 1.3.29-0 → 1.3.30-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/background/KoniTypes.d.ts +4 -4
- package/background/errors/SwapError.js +1 -1
- package/cjs/background/errors/SwapError.js +1 -1
- package/cjs/constants/blocked-actions.js +2 -2
- package/cjs/constants/remind-notification-time.js +3 -3
- package/cjs/core/logic-validation/swap.js +63 -4
- package/cjs/core/utils.js +9 -3
- package/cjs/koni/background/handlers/Extension.js +5 -82
- package/cjs/packageInfo.js +1 -1
- package/cjs/services/balance-service/transfer/xcm/availBridge.js +6 -6
- package/cjs/services/chain-service/constants.js +1 -1
- package/cjs/services/earning-service/handlers/base.js +6 -3
- package/cjs/services/earning-service/handlers/native-staking/base.js +4 -1
- package/cjs/services/earning-service/handlers/native-staking/dtao.js +68 -50
- package/cjs/services/earning-service/handlers/native-staking/tao.js +12 -2
- package/cjs/services/earning-service/service.js +2 -1
- package/cjs/services/fee-service/utils/index.js +16 -4
- package/cjs/services/inapp-notification-service/index.js +19 -13
- package/cjs/services/swap-service/handler/asset-hub/handler.js +61 -314
- package/cjs/services/swap-service/handler/base-handler.js +393 -231
- package/cjs/services/swap-service/handler/chainflip-handler.js +18 -40
- package/cjs/services/swap-service/handler/hydradx-handler.js +77 -269
- package/cjs/services/swap-service/handler/simpleswap-handler.js +27 -48
- package/cjs/services/swap-service/handler/uniswap-handler.js +33 -54
- package/cjs/services/swap-service/index.js +154 -143
- package/cjs/services/swap-service/utils.js +107 -17
- package/cjs/services/transaction-service/index.js +1 -1
- package/cjs/types/swap/index.js +13 -1
- package/cjs/utils/swap.js +5 -1
- package/constants/blocked-actions.d.ts +1 -1
- package/constants/blocked-actions.js +1 -1
- package/constants/remind-notification-time.d.ts +1 -1
- package/constants/remind-notification-time.js +1 -1
- package/core/logic-validation/swap.d.ts +15 -0
- package/core/logic-validation/swap.js +60 -4
- package/core/utils.js +9 -3
- package/koni/background/handlers/Extension.d.ts +0 -1
- package/koni/background/handlers/Extension.js +6 -83
- package/package.json +6 -12
- package/packageInfo.js +1 -1
- package/services/balance-service/transfer/xcm/availBridge.js +6 -6
- package/services/base/types.d.ts +0 -4
- package/services/chain-service/constants.js +1 -1
- package/services/earning-service/handlers/base.d.ts +4 -3
- package/services/earning-service/handlers/base.js +6 -4
- package/services/earning-service/handlers/native-staking/base.js +4 -1
- package/services/earning-service/handlers/native-staking/dtao.d.ts +9 -6
- package/services/earning-service/handlers/native-staking/dtao.js +69 -48
- package/services/earning-service/handlers/native-staking/tao.js +12 -2
- package/services/earning-service/service.d.ts +2 -1
- package/services/earning-service/service.js +2 -1
- package/services/fee-service/utils/index.d.ts +1 -0
- package/services/fee-service/utils/index.js +14 -4
- package/services/inapp-notification-service/index.js +13 -7
- package/services/swap-service/handler/asset-hub/handler.d.ts +2 -9
- package/services/swap-service/handler/asset-hub/handler.js +64 -317
- package/services/swap-service/handler/base-handler.d.ts +6 -9
- package/services/swap-service/handler/base-handler.js +391 -229
- package/services/swap-service/handler/chainflip-handler.d.ts +2 -4
- package/services/swap-service/handler/chainflip-handler.js +15 -37
- package/services/swap-service/handler/hydradx-handler.d.ts +3 -10
- package/services/swap-service/handler/hydradx-handler.js +78 -270
- package/services/swap-service/handler/simpleswap-handler.d.ts +2 -4
- package/services/swap-service/handler/simpleswap-handler.js +24 -45
- package/services/swap-service/handler/uniswap-handler.d.ts +4 -6
- package/services/swap-service/handler/uniswap-handler.js +25 -46
- package/services/swap-service/index.d.ts +8 -14
- package/services/swap-service/index.js +141 -129
- package/services/swap-service/utils.d.ts +11 -3
- package/services/swap-service/utils.js +96 -15
- package/services/transaction-service/index.js +2 -2
- package/types/service-base.d.ts +2 -3
- package/types/swap/index.d.ts +25 -9
- package/types/swap/index.js +10 -0
- package/types/transaction/process.d.ts +19 -0
- package/types/yield/actions/join/submit.d.ts +4 -1
- package/types/yield/actions/others.d.ts +2 -0
- package/utils/swap.d.ts +3 -0
- package/utils/swap.js +3 -0
- package/cjs/services/swap-service/interface.js +0 -14
- package/services/swap-service/interface.d.ts +0 -9
- package/services/swap-service/interface.js +0 -8
|
@@ -5,8 +5,7 @@ import { SwapError } from '@subwallet/extension-base/background/errors/SwapError
|
|
|
5
5
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
6
6
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
7
7
|
import { _getAssetDecimals, _getContractAddressOfToken, _isChainSubstrateCompatible, _isNativeToken } from '@subwallet/extension-base/services/chain-service/utils';
|
|
8
|
-
import { DynamicSwapType } from '@subwallet/extension-base/
|
|
9
|
-
import { BasicTxErrorType, CommonStepType, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
8
|
+
import { BasicTxErrorType, CommonStepType, DynamicSwapType, SwapErrorType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
10
9
|
import { _reformatAddressWithChain, formatNumber } from '@subwallet/extension-base/utils';
|
|
11
10
|
import { getId } from '@subwallet/extension-base/utils/getId';
|
|
12
11
|
import BigN, { BigNumber } from 'bignumber.js';
|
|
@@ -61,33 +60,6 @@ export class SimpleSwapHandler {
|
|
|
61
60
|
});
|
|
62
61
|
this.providerSlug = SwapProviderId.SIMPLE_SWAP;
|
|
63
62
|
}
|
|
64
|
-
async validateSwapProcess(params) {
|
|
65
|
-
const amount = params.selectedQuote.fromAmount;
|
|
66
|
-
const bnAmount = BigInt(amount);
|
|
67
|
-
if (bnAmount <= BigInt(0)) {
|
|
68
|
-
return Promise.resolve([new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')]);
|
|
69
|
-
}
|
|
70
|
-
let isXcmOk = false;
|
|
71
|
-
for (const [index, step] of params.process.steps.entries()) {
|
|
72
|
-
const getErrors = async () => {
|
|
73
|
-
switch (step.type) {
|
|
74
|
-
case CommonStepType.DEFAULT:
|
|
75
|
-
return Promise.resolve([]);
|
|
76
|
-
case CommonStepType.TOKEN_APPROVAL:
|
|
77
|
-
return Promise.reject(new TransactionError(BasicTxErrorType.UNSUPPORTED));
|
|
78
|
-
default:
|
|
79
|
-
return this.swapBaseHandler.validateSwapStep(params, isXcmOk, index);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
const errors = await getErrors();
|
|
83
|
-
if (errors.length) {
|
|
84
|
-
return errors;
|
|
85
|
-
} else if (step.type === CommonStepType.XCM) {
|
|
86
|
-
isXcmOk = true;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return [];
|
|
90
|
-
}
|
|
91
63
|
get chainService() {
|
|
92
64
|
return this.swapBaseHandler.chainService;
|
|
93
65
|
}
|
|
@@ -103,26 +75,32 @@ export class SimpleSwapHandler {
|
|
|
103
75
|
get slug() {
|
|
104
76
|
return this.swapBaseHandler.slug;
|
|
105
77
|
}
|
|
106
|
-
generateOptimalProcess(params) {
|
|
107
|
-
return this.swapBaseHandler.generateOptimalProcess(params, [this.getSubmitStep.bind(this)]);
|
|
108
|
-
}
|
|
109
78
|
generateOptimalProcessV2(params) {
|
|
110
79
|
return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getSubmitStep.bind(this)]);
|
|
111
80
|
}
|
|
112
|
-
async getSubmitStep(params) {
|
|
113
|
-
if (params.selectedQuote) {
|
|
114
|
-
|
|
115
|
-
name: 'Swap',
|
|
116
|
-
type: SwapStepType.SWAP,
|
|
117
|
-
metadata: {
|
|
118
|
-
sendingValue: params.request.fromAmount.toString(),
|
|
119
|
-
originTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.from),
|
|
120
|
-
destinationTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.to)
|
|
121
|
-
}
|
|
122
|
-
};
|
|
123
|
-
return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
|
|
81
|
+
async getSubmitStep(params, stepIndex) {
|
|
82
|
+
if (!params.selectedQuote) {
|
|
83
|
+
return Promise.resolve(undefined);
|
|
124
84
|
}
|
|
125
|
-
|
|
85
|
+
const originTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
|
|
86
|
+
const destinationTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
|
|
87
|
+
const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
|
|
88
|
+
const destinationChain = this.chainService.getChainInfoByKey(destinationTokenInfo.originChain);
|
|
89
|
+
const submitStep = {
|
|
90
|
+
name: 'Swap',
|
|
91
|
+
type: SwapStepType.SWAP,
|
|
92
|
+
// @ts-ignore
|
|
93
|
+
metadata: {
|
|
94
|
+
sendingValue: params.request.fromAmount.toString(),
|
|
95
|
+
expectedReceive: params.selectedQuote.toAmount,
|
|
96
|
+
originTokenInfo,
|
|
97
|
+
destinationTokenInfo,
|
|
98
|
+
sender: _reformatAddressWithChain(params.request.address, originChain),
|
|
99
|
+
receiver: _reformatAddressWithChain(params.request.recipient || params.request.address, destinationChain),
|
|
100
|
+
version: 2
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
|
|
126
104
|
}
|
|
127
105
|
async handleSwapProcess(params) {
|
|
128
106
|
const {
|
|
@@ -171,6 +149,7 @@ export class SimpleSwapHandler {
|
|
|
171
149
|
sender,
|
|
172
150
|
toAsset
|
|
173
151
|
});
|
|
152
|
+
console.log('simpleswap data', id, addressFrom);
|
|
174
153
|
if (!id || id.length === 0 || !addressFrom || addressFrom.length === 0) {
|
|
175
154
|
throw new SwapError(SwapErrorType.UNKNOWN);
|
|
176
155
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
2
2
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
3
3
|
import TransactionService from '@subwallet/extension-base/services/transaction-service';
|
|
4
|
-
import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo,
|
|
4
|
+
import { BaseStepDetail, CommonOptimalSwapPath, CommonStepFeeInfo, OptimalSwapPathParamsV2, PermitSwapData, SwapProviderId, SwapSubmitParams, SwapSubmitStepData, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
|
|
5
5
|
import { TransactionConfig } from 'web3-core';
|
|
6
6
|
import { BalanceService } from '../../balance-service';
|
|
7
7
|
import { ChainService } from '../../chain-service';
|
|
@@ -21,12 +21,10 @@ export declare class UniswapHandler implements SwapBaseInterface {
|
|
|
21
21
|
get balanceService(): BalanceService;
|
|
22
22
|
get feeService(): FeeService;
|
|
23
23
|
get providerInfo(): import("@subwallet/extension-base/types").SwapProvider;
|
|
24
|
-
generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalSwapPath>;
|
|
25
24
|
generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
|
|
26
|
-
getApprovalStep(params:
|
|
27
|
-
getPermitStep(params:
|
|
28
|
-
getSubmitStep(params:
|
|
29
|
-
validateSwapProcess(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
|
|
25
|
+
getApprovalStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
26
|
+
getPermitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
27
|
+
getSubmitStep(params: OptimalSwapPathParamsV2, stepIndex: number): Promise<[BaseStepDetail, CommonStepFeeInfo] | undefined>;
|
|
30
28
|
handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
31
29
|
private tokenApproveSpending;
|
|
32
30
|
handleSubmitStep(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
5
5
|
import { ChainType, ExtrinsicType } from '@subwallet/extension-base/background/KoniTypes';
|
|
6
6
|
import { validateTypedSignMessageDataV3V4 } from '@subwallet/extension-base/core/logic-validation';
|
|
7
|
-
import { DynamicSwapType } from '@subwallet/extension-base/
|
|
8
|
-
import {
|
|
7
|
+
import { BasicTxErrorType, CommonStepType, DynamicSwapType, FeeOptionKey, SwapFeeType, SwapProviderId, SwapStepType } from '@subwallet/extension-base/types';
|
|
8
|
+
import { _reformatAddressWithChain } from '@subwallet/extension-base/utils';
|
|
9
9
|
import BigNumber from 'bignumber.js';
|
|
10
10
|
import { _getContractAddressOfToken, _isNativeToken } from "../../chain-service/utils/index.js";
|
|
11
11
|
import { calculateGasFeeParams } from "../../fee-service/utils/index.js";
|
|
@@ -58,13 +58,10 @@ export class UniswapHandler {
|
|
|
58
58
|
get providerInfo() {
|
|
59
59
|
return this.swapBaseHandler.providerInfo;
|
|
60
60
|
}
|
|
61
|
-
generateOptimalProcess(params) {
|
|
62
|
-
return this.swapBaseHandler.generateOptimalProcess(params, [this.getApprovalStep.bind(this), this.getPermitStep.bind(this), this.getSubmitStep.bind(this)]);
|
|
63
|
-
}
|
|
64
61
|
generateOptimalProcessV2(params) {
|
|
65
62
|
return this.swapBaseHandler.generateOptimalProcessV2(params, [this.getApprovalStep.bind(this), this.getPermitStep.bind(this), this.getSubmitStep.bind(this)]);
|
|
66
63
|
}
|
|
67
|
-
async getApprovalStep(params) {
|
|
64
|
+
async getApprovalStep(params, stepIndex) {
|
|
68
65
|
if (params.selectedQuote) {
|
|
69
66
|
const walletAddress = params.request.address;
|
|
70
67
|
const fromAmount = params.selectedQuote.fromAmount;
|
|
@@ -97,7 +94,7 @@ export class UniswapHandler {
|
|
|
97
94
|
}
|
|
98
95
|
return Promise.resolve(undefined);
|
|
99
96
|
}
|
|
100
|
-
async getPermitStep(params) {
|
|
97
|
+
async getPermitStep(params, stepIndex) {
|
|
101
98
|
if (params.selectedQuote && params.selectedQuote.metadata.permitData) {
|
|
102
99
|
const submitStep = {
|
|
103
100
|
name: 'Permit Step',
|
|
@@ -118,47 +115,29 @@ export class UniswapHandler {
|
|
|
118
115
|
}
|
|
119
116
|
return Promise.resolve(undefined);
|
|
120
117
|
}
|
|
121
|
-
async getSubmitStep(params) {
|
|
122
|
-
if (params.selectedQuote) {
|
|
123
|
-
|
|
124
|
-
name: 'Swap',
|
|
125
|
-
type: SwapStepType.SWAP,
|
|
126
|
-
metadata: {
|
|
127
|
-
sendingValue: params.request.fromAmount.toString(),
|
|
128
|
-
originTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.from),
|
|
129
|
-
destinationTokenInfo: this.chainService.getAssetBySlug(params.selectedQuote.pair.to)
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
|
|
133
|
-
}
|
|
134
|
-
return Promise.resolve(undefined);
|
|
135
|
-
}
|
|
136
|
-
async validateSwapProcess(params) {
|
|
137
|
-
const amount = params.selectedQuote.fromAmount;
|
|
138
|
-
const bnAmount = BigInt(amount);
|
|
139
|
-
if (bnAmount <= BigInt(0)) {
|
|
140
|
-
return Promise.resolve([new TransactionError(BasicTxErrorType.INVALID_PARAMS, 'Amount must be greater than 0')]);
|
|
118
|
+
async getSubmitStep(params, stepIndex) {
|
|
119
|
+
if (!params.selectedQuote) {
|
|
120
|
+
return Promise.resolve(undefined);
|
|
141
121
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
isXcmOk = true;
|
|
122
|
+
const originTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.from);
|
|
123
|
+
const destinationTokenInfo = this.chainService.getAssetBySlug(params.selectedQuote.pair.to);
|
|
124
|
+
const originChain = this.chainService.getChainInfoByKey(originTokenInfo.originChain);
|
|
125
|
+
const destinationChain = this.chainService.getChainInfoByKey(destinationTokenInfo.originChain);
|
|
126
|
+
const submitStep = {
|
|
127
|
+
name: 'Swap',
|
|
128
|
+
type: SwapStepType.SWAP,
|
|
129
|
+
// @ts-ignore
|
|
130
|
+
metadata: {
|
|
131
|
+
sendingValue: params.request.fromAmount.toString(),
|
|
132
|
+
expectedReceive: params.selectedQuote.toAmount,
|
|
133
|
+
originTokenInfo,
|
|
134
|
+
destinationTokenInfo,
|
|
135
|
+
sender: _reformatAddressWithChain(params.request.address, originChain),
|
|
136
|
+
receiver: _reformatAddressWithChain(params.request.recipient || params.request.address, destinationChain),
|
|
137
|
+
version: 2
|
|
159
138
|
}
|
|
160
|
-
}
|
|
161
|
-
return [];
|
|
139
|
+
};
|
|
140
|
+
return Promise.resolve([submitStep, params.selectedQuote.feeInfo]);
|
|
162
141
|
}
|
|
163
142
|
async handleSwapProcess(params) {
|
|
164
143
|
const {
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { TransactionError } from '@subwallet/extension-base/background/errors/TransactionError';
|
|
2
2
|
import KoniState from '@subwallet/extension-base/koni/background/handlers/State';
|
|
3
|
-
import { ServiceStatus,
|
|
4
|
-
import { DynamicSwapAction } from '@subwallet/extension-base/
|
|
5
|
-
import { OptimalSwapPathParamsV2, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
|
|
3
|
+
import { ServiceStatus, StoppableServiceInterface } from '@subwallet/extension-base/services/base/types';
|
|
4
|
+
import { DynamicSwapAction, OptimalSwapPathParamsV2, SwapRequestV2, ValidateSwapProcessParams } from '@subwallet/extension-base/types';
|
|
6
5
|
import { CommonOptimalSwapPath } from '@subwallet/extension-base/types/service-base';
|
|
7
|
-
import {
|
|
6
|
+
import { SwapPair, SwapQuoteResponse, SwapRequestResult, SwapSubmitParams, SwapSubmitStepData } from '@subwallet/extension-base/types/swap';
|
|
8
7
|
import { PromiseHandler } from '@subwallet/extension-base/utils';
|
|
9
|
-
export declare
|
|
10
|
-
export declare class SwapService implements ServiceWithProcessInterface, StoppableServiceInterface {
|
|
8
|
+
export declare class SwapService implements StoppableServiceInterface {
|
|
11
9
|
protected readonly state: KoniState;
|
|
12
10
|
private eventService;
|
|
13
11
|
private readonly chainService;
|
|
@@ -18,15 +16,11 @@ export declare class SwapService implements ServiceWithProcessInterface, Stoppab
|
|
|
18
16
|
status: ServiceStatus;
|
|
19
17
|
constructor(state: KoniState);
|
|
20
18
|
private askProvidersForQuote;
|
|
21
|
-
private getDefaultProcess;
|
|
22
19
|
private getDefaultProcessV2;
|
|
23
|
-
generateOptimalProcess(params: OptimalSwapPathParams): Promise<CommonOptimalSwapPath>;
|
|
24
20
|
generateOptimalProcessV2(params: OptimalSwapPathParamsV2): Promise<CommonOptimalSwapPath>;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
getAvailablePath(request: SwapRequest): [DynamicSwapAction[], SwapRequest | undefined];
|
|
29
|
-
getLatestQuoteFromSwapRequest(request: SwapRequest): Promise<{
|
|
21
|
+
handleSwapRequestV2(request: SwapRequestV2): Promise<SwapRequestResult>;
|
|
22
|
+
getAvailablePath(request: SwapRequestV2): [DynamicSwapAction[], SwapRequestV2 | undefined];
|
|
23
|
+
getLatestQuoteFromSwapRequest(request: SwapRequestV2): Promise<{
|
|
30
24
|
path: DynamicSwapAction[];
|
|
31
25
|
swapQuoteResponse: SwapQuoteResponse;
|
|
32
26
|
}>;
|
|
@@ -38,7 +32,7 @@ export declare class SwapService implements ServiceWithProcessInterface, Stoppab
|
|
|
38
32
|
waitForStarted(): Promise<void>;
|
|
39
33
|
waitForStopped(): Promise<void>;
|
|
40
34
|
getSwapPairs(): SwapPair[];
|
|
41
|
-
|
|
35
|
+
validateSwapProcessV2(params: ValidateSwapProcessParams): Promise<TransactionError[]>;
|
|
42
36
|
handleSwapProcess(params: SwapSubmitParams): Promise<SwapSubmitStepData>;
|
|
43
37
|
subscribeSwapPairs(callback: (pairs: SwapPair[]) => void): import("rxjs").Subscription;
|
|
44
38
|
}
|