starknet 3.2.0 → 3.5.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/.eslintrc +2 -1
- package/CHANGELOG.md +32 -0
- package/__tests__/account.test.ts +11 -21
- package/__tests__/accountContract.test.ts +15 -27
- package/__tests__/contract.test.ts +156 -59
- package/__tests__/utils/utils.browser.test.ts +1 -3
- package/account/default.d.ts +6 -0
- package/account/default.js +129 -0
- package/contract/contractFactory.d.ts +36 -0
- package/contract/contractFactory.js +218 -0
- package/contract/default.d.ts +143 -0
- package/{contract.js → contract/default.js} +357 -86
- package/contract/index.d.ts +3 -0
- package/contract/index.js +28 -0
- package/contract/interface.d.ts +79 -0
- package/contract/interface.js +8 -0
- package/dist/account/default.d.ts +6 -1
- package/dist/account/default.js +99 -0
- package/dist/contract/contractFactory.d.ts +32 -0
- package/dist/contract/contractFactory.js +102 -0
- package/dist/contract/default.d.ts +121 -0
- package/dist/{contract.js → contract/default.js} +321 -73
- package/dist/contract/index.d.ts +3 -0
- package/dist/contract/index.js +15 -0
- package/dist/contract/interface.d.ts +72 -0
- package/dist/contract/interface.js +9 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/provider/default.d.ts +10 -5
- package/dist/provider/default.js +29 -11
- package/dist/provider/interface.d.ts +8 -2
- package/dist/types/api.d.ts +6 -0
- package/dist/types/contract.d.ts +5 -0
- package/dist/types/contract.js +2 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/lib.d.ts +11 -1
- package/dist/utils/transaction.d.ts +1 -2
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/package.json +1 -1
- package/provider/default.d.ts +10 -5
- package/provider/default.js +41 -21
- package/provider/interface.d.ts +8 -2
- package/src/account/default.ts +109 -1
- package/src/contract/contractFactory.ts +78 -0
- package/src/contract/default.ts +622 -0
- package/src/contract/index.ts +3 -0
- package/src/contract/interface.ts +87 -0
- package/src/index.ts +1 -1
- package/src/provider/default.ts +29 -19
- package/src/provider/interface.ts +9 -2
- package/src/types/api.ts +7 -0
- package/src/types/contract.ts +5 -0
- package/src/types/index.ts +1 -0
- package/src/types/lib.ts +12 -1
- package/src/utils/transaction.ts +1 -2
- package/types/api.d.ts +6 -0
- package/types/contract.d.ts +5 -0
- package/types/contract.js +2 -0
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
- package/types/lib.d.ts +11 -1
- package/utils/transaction.d.ts +1 -2
- package/contract.d.ts +0 -98
- package/dist/contract.d.ts +0 -94
- package/src/contract.ts +0 -357
package/src/index.ts
CHANGED
package/src/provider/default.ts
CHANGED
|
@@ -81,7 +81,7 @@ export class Provider implements ProviderInterface {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
private getFetchMethod(endpoint: keyof Endpoints) {
|
|
84
|
-
const postMethodEndpoints = ['add_transaction', 'call_contract'];
|
|
84
|
+
const postMethodEndpoints = ['add_transaction', 'call_contract', 'estimate_fee'];
|
|
85
85
|
|
|
86
86
|
return postMethodEndpoints.includes(endpoint) ? 'POST' : 'GET';
|
|
87
87
|
}
|
|
@@ -167,20 +167,14 @@ export class Provider implements ProviderInterface {
|
|
|
167
167
|
*/
|
|
168
168
|
public async callContract(
|
|
169
169
|
{ contractAddress, entrypoint, calldata = [] }: Call,
|
|
170
|
-
blockIdentifier: BlockIdentifier = null
|
|
170
|
+
options: { blockIdentifier: BlockIdentifier } = { blockIdentifier: null }
|
|
171
171
|
): Promise<CallContractResponse> {
|
|
172
|
-
return this.fetchEndpoint(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
signature: [],
|
|
179
|
-
contract_address: contractAddress,
|
|
180
|
-
entry_point_selector: getSelectorFromName(entrypoint),
|
|
181
|
-
calldata,
|
|
182
|
-
}
|
|
183
|
-
);
|
|
172
|
+
return this.fetchEndpoint('call_contract', options, {
|
|
173
|
+
signature: [],
|
|
174
|
+
contract_address: contractAddress,
|
|
175
|
+
entry_point_selector: getSelectorFromName(entrypoint),
|
|
176
|
+
calldata,
|
|
177
|
+
});
|
|
184
178
|
}
|
|
185
179
|
|
|
186
180
|
/**
|
|
@@ -317,10 +311,8 @@ export class Provider implements ProviderInterface {
|
|
|
317
311
|
* Invokes a function on starknet
|
|
318
312
|
* @deprecated This method wont be supported as soon as fees are mandatory
|
|
319
313
|
*
|
|
320
|
-
* @param
|
|
321
|
-
* @param
|
|
322
|
-
* @param calldata - (optional, default []) calldata
|
|
323
|
-
* @param signature - (optional) signature to send along
|
|
314
|
+
* @param invocation
|
|
315
|
+
* @param _abi - (optional) signature to send along
|
|
324
316
|
* @returns response from addTransaction
|
|
325
317
|
*/
|
|
326
318
|
public invokeFunction(invocation: Invocation, _abi?: Abi): Promise<AddTransactionResponse> {
|
|
@@ -333,7 +325,18 @@ export class Provider implements ProviderInterface {
|
|
|
333
325
|
});
|
|
334
326
|
}
|
|
335
327
|
|
|
336
|
-
public
|
|
328
|
+
public estimateFee(invocation: Invocation): Promise<any> {
|
|
329
|
+
return this.fetchEndpoint('estimate_fee', undefined, {
|
|
330
|
+
// TODO: change the TYPE of the call
|
|
331
|
+
type: 'INVOKE_FUNCTION',
|
|
332
|
+
contract_address: invocation.contractAddress,
|
|
333
|
+
entry_point_selector: getSelectorFromName(invocation.entrypoint),
|
|
334
|
+
calldata: bigNumberishArrayToDecimalStringArray(invocation.calldata ?? []),
|
|
335
|
+
signature: bigNumberishArrayToDecimalStringArray(invocation.signature ?? []),
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
public async waitForTransaction(txHash: BigNumberish, retryInterval: number = 8000) {
|
|
337
340
|
let onchain = false;
|
|
338
341
|
await wait(retryInterval);
|
|
339
342
|
|
|
@@ -355,4 +358,11 @@ export class Provider implements ProviderInterface {
|
|
|
355
358
|
}
|
|
356
359
|
}
|
|
357
360
|
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* @deprecated use `waitForTransaction` instead
|
|
364
|
+
*/
|
|
365
|
+
public async waitForTx(txHash: BigNumberish, retryInterval: number = 8000) {
|
|
366
|
+
return this.waitForTransaction(txHash, retryInterval);
|
|
367
|
+
}
|
|
358
368
|
}
|
|
@@ -40,7 +40,9 @@ export abstract class ProviderInterface {
|
|
|
40
40
|
*/
|
|
41
41
|
public abstract callContract(
|
|
42
42
|
invokeTransaction: Call,
|
|
43
|
-
|
|
43
|
+
options: {
|
|
44
|
+
blockIdentifier: BlockIdentifier;
|
|
45
|
+
}
|
|
44
46
|
): Promise<CallContractResponse>;
|
|
45
47
|
|
|
46
48
|
/**
|
|
@@ -137,5 +139,10 @@ export abstract class ProviderInterface {
|
|
|
137
139
|
*/
|
|
138
140
|
public abstract invokeFunction(invocation: Invocation): Promise<AddTransactionResponse>;
|
|
139
141
|
|
|
140
|
-
public abstract
|
|
142
|
+
public abstract waitForTransaction(txHash: BigNumberish, retryInterval?: number): Promise<void>;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* @deprecated use `waitForTransaction` instead
|
|
146
|
+
*/
|
|
147
|
+
public abstract waitForTransaction(txHash: BigNumberish, retryInterval?: number): Promise<void>;
|
|
141
148
|
}
|
package/src/types/api.ts
CHANGED
|
@@ -67,6 +67,11 @@ export type Endpoints = {
|
|
|
67
67
|
REQUEST: CallContractTransaction;
|
|
68
68
|
RESPONSE: CallContractResponse;
|
|
69
69
|
};
|
|
70
|
+
estimate_fee: {
|
|
71
|
+
QUERY: never;
|
|
72
|
+
REQUEST: Transaction;
|
|
73
|
+
RESPONSE: EstimateFeeResponse;
|
|
74
|
+
};
|
|
70
75
|
};
|
|
71
76
|
|
|
72
77
|
export type GetContractAddressesResponse = {
|
|
@@ -168,6 +173,8 @@ export type TransactionReceipt = {
|
|
|
168
173
|
l2_to_l1_messages: string[];
|
|
169
174
|
events: string[];
|
|
170
175
|
};
|
|
176
|
+
// TODO: Add response data
|
|
177
|
+
export type EstimateFeeResponse = {};
|
|
171
178
|
|
|
172
179
|
export type RawArgs = {
|
|
173
180
|
[inputName: string]: string | string[] | { type: 'struct'; [k: string]: BigNumberish };
|
package/src/types/index.ts
CHANGED
package/src/types/lib.ts
CHANGED
|
@@ -45,7 +45,7 @@ export type FunctionAbi = {
|
|
|
45
45
|
name: string;
|
|
46
46
|
outputs: AbiEntry[];
|
|
47
47
|
stateMutability?: 'view';
|
|
48
|
-
type: 'function';
|
|
48
|
+
type: 'function' | 'constructor';
|
|
49
49
|
};
|
|
50
50
|
|
|
51
51
|
export type StructAbi = {
|
|
@@ -70,3 +70,14 @@ export type CompiledContract = {
|
|
|
70
70
|
export type CompressedCompiledContract = Omit<CompiledContract, 'program'> & {
|
|
71
71
|
program: CompressedProgram;
|
|
72
72
|
};
|
|
73
|
+
|
|
74
|
+
export type Struct = {
|
|
75
|
+
type: 'struct';
|
|
76
|
+
[k: string]: BigNumberish;
|
|
77
|
+
};
|
|
78
|
+
export type Args = {
|
|
79
|
+
[inputName: string]: BigNumberish | BigNumberish[] | ParsedStruct | ParsedStruct[];
|
|
80
|
+
};
|
|
81
|
+
export type ParsedStruct = {
|
|
82
|
+
[key: string]: BigNumberish | ParsedStruct;
|
|
83
|
+
};
|
package/src/utils/transaction.ts
CHANGED
package/types/api.d.ts
CHANGED
|
@@ -66,6 +66,11 @@ export declare type Endpoints = {
|
|
|
66
66
|
REQUEST: CallContractTransaction;
|
|
67
67
|
RESPONSE: CallContractResponse;
|
|
68
68
|
};
|
|
69
|
+
estimate_fee: {
|
|
70
|
+
QUERY: never;
|
|
71
|
+
REQUEST: Transaction;
|
|
72
|
+
RESPONSE: EstimateFeeResponse;
|
|
73
|
+
};
|
|
69
74
|
};
|
|
70
75
|
export declare type GetContractAddressesResponse = {
|
|
71
76
|
Starknet: string;
|
|
@@ -155,6 +160,7 @@ export declare type TransactionReceipt = {
|
|
|
155
160
|
l2_to_l1_messages: string[];
|
|
156
161
|
events: string[];
|
|
157
162
|
};
|
|
163
|
+
export declare type EstimateFeeResponse = {};
|
|
158
164
|
export declare type RawArgs = {
|
|
159
165
|
[inputName: string]:
|
|
160
166
|
| string
|
package/types/index.d.ts
CHANGED
package/types/index.js
CHANGED
package/types/lib.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export declare type FunctionAbi = {
|
|
|
40
40
|
name: string;
|
|
41
41
|
outputs: AbiEntry[];
|
|
42
42
|
stateMutability?: 'view';
|
|
43
|
-
type: 'function';
|
|
43
|
+
type: 'function' | 'constructor';
|
|
44
44
|
};
|
|
45
45
|
export declare type StructAbi = {
|
|
46
46
|
members: (AbiEntry & {
|
|
@@ -62,3 +62,13 @@ export declare type CompiledContract = {
|
|
|
62
62
|
export declare type CompressedCompiledContract = Omit<CompiledContract, 'program'> & {
|
|
63
63
|
program: CompressedProgram;
|
|
64
64
|
};
|
|
65
|
+
export declare type Struct = {
|
|
66
|
+
type: 'struct';
|
|
67
|
+
[k: string]: BigNumberish;
|
|
68
|
+
};
|
|
69
|
+
export declare type Args = {
|
|
70
|
+
[inputName: string]: BigNumberish | BigNumberish[] | ParsedStruct | ParsedStruct[];
|
|
71
|
+
};
|
|
72
|
+
export declare type ParsedStruct = {
|
|
73
|
+
[key: string]: BigNumberish | ParsedStruct;
|
|
74
|
+
};
|
package/utils/transaction.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ParsedStruct } from '../
|
|
2
|
-
import { Call } from '../types';
|
|
1
|
+
import { Call, ParsedStruct } from '../types';
|
|
3
2
|
/**
|
|
4
3
|
* Transforms a list of Calls, each with their own calldata, into
|
|
5
4
|
* two arrays: one with the entrypoints, and one with the concatenated calldata.
|
package/contract.d.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { Provider } from './provider';
|
|
2
|
-
import { BlockIdentifier } from './provider/utils';
|
|
3
|
-
import { Abi, Signature, StructAbi } from './types';
|
|
4
|
-
import { BigNumberish } from './utils/number';
|
|
5
|
-
export declare type Struct = {
|
|
6
|
-
type: 'struct';
|
|
7
|
-
[k: string]: BigNumberish;
|
|
8
|
-
};
|
|
9
|
-
export declare type ParsedStruct = {
|
|
10
|
-
[key: string]: BigNumberish | ParsedStruct;
|
|
11
|
-
};
|
|
12
|
-
export declare type Args = {
|
|
13
|
-
[inputName: string]: BigNumberish | BigNumberish[] | ParsedStruct | ParsedStruct[];
|
|
14
|
-
};
|
|
15
|
-
export declare class Contract {
|
|
16
|
-
connectedTo: string | null;
|
|
17
|
-
abi: Abi;
|
|
18
|
-
structs: {
|
|
19
|
-
[name: string]: StructAbi;
|
|
20
|
-
};
|
|
21
|
-
provider: Provider;
|
|
22
|
-
/**
|
|
23
|
-
* Contract class to handle contract methods
|
|
24
|
-
*
|
|
25
|
-
* @param abi - Abi of the contract object
|
|
26
|
-
* @param address (optional) - address to connect to
|
|
27
|
-
*/
|
|
28
|
-
constructor(abi: Abi, address?: string | null, provider?: Provider);
|
|
29
|
-
/**
|
|
30
|
-
* Saves the address of the contract deployed on network that will be used for interaction
|
|
31
|
-
*
|
|
32
|
-
* @param address - address of the contract
|
|
33
|
-
* @returns Contract
|
|
34
|
-
*/
|
|
35
|
-
connect(address: string): Contract;
|
|
36
|
-
/**
|
|
37
|
-
* Validates if all arguments that are passed to the method are corresponding to the ones in the abi
|
|
38
|
-
*
|
|
39
|
-
* @param type - type of the method
|
|
40
|
-
* @param method - name of the method
|
|
41
|
-
* @param args - arguments that are passed to the method
|
|
42
|
-
*/
|
|
43
|
-
private validateMethodAndArgs;
|
|
44
|
-
/**
|
|
45
|
-
* Deep parse of the object that has been passed to the method
|
|
46
|
-
*
|
|
47
|
-
* @param element - element that needs to be parsed
|
|
48
|
-
* @param type - name of the method
|
|
49
|
-
* @return {string | string[]} - parsed arguments in format that contract is expecting
|
|
50
|
-
*/
|
|
51
|
-
private parseCalldataObject;
|
|
52
|
-
/**
|
|
53
|
-
* Parse of the response elements that are converted to Object (Struct) by using the abi
|
|
54
|
-
*
|
|
55
|
-
* @param responseIterator - iterator of the response
|
|
56
|
-
* @param type - type of the struct
|
|
57
|
-
* @return {BigNumberish | ParsedStruct} - parsed arguments in format that contract is expecting
|
|
58
|
-
*/
|
|
59
|
-
private parseResponseStruct;
|
|
60
|
-
/**
|
|
61
|
-
* Parse one field of the calldata by using input field from the abi for that method
|
|
62
|
-
*
|
|
63
|
-
* @param args - value of the field
|
|
64
|
-
* @param input - input(field) information from the abi that will be used to parse the data
|
|
65
|
-
* @return {string | string[]} - parsed arguments in format that contract is expecting
|
|
66
|
-
*/
|
|
67
|
-
private parsCalldataField;
|
|
68
|
-
/**
|
|
69
|
-
* Parse the calldata by using input fields from the abi for that method
|
|
70
|
-
*
|
|
71
|
-
* @param args - arguments passed the the method
|
|
72
|
-
* @param inputs - list of inputs(fields) that are in the abi
|
|
73
|
-
* @return {Calldata} - parsed arguments in format that contract is expecting
|
|
74
|
-
*/
|
|
75
|
-
private compileCalldata;
|
|
76
|
-
/**
|
|
77
|
-
* Parse elements of the response and structuring them into one field by using output property from the abi for that method
|
|
78
|
-
*
|
|
79
|
-
* @param responseIterator - iterator of the response
|
|
80
|
-
* @param output - output(field) information from the abi that will be used to parse the data
|
|
81
|
-
* @return - parsed response corresponding to the abi structure of the field
|
|
82
|
-
*/
|
|
83
|
-
private parseResponseField;
|
|
84
|
-
/**
|
|
85
|
-
* Parse elements of the response array and structuring them into response object
|
|
86
|
-
*
|
|
87
|
-
* @param method - method name
|
|
88
|
-
* @param response - response from the method
|
|
89
|
-
* @return - parsed response corresponding to the abi
|
|
90
|
-
*/
|
|
91
|
-
private parseResponse;
|
|
92
|
-
invoke(
|
|
93
|
-
method: string,
|
|
94
|
-
args?: Args,
|
|
95
|
-
signature?: Signature
|
|
96
|
-
): Promise<import('./types').AddTransactionResponse>;
|
|
97
|
-
call(method: string, args?: Args, blockIdentifier?: BlockIdentifier): Promise<Args>;
|
|
98
|
-
}
|
package/dist/contract.d.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { Provider } from './provider';
|
|
2
|
-
import { BlockIdentifier } from './provider/utils';
|
|
3
|
-
import { Abi, Signature, StructAbi } from './types';
|
|
4
|
-
import { BigNumberish } from './utils/number';
|
|
5
|
-
export declare type Struct = {
|
|
6
|
-
type: 'struct';
|
|
7
|
-
[k: string]: BigNumberish;
|
|
8
|
-
};
|
|
9
|
-
export declare type ParsedStruct = {
|
|
10
|
-
[key: string]: BigNumberish | ParsedStruct;
|
|
11
|
-
};
|
|
12
|
-
export declare type Args = {
|
|
13
|
-
[inputName: string]: BigNumberish | BigNumberish[] | ParsedStruct | ParsedStruct[];
|
|
14
|
-
};
|
|
15
|
-
export declare class Contract {
|
|
16
|
-
connectedTo: string | null;
|
|
17
|
-
abi: Abi;
|
|
18
|
-
structs: {
|
|
19
|
-
[name: string]: StructAbi;
|
|
20
|
-
};
|
|
21
|
-
provider: Provider;
|
|
22
|
-
/**
|
|
23
|
-
* Contract class to handle contract methods
|
|
24
|
-
*
|
|
25
|
-
* @param abi - Abi of the contract object
|
|
26
|
-
* @param address (optional) - address to connect to
|
|
27
|
-
*/
|
|
28
|
-
constructor(abi: Abi, address?: string | null, provider?: Provider);
|
|
29
|
-
/**
|
|
30
|
-
* Saves the address of the contract deployed on network that will be used for interaction
|
|
31
|
-
*
|
|
32
|
-
* @param address - address of the contract
|
|
33
|
-
* @returns Contract
|
|
34
|
-
*/
|
|
35
|
-
connect(address: string): Contract;
|
|
36
|
-
/**
|
|
37
|
-
* Validates if all arguments that are passed to the method are corresponding to the ones in the abi
|
|
38
|
-
*
|
|
39
|
-
* @param type - type of the method
|
|
40
|
-
* @param method - name of the method
|
|
41
|
-
* @param args - arguments that are passed to the method
|
|
42
|
-
*/
|
|
43
|
-
private validateMethodAndArgs;
|
|
44
|
-
/**
|
|
45
|
-
* Deep parse of the object that has been passed to the method
|
|
46
|
-
*
|
|
47
|
-
* @param element - element that needs to be parsed
|
|
48
|
-
* @param type - name of the method
|
|
49
|
-
* @return {string | string[]} - parsed arguments in format that contract is expecting
|
|
50
|
-
*/
|
|
51
|
-
private parseCalldataObject;
|
|
52
|
-
/**
|
|
53
|
-
* Parse of the response elements that are converted to Object (Struct) by using the abi
|
|
54
|
-
*
|
|
55
|
-
* @param responseIterator - iterator of the response
|
|
56
|
-
* @param type - type of the struct
|
|
57
|
-
* @return {BigNumberish | ParsedStruct} - parsed arguments in format that contract is expecting
|
|
58
|
-
*/
|
|
59
|
-
private parseResponseStruct;
|
|
60
|
-
/**
|
|
61
|
-
* Parse one field of the calldata by using input field from the abi for that method
|
|
62
|
-
*
|
|
63
|
-
* @param args - value of the field
|
|
64
|
-
* @param input - input(field) information from the abi that will be used to parse the data
|
|
65
|
-
* @return {string | string[]} - parsed arguments in format that contract is expecting
|
|
66
|
-
*/
|
|
67
|
-
private parsCalldataField;
|
|
68
|
-
/**
|
|
69
|
-
* Parse the calldata by using input fields from the abi for that method
|
|
70
|
-
*
|
|
71
|
-
* @param args - arguments passed the the method
|
|
72
|
-
* @param inputs - list of inputs(fields) that are in the abi
|
|
73
|
-
* @return {Calldata} - parsed arguments in format that contract is expecting
|
|
74
|
-
*/
|
|
75
|
-
private compileCalldata;
|
|
76
|
-
/**
|
|
77
|
-
* Parse elements of the response and structuring them into one field by using output property from the abi for that method
|
|
78
|
-
*
|
|
79
|
-
* @param responseIterator - iterator of the response
|
|
80
|
-
* @param output - output(field) information from the abi that will be used to parse the data
|
|
81
|
-
* @return - parsed response corresponding to the abi structure of the field
|
|
82
|
-
*/
|
|
83
|
-
private parseResponseField;
|
|
84
|
-
/**
|
|
85
|
-
* Parse elements of the response array and structuring them into response object
|
|
86
|
-
*
|
|
87
|
-
* @param method - method name
|
|
88
|
-
* @param response - response from the method
|
|
89
|
-
* @return - parsed response corresponding to the abi
|
|
90
|
-
*/
|
|
91
|
-
private parseResponse;
|
|
92
|
-
invoke(method: string, args?: Args, signature?: Signature): Promise<import("./types").AddTransactionResponse>;
|
|
93
|
-
call(method: string, args?: Args, blockIdentifier?: BlockIdentifier): Promise<Args>;
|
|
94
|
-
}
|