@fiado/api-invoker 4.36.0 → 4.37.1
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/bin/container.config.js +5 -0
- package/bin/index.d.ts +1 -0
- package/bin/index.js +1 -0
- package/bin/transactionProcessor/api/TransactionProcessorApi.d.ts +2 -0
- package/bin/transactionProcessor/api/TransactionProcessorApi.js +4 -0
- package/bin/transactionProcessor/api/interfaces/ITransactionProcessorApi.d.ts +18 -0
- package/bin/walletFundingSettlement/api/WalletFundingSettlementApi.d.ts +10 -0
- package/bin/walletFundingSettlement/api/WalletFundingSettlementApi.js +30 -0
- package/bin/walletFundingSettlement/api/interfaces/IWalletFundingSettlementApi.d.ts +25 -0
- package/bin/walletFundingSettlement/api/interfaces/IWalletFundingSettlementApi.js +1 -0
- package/bin/walletFundingSettlement/index.d.ts +2 -0
- package/bin/walletFundingSettlement/index.js +2 -0
- package/package.json +2 -2
- package/src/container.config.ts +6 -0
- package/src/index.ts +1 -0
- package/src/transactionProcessor/api/TransactionProcessorApi.ts +8 -0
- package/src/transactionProcessor/api/interfaces/ITransactionProcessorApi.ts +21 -0
- package/src/walletFundingSettlement/api/WalletFundingSettlementApi.ts +22 -0
- package/src/walletFundingSettlement/api/interfaces/IWalletFundingSettlementApi.ts +31 -0
- package/src/walletFundingSettlement/index.ts +2 -0
package/bin/container.config.js
CHANGED
|
@@ -108,6 +108,8 @@ import { TotpSecurityApi } from "./totp-security/index.js";
|
|
|
108
108
|
import { EqualityConnectorApi } from "./equality-connector/index.js";
|
|
109
109
|
// Contacts business — fuente de verdad de correos verificados (F2 gate UNIR)
|
|
110
110
|
import { ContactsBusinessApi } from "./contacts-business/index.js";
|
|
111
|
+
// Wallet funding settlement — TransactWriteItems atómico del money path cash-in (spec 15)
|
|
112
|
+
import { WalletFundingSettlementApi } from "./walletFundingSettlement/index.js";
|
|
111
113
|
export const apiInvokerBindings = new ContainerModule(({ bind }) => {
|
|
112
114
|
// UTILS bindings
|
|
113
115
|
bind("InvokerUtils").to(InvokerUtils);
|
|
@@ -227,4 +229,7 @@ export const apiInvokerBindings = new ContainerModule(({ bind }) => {
|
|
|
227
229
|
bind("IEqualityConnectorApi").to(EqualityConnectorApi);
|
|
228
230
|
// Contacts business — fuente de verdad de correos verificados (F2 gate UNIR)
|
|
229
231
|
bind("IContactsBusinessApi").to(ContactsBusinessApi);
|
|
232
|
+
// Wallet funding settlement — TransactWriteItems atómico del money path cash-in
|
|
233
|
+
// (consumido por equality-connector post processor.walletFundingValidate). Ver spec 15.
|
|
234
|
+
bind("IWalletFundingSettlementApi").to(WalletFundingSettlementApi);
|
|
230
235
|
});
|
package/bin/index.d.ts
CHANGED
package/bin/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import { AuthorizeCollectorOrderRequest, AuthorizeCollectorOrderResponse, Author
|
|
|
4
4
|
import { ApiGatewayResponse } from "@fiado/gateway-adapter";
|
|
5
5
|
import { ValidateWalletFundingRequest, ValidateWalletFundingResponse, CreditWalletFundingRequest, CreditWalletFundingResponse, ReverseWalletFundingRequest, ReverseWalletFundingResponse, GetWalletFundingLimitRequest, GetWalletFundingLimitResponse } from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
6
6
|
import { RemittanceCreditBackRequest, RemittanceCreditBackResponse } from "@fiado/type-kit/bin/remittance/index.js";
|
|
7
|
+
import { PublishFiadoTxRequest, PublishFiadoTxResponse } from "@fiado/type-kit/bin/transactionProcessor/index.js";
|
|
7
8
|
type ProcessUpdateLevelRequest = import("@fiado/type-kit/bin/transactionProcessor/dtos/ProcessUpdateLevelRequest.js").default;
|
|
8
9
|
type FiadoApiResponse<T> = import("@fiado/type-kit/bin/apiResponse/dtos/FiadoApiResponse.js").default<T>;
|
|
9
10
|
export default class TransactionProcessorApi implements ITransactionProcessorApi {
|
|
@@ -22,5 +23,6 @@ export default class TransactionProcessorApi implements ITransactionProcessorApi
|
|
|
22
23
|
walletFundingReverse(request: ReverseWalletFundingRequest): Promise<ApiGatewayResponse<ReverseWalletFundingResponse>>;
|
|
23
24
|
walletFundingGetLimit(request: GetWalletFundingLimitRequest): Promise<ApiGatewayResponse<GetWalletFundingLimitResponse>>;
|
|
24
25
|
creditBack(request: RemittanceCreditBackRequest): Promise<FiadoApiResponse<RemittanceCreditBackResponse>>;
|
|
26
|
+
publishFiadoTx(request: PublishFiadoTxRequest): Promise<ApiGatewayResponse<PublishFiadoTxResponse>>;
|
|
25
27
|
}
|
|
26
28
|
export {};
|
|
@@ -65,6 +65,10 @@ let TransactionProcessorApi = class TransactionProcessorApi {
|
|
|
65
65
|
const url = `${this.baseUrl}remittance/credit-back`;
|
|
66
66
|
return await this.httpRequest.post(url, request);
|
|
67
67
|
}
|
|
68
|
+
async publishFiadoTx(request) {
|
|
69
|
+
const url = `${this.baseUrl}wallet-funding/publish`;
|
|
70
|
+
return await this.httpRequest.post(url, request);
|
|
71
|
+
}
|
|
68
72
|
};
|
|
69
73
|
TransactionProcessorApi = __decorate([
|
|
70
74
|
injectable(),
|
|
@@ -3,6 +3,7 @@ import { AuthorizeCollectorOrderRequest, AuthorizeCollectorOrderResponse, Author
|
|
|
3
3
|
import { ApiGatewayResponse } from "@fiado/gateway-adapter";
|
|
4
4
|
import { ValidateWalletFundingRequest, ValidateWalletFundingResponse, CreditWalletFundingRequest, CreditWalletFundingResponse, ReverseWalletFundingRequest, ReverseWalletFundingResponse, GetWalletFundingLimitRequest, GetWalletFundingLimitResponse } from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
5
5
|
import { RemittanceCreditBackRequest, RemittanceCreditBackResponse } from "@fiado/type-kit/bin/remittance/index.js";
|
|
6
|
+
import { PublishFiadoTxRequest, PublishFiadoTxResponse } from "@fiado/type-kit/bin/transactionProcessor/index.js";
|
|
6
7
|
type ProcessUpdateLevelRequest = import("@fiado/type-kit/bin/transactionProcessor/dtos/ProcessUpdateLevelRequest.js").default;
|
|
7
8
|
export interface ITransactionProcessorApi {
|
|
8
9
|
authorizeTransaction(request: AuthorizeCreditCardPurchaseRequest): Promise<any>;
|
|
@@ -43,5 +44,22 @@ export interface ITransactionProcessorApi {
|
|
|
43
44
|
* Backend: POST /transaction-processor/remittance/credit-back (privado VPC).
|
|
44
45
|
*/
|
|
45
46
|
creditBack(request: RemittanceCreditBackRequest): Promise<FiadoApiResponse<RemittanceCreditBackResponse>>;
|
|
47
|
+
/**
|
|
48
|
+
* Publica el evento FiadoTx del wallet-funding cash-in al SQS
|
|
49
|
+
* TRANSACTION_QUEUE para que transaction-business persista la
|
|
50
|
+
* tupla EQ_CASH_SA en FiadoTx_GT.
|
|
51
|
+
*
|
|
52
|
+
* Ownership del SQS sigue en el processor (el settlement NO publica,
|
|
53
|
+
* solo ejecuta el TransactWriteItems atómico). Best-effort: status
|
|
54
|
+
* FAILED indica que sqs.sendMessage falló — el caller debe loggear
|
|
55
|
+
* y continuar; el reconciler T+0 del connector recupera gaps.
|
|
56
|
+
*
|
|
57
|
+
* Backend: POST /transaction-processor/wallet-funding/publish (privado VPC).
|
|
58
|
+
* Consumido por equality-connector (post-settlement OK) y por su
|
|
59
|
+
* FiadoTxGapReconcilerCron.
|
|
60
|
+
*
|
|
61
|
+
* Ver spec 15 §6.2.
|
|
62
|
+
*/
|
|
63
|
+
publishFiadoTx(request: PublishFiadoTxRequest): Promise<ApiGatewayResponse<PublishFiadoTxResponse>>;
|
|
46
64
|
}
|
|
47
65
|
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IHttpRequest } from "@fiado/http-client";
|
|
2
|
+
import { ApiGatewayResponse } from "@fiado/gateway-adapter";
|
|
3
|
+
import { SettleWalletFundingRequest, SettleWalletFundingResponse } from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
4
|
+
import { IWalletFundingSettlementApi } from "./interfaces/IWalletFundingSettlementApi.js";
|
|
5
|
+
export default class WalletFundingSettlementApi implements IWalletFundingSettlementApi {
|
|
6
|
+
private httpRequest;
|
|
7
|
+
private readonly baseUrl;
|
|
8
|
+
constructor(httpRequest: IHttpRequest);
|
|
9
|
+
settle(request: SettleWalletFundingRequest): Promise<ApiGatewayResponse<SettleWalletFundingResponse>>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
11
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
12
|
+
};
|
|
13
|
+
import { inject, injectable } from "inversify";
|
|
14
|
+
let WalletFundingSettlementApi = class WalletFundingSettlementApi {
|
|
15
|
+
httpRequest;
|
|
16
|
+
baseUrl = process.env.WALLET_FUNDING_SETTLEMENT_LAMBDA_URL || "";
|
|
17
|
+
constructor(httpRequest) {
|
|
18
|
+
this.httpRequest = httpRequest;
|
|
19
|
+
}
|
|
20
|
+
async settle(request) {
|
|
21
|
+
const url = `${this.baseUrl}/settlements`;
|
|
22
|
+
return await this.httpRequest.post(url, request);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
WalletFundingSettlementApi = __decorate([
|
|
26
|
+
injectable(),
|
|
27
|
+
__param(0, inject("IHttpRequest")),
|
|
28
|
+
__metadata("design:paramtypes", [Object])
|
|
29
|
+
], WalletFundingSettlementApi);
|
|
30
|
+
export default WalletFundingSettlementApi;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ApiGatewayResponse } from "@fiado/gateway-adapter";
|
|
2
|
+
import { SettleWalletFundingRequest, SettleWalletFundingResponse } from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cliente hacia `wallet-funding-settlement` (lambda privado VPC).
|
|
5
|
+
*
|
|
6
|
+
* Lo consume exclusivamente `equality-connector.WebhookPaymentManager`
|
|
7
|
+
* post `processor.walletFundingValidate()`. Ningún otro lambda conoce
|
|
8
|
+
* este cliente — el settlement está dedicado al money path wallet-funding
|
|
9
|
+
* cash-in.
|
|
10
|
+
*
|
|
11
|
+
* Endpoint backend en wallet-funding-settlement:
|
|
12
|
+
* - POST /settlements (privado VPC)
|
|
13
|
+
*
|
|
14
|
+
* Ver spec 15 (https://github.com/Fiado-Today/surekeep/blob/main/docs/4_specs/arquitectura/15_wallet_funding_settlement.md).
|
|
15
|
+
*/
|
|
16
|
+
export interface IWalletFundingSettlementApi {
|
|
17
|
+
/**
|
|
18
|
+
* Ejecuta el TransactWriteItems atómico (balance + payment status = APPLIED).
|
|
19
|
+
*
|
|
20
|
+
* Idempotente: si el payment ya estaba en APPLIED al momento del request,
|
|
21
|
+
* devuelve `alreadySettled=true` con el `processorTransactionNumber`
|
|
22
|
+
* cacheado sin re-creditar.
|
|
23
|
+
*/
|
|
24
|
+
settle(request: SettleWalletFundingRequest): Promise<ApiGatewayResponse<SettleWalletFundingResponse>>;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fiado/api-invoker",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.37.1",
|
|
4
4
|
"description": "Sirve como un puente entre diferentes funciones lambda, facilitando la comunicación entre ellas a través de invocaciones http",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "bin/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@fiado/gateway-adapter": "^2.0.2",
|
|
35
35
|
"@fiado/http-client": "^2.0.1",
|
|
36
36
|
"@fiado/logger": "^1.1.3",
|
|
37
|
-
"@fiado/type-kit": "^3.
|
|
37
|
+
"@fiado/type-kit": "^3.123.0",
|
|
38
38
|
"dotenv": "^16.4.7"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
package/src/container.config.ts
CHANGED
|
@@ -167,6 +167,8 @@ import { ITotpSecurityApi, TotpSecurityApi } from "./totp-security/index.js";
|
|
|
167
167
|
import { IEqualityConnectorApi, EqualityConnectorApi } from "./equality-connector/index.js";
|
|
168
168
|
// Contacts business — fuente de verdad de correos verificados (F2 gate UNIR)
|
|
169
169
|
import { IContactsBusinessApi, ContactsBusinessApi } from "./contacts-business/index.js";
|
|
170
|
+
// Wallet funding settlement — TransactWriteItems atómico del money path cash-in (spec 15)
|
|
171
|
+
import { IWalletFundingSettlementApi, WalletFundingSettlementApi } from "./walletFundingSettlement/index.js";
|
|
170
172
|
|
|
171
173
|
export const apiInvokerBindings = new ContainerModule(({ bind }) => {
|
|
172
174
|
// UTILS bindings
|
|
@@ -303,4 +305,8 @@ export const apiInvokerBindings = new ContainerModule(({ bind }) => {
|
|
|
303
305
|
|
|
304
306
|
// Contacts business — fuente de verdad de correos verificados (F2 gate UNIR)
|
|
305
307
|
bind<IContactsBusinessApi>("IContactsBusinessApi").to(ContactsBusinessApi);
|
|
308
|
+
|
|
309
|
+
// Wallet funding settlement — TransactWriteItems atómico del money path cash-in
|
|
310
|
+
// (consumido por equality-connector post processor.walletFundingValidate). Ver spec 15.
|
|
311
|
+
bind<IWalletFundingSettlementApi>("IWalletFundingSettlementApi").to(WalletFundingSettlementApi);
|
|
306
312
|
});
|
package/src/index.ts
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
GetWalletFundingLimitResponse,
|
|
23
23
|
} from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
24
24
|
import { RemittanceCreditBackRequest, RemittanceCreditBackResponse } from "@fiado/type-kit/bin/remittance/index.js";
|
|
25
|
+
import { PublishFiadoTxRequest, PublishFiadoTxResponse } from "@fiado/type-kit/bin/transactionProcessor/index.js";
|
|
25
26
|
type ProcessUpdateLevelRequest = import("@fiado/type-kit/bin/transactionProcessor/dtos/ProcessUpdateLevelRequest.js").default;
|
|
26
27
|
type FiadoApiResponse<T> = import("@fiado/type-kit/bin/apiResponse/dtos/FiadoApiResponse.js").default<T>;
|
|
27
28
|
|
|
@@ -102,4 +103,11 @@ export default class TransactionProcessorApi implements ITransactionProcessorApi
|
|
|
102
103
|
const url = `${this.baseUrl}remittance/credit-back`;
|
|
103
104
|
return await this.httpRequest.post(url, request);
|
|
104
105
|
}
|
|
106
|
+
|
|
107
|
+
async publishFiadoTx(
|
|
108
|
+
request: PublishFiadoTxRequest,
|
|
109
|
+
): Promise<ApiGatewayResponse<PublishFiadoTxResponse>> {
|
|
110
|
+
const url = `${this.baseUrl}wallet-funding/publish`;
|
|
111
|
+
return await this.httpRequest.post(url, request);
|
|
112
|
+
}
|
|
105
113
|
}
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
GetWalletFundingLimitResponse,
|
|
22
22
|
} from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
23
23
|
import { RemittanceCreditBackRequest, RemittanceCreditBackResponse } from "@fiado/type-kit/bin/remittance/index.js";
|
|
24
|
+
import { PublishFiadoTxRequest, PublishFiadoTxResponse } from "@fiado/type-kit/bin/transactionProcessor/index.js";
|
|
24
25
|
type ProcessUpdateLevelRequest = import("@fiado/type-kit/bin/transactionProcessor/dtos/ProcessUpdateLevelRequest.js").default;
|
|
25
26
|
|
|
26
27
|
export interface ITransactionProcessorApi {
|
|
@@ -84,4 +85,24 @@ export interface ITransactionProcessorApi {
|
|
|
84
85
|
creditBack(
|
|
85
86
|
request: RemittanceCreditBackRequest,
|
|
86
87
|
): Promise<FiadoApiResponse<RemittanceCreditBackResponse>>;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Publica el evento FiadoTx del wallet-funding cash-in al SQS
|
|
91
|
+
* TRANSACTION_QUEUE para que transaction-business persista la
|
|
92
|
+
* tupla EQ_CASH_SA en FiadoTx_GT.
|
|
93
|
+
*
|
|
94
|
+
* Ownership del SQS sigue en el processor (el settlement NO publica,
|
|
95
|
+
* solo ejecuta el TransactWriteItems atómico). Best-effort: status
|
|
96
|
+
* FAILED indica que sqs.sendMessage falló — el caller debe loggear
|
|
97
|
+
* y continuar; el reconciler T+0 del connector recupera gaps.
|
|
98
|
+
*
|
|
99
|
+
* Backend: POST /transaction-processor/wallet-funding/publish (privado VPC).
|
|
100
|
+
* Consumido por equality-connector (post-settlement OK) y por su
|
|
101
|
+
* FiadoTxGapReconcilerCron.
|
|
102
|
+
*
|
|
103
|
+
* Ver spec 15 §6.2.
|
|
104
|
+
*/
|
|
105
|
+
publishFiadoTx(
|
|
106
|
+
request: PublishFiadoTxRequest,
|
|
107
|
+
): Promise<ApiGatewayResponse<PublishFiadoTxResponse>>;
|
|
87
108
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { inject, injectable } from "inversify";
|
|
2
|
+
import { IHttpRequest } from "@fiado/http-client";
|
|
3
|
+
import { ApiGatewayResponse } from "@fiado/gateway-adapter";
|
|
4
|
+
import {
|
|
5
|
+
SettleWalletFundingRequest,
|
|
6
|
+
SettleWalletFundingResponse,
|
|
7
|
+
} from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
8
|
+
import { IWalletFundingSettlementApi } from "./interfaces/IWalletFundingSettlementApi.js";
|
|
9
|
+
|
|
10
|
+
@injectable()
|
|
11
|
+
export default class WalletFundingSettlementApi implements IWalletFundingSettlementApi {
|
|
12
|
+
private readonly baseUrl = process.env.WALLET_FUNDING_SETTLEMENT_LAMBDA_URL || "";
|
|
13
|
+
|
|
14
|
+
constructor(@inject("IHttpRequest") private httpRequest: IHttpRequest) {}
|
|
15
|
+
|
|
16
|
+
async settle(
|
|
17
|
+
request: SettleWalletFundingRequest,
|
|
18
|
+
): Promise<ApiGatewayResponse<SettleWalletFundingResponse>> {
|
|
19
|
+
const url = `${this.baseUrl}/settlements`;
|
|
20
|
+
return await this.httpRequest.post(url, request);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ApiGatewayResponse } from "@fiado/gateway-adapter";
|
|
2
|
+
import {
|
|
3
|
+
SettleWalletFundingRequest,
|
|
4
|
+
SettleWalletFundingResponse,
|
|
5
|
+
} from "@fiado/type-kit/bin/walletFunding/index.js";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Cliente hacia `wallet-funding-settlement` (lambda privado VPC).
|
|
9
|
+
*
|
|
10
|
+
* Lo consume exclusivamente `equality-connector.WebhookPaymentManager`
|
|
11
|
+
* post `processor.walletFundingValidate()`. Ningún otro lambda conoce
|
|
12
|
+
* este cliente — el settlement está dedicado al money path wallet-funding
|
|
13
|
+
* cash-in.
|
|
14
|
+
*
|
|
15
|
+
* Endpoint backend en wallet-funding-settlement:
|
|
16
|
+
* - POST /settlements (privado VPC)
|
|
17
|
+
*
|
|
18
|
+
* Ver spec 15 (https://github.com/Fiado-Today/surekeep/blob/main/docs/4_specs/arquitectura/15_wallet_funding_settlement.md).
|
|
19
|
+
*/
|
|
20
|
+
export interface IWalletFundingSettlementApi {
|
|
21
|
+
/**
|
|
22
|
+
* Ejecuta el TransactWriteItems atómico (balance + payment status = APPLIED).
|
|
23
|
+
*
|
|
24
|
+
* Idempotente: si el payment ya estaba en APPLIED al momento del request,
|
|
25
|
+
* devuelve `alreadySettled=true` con el `processorTransactionNumber`
|
|
26
|
+
* cacheado sin re-creditar.
|
|
27
|
+
*/
|
|
28
|
+
settle(
|
|
29
|
+
request: SettleWalletFundingRequest,
|
|
30
|
+
): Promise<ApiGatewayResponse<SettleWalletFundingResponse>>;
|
|
31
|
+
}
|