@pizzaton/ton 0.0.0-stage → 0.1.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/CONTRACTS.md +239 -0
- package/README.md +481 -2
- package/dist/airdrop/index.d.mts +18 -0
- package/dist/airdrop/index.mjs +86 -0
- package/dist/connect/errors.d.mts +4 -0
- package/dist/connect/errors.mjs +21 -0
- package/dist/connect/index.d.mts +23 -0
- package/dist/connect/index.mjs +34 -0
- package/dist/contracts/catalog/index.d.mts +361 -0
- package/dist/contracts/catalog/index.mjs +403 -0
- package/dist/contracts/client.d.mts +18 -0
- package/dist/contracts/client.mjs +31 -0
- package/dist/contracts/codecs.d.mts +14 -0
- package/dist/contracts/codecs.mjs +61 -0
- package/dist/contracts/hipo.d.mts +138 -0
- package/dist/contracts/hipo.mjs +198 -0
- package/dist/contracts/index.d.mts +23 -0
- package/dist/contracts/index.mjs +20 -0
- package/dist/contracts/metadata.d.mts +38 -0
- package/dist/contracts/metadata.mjs +50 -0
- package/dist/contracts/module-client.d.mts +20 -0
- package/dist/contracts/module-client.mjs +34 -0
- package/dist/contracts/module.d.mts +8 -0
- package/dist/contracts/module.mjs +11 -0
- package/dist/contracts/wrappers/base.d.mts +18 -0
- package/dist/contracts/wrappers/base.mjs +31 -0
- package/dist/contracts/wrappers/index.d.mts +12 -0
- package/dist/contracts/wrappers/index.mjs +12 -0
- package/dist/contracts/wrappers/jvault-protocols.d.mts +206 -0
- package/dist/contracts/wrappers/jvault-protocols.mjs +432 -0
- package/dist/contracts/wrappers/jvault-support.d.mts +135 -0
- package/dist/contracts/wrappers/jvault-support.mjs +269 -0
- package/dist/contracts/wrappers/jvault.d.mts +123 -0
- package/dist/contracts/wrappers/jvault.mjs +258 -0
- package/dist/contracts/wrappers/memeland.d.mts +253 -0
- package/dist/contracts/wrappers/memeland.mjs +396 -0
- package/dist/contracts/wrappers/multix.d.mts +92 -0
- package/dist/contracts/wrappers/multix.mjs +156 -0
- package/dist/contracts/wrappers/pizzabox.d.mts +66 -0
- package/dist/contracts/wrappers/pizzabox.mjs +105 -0
- package/dist/contracts/wrappers/ton-raffles.d.mts +215 -0
- package/dist/contracts/wrappers/ton-raffles.mjs +398 -0
- package/dist/contracts/wrappers/tonresistor.d.mts +189 -0
- package/dist/contracts/wrappers/tonresistor.mjs +276 -0
- package/dist/core/address.d.mts +25 -0
- package/dist/core/address.mjs +45 -0
- package/dist/core/amount.d.mts +8 -0
- package/dist/core/amount.mjs +34 -0
- package/dist/core/bytes.d.mts +5 -0
- package/dist/core/bytes.mjs +18 -0
- package/dist/core/constants.d.mts +14 -0
- package/dist/core/constants.mjs +15 -0
- package/dist/core/errors.d.mts +9 -0
- package/dist/core/errors.mjs +16 -0
- package/dist/core/http.mjs +39 -0
- package/dist/core/index.d.mts +8 -0
- package/dist/core/index.mjs +8 -0
- package/dist/core/metadata.d.mts +12 -0
- package/dist/core/metadata.mjs +35 -0
- package/dist/core/network.d.mts +24 -0
- package/dist/core/network.mjs +41 -0
- package/dist/emulator/index.d.mts +20 -0
- package/dist/emulator/index.mjs +24 -0
- package/dist/index.d.mts +21 -0
- package/dist/index.mjs +19 -0
- package/dist/indexer/index.d.mts +90 -0
- package/dist/indexer/index.mjs +279 -0
- package/dist/jetton/details.d.mts +27 -0
- package/dist/jetton/details.mjs +116 -0
- package/dist/jetton/index.d.mts +54 -0
- package/dist/jetton/index.mjs +92 -0
- package/dist/jetton/versions.d.mts +12 -0
- package/dist/jetton/versions.mjs +50 -0
- package/dist/nft/collection.d.mts +57 -0
- package/dist/nft/collection.mjs +148 -0
- package/dist/nft/content.d.mts +34 -0
- package/dist/nft/content.mjs +142 -0
- package/dist/nft/index.d.mts +35 -0
- package/dist/nft/index.mjs +51 -0
- package/dist/nft/versions.d.mts +11 -0
- package/dist/nft/versions.mjs +29 -0
- package/dist/provider/index.d.mts +32 -0
- package/dist/provider/index.mjs +1 -0
- package/dist/react/index.d.mts +13 -0
- package/dist/react/index.mjs +48 -0
- package/dist/server/index.d.mts +11 -0
- package/dist/server/index.mjs +55 -0
- package/dist/simulation/index.d.mts +112 -0
- package/dist/simulation/index.mjs +310 -0
- package/dist/transactions/index.d.mts +33 -0
- package/dist/transactions/index.mjs +51 -0
- package/dist/vesting/index.d.mts +12 -0
- package/dist/vesting/index.mjs +25 -0
- package/dist/wallet/index.d.mts +23 -0
- package/dist/wallet/index.mjs +71 -0
- package/package.json +169 -5
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/vesting/index.d.ts
|
|
2
|
+
export interface VestingSchedule {
|
|
3
|
+
readonly totalAmount: bigint;
|
|
4
|
+
readonly startTime: number;
|
|
5
|
+
readonly cliffDuration: number;
|
|
6
|
+
readonly duration: number;
|
|
7
|
+
readonly now?: number;
|
|
8
|
+
}
|
|
9
|
+
export declare function validateVestingSchedule(schedule: VestingSchedule): void;
|
|
10
|
+
export declare function unlockedAmount(schedule: VestingSchedule, at?: number): bigint;
|
|
11
|
+
export declare function claimableAmount(schedule: VestingSchedule, releasedAmount: bigint, at?: number): bigint;
|
|
12
|
+
//#endregion
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { invariant } from "../core/errors.mjs";
|
|
2
|
+
//#region src/vesting/index.ts
|
|
3
|
+
function validateVestingSchedule(schedule) {
|
|
4
|
+
invariant(schedule.totalAmount >= 0n, "INVALID_SCHEDULE", "Total vesting amount cannot be negative");
|
|
5
|
+
invariant(Number.isSafeInteger(schedule.startTime), "INVALID_SCHEDULE", "Start time must be a safe integer");
|
|
6
|
+
if (schedule.now !== void 0) invariant(Number.isSafeInteger(schedule.now), "INVALID_SCHEDULE", "Current time must be a safe integer");
|
|
7
|
+
invariant(Number.isSafeInteger(schedule.cliffDuration) && schedule.cliffDuration >= 0, "INVALID_SCHEDULE", "Cliff duration is invalid");
|
|
8
|
+
invariant(Number.isSafeInteger(schedule.duration) && schedule.duration > 0, "INVALID_SCHEDULE", "Vesting duration must be positive");
|
|
9
|
+
invariant(schedule.cliffDuration <= schedule.duration, "INVALID_SCHEDULE", "Cliff cannot exceed vesting duration");
|
|
10
|
+
invariant(Number.isSafeInteger(schedule.startTime + schedule.duration), "INVALID_SCHEDULE", "Vesting schedule end time is out of range");
|
|
11
|
+
}
|
|
12
|
+
function unlockedAmount(schedule, at = schedule.now ?? Math.floor(Date.now() / 1e3)) {
|
|
13
|
+
validateVestingSchedule(schedule);
|
|
14
|
+
invariant(Number.isSafeInteger(at), "INVALID_SCHEDULE", "Calculation time must be a safe integer");
|
|
15
|
+
if (at < schedule.startTime + schedule.cliffDuration) return 0n;
|
|
16
|
+
const elapsed = Math.min(at - schedule.startTime, schedule.duration);
|
|
17
|
+
return schedule.totalAmount * BigInt(elapsed) / BigInt(schedule.duration);
|
|
18
|
+
}
|
|
19
|
+
function claimableAmount(schedule, releasedAmount, at) {
|
|
20
|
+
invariant(releasedAmount >= 0n && releasedAmount <= schedule.totalAmount, "INVALID_SCHEDULE", "Released amount is out of range");
|
|
21
|
+
const claimable = unlockedAmount(schedule, at) - releasedAmount;
|
|
22
|
+
return claimable > 0n ? claimable : 0n;
|
|
23
|
+
}
|
|
24
|
+
//#endregion
|
|
25
|
+
export { claimableAmount, unlockedAmount, validateVestingSchedule };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Address, Contract, ContractProvider, StateInit } from "@ton/core";
|
|
2
|
+
import { WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, WalletContractV2R1, WalletContractV2R2, WalletContractV3R1, WalletContractV3R2, WalletContractV4, WalletContractV5Beta, WalletContractV5R1 } from "@ton/ton";
|
|
3
|
+
//#region src/wallet/index.d.ts
|
|
4
|
+
export declare const TON_WALLET_VERSIONS: readonly ["v1r1", "v1r2", "v1r3", "v2r1", "v2r2", "v3r1", "v3r2", "v4", "v5beta", "v5r1"];
|
|
5
|
+
export type TonWalletVersion = (typeof TON_WALLET_VERSIONS)[number];
|
|
6
|
+
export declare const DEFAULT_TON_WALLET_VERSION: TonWalletVersion;
|
|
7
|
+
export interface TonWalletContract extends Contract {
|
|
8
|
+
readonly address: Address;
|
|
9
|
+
readonly init: StateInit;
|
|
10
|
+
readonly publicKey: Buffer;
|
|
11
|
+
getBalance(provider: ContractProvider): Promise<bigint>;
|
|
12
|
+
getSeqno(provider: ContractProvider): Promise<number>;
|
|
13
|
+
}
|
|
14
|
+
export interface TonWalletFactoryOptions {
|
|
15
|
+
readonly version?: TonWalletVersion;
|
|
16
|
+
readonly workchain?: number;
|
|
17
|
+
readonly publicKey: Buffer;
|
|
18
|
+
readonly walletId?: number;
|
|
19
|
+
readonly networkGlobalId?: -239 | -3;
|
|
20
|
+
}
|
|
21
|
+
export declare function createTonWalletContract(options: TonWalletFactoryOptions): TonWalletContract;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, WalletContractV2R1, WalletContractV2R2, WalletContractV3R1, WalletContractV3R2, WalletContractV4, WalletContractV5Beta, WalletContractV5R1 };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { WalletContractV1R1, WalletContractV1R1 as WalletContractV1R1$1, WalletContractV1R2, WalletContractV1R2 as WalletContractV1R2$1, WalletContractV1R3, WalletContractV1R3 as WalletContractV1R3$1, WalletContractV2R1, WalletContractV2R1 as WalletContractV2R1$1, WalletContractV2R2, WalletContractV2R2 as WalletContractV2R2$1, WalletContractV3R1, WalletContractV3R1 as WalletContractV3R1$1, WalletContractV3R2, WalletContractV3R2 as WalletContractV3R2$1, WalletContractV4, WalletContractV4 as WalletContractV4$1, WalletContractV5Beta, WalletContractV5Beta as WalletContractV5Beta$1, WalletContractV5R1, WalletContractV5R1 as WalletContractV5R1$1 } from "@ton/ton";
|
|
2
|
+
//#region src/wallet/index.ts
|
|
3
|
+
const TON_WALLET_VERSIONS = [
|
|
4
|
+
"v1r1",
|
|
5
|
+
"v1r2",
|
|
6
|
+
"v1r3",
|
|
7
|
+
"v2r1",
|
|
8
|
+
"v2r2",
|
|
9
|
+
"v3r1",
|
|
10
|
+
"v3r2",
|
|
11
|
+
"v4",
|
|
12
|
+
"v5beta",
|
|
13
|
+
"v5r1"
|
|
14
|
+
];
|
|
15
|
+
const DEFAULT_TON_WALLET_VERSION = "v5r1";
|
|
16
|
+
function createTonWalletContract(options) {
|
|
17
|
+
const workchain = options.workchain ?? 0;
|
|
18
|
+
const publicKey = Buffer.from(options.publicKey);
|
|
19
|
+
if (publicKey.length !== 32) throw new Error("TON wallet public keys must be exactly 32 bytes");
|
|
20
|
+
switch (options.version ?? "v5r1") {
|
|
21
|
+
case "v1r1": return WalletContractV1R1$1.create({
|
|
22
|
+
workchain,
|
|
23
|
+
publicKey
|
|
24
|
+
});
|
|
25
|
+
case "v1r2": return WalletContractV1R2$1.create({
|
|
26
|
+
workchain,
|
|
27
|
+
publicKey
|
|
28
|
+
});
|
|
29
|
+
case "v1r3": return WalletContractV1R3$1.create({
|
|
30
|
+
workchain,
|
|
31
|
+
publicKey
|
|
32
|
+
});
|
|
33
|
+
case "v2r1": return WalletContractV2R1$1.create({
|
|
34
|
+
workchain,
|
|
35
|
+
publicKey
|
|
36
|
+
});
|
|
37
|
+
case "v2r2": return WalletContractV2R2$1.create({
|
|
38
|
+
workchain,
|
|
39
|
+
publicKey
|
|
40
|
+
});
|
|
41
|
+
case "v3r1": return WalletContractV3R1$1.create({
|
|
42
|
+
workchain,
|
|
43
|
+
publicKey,
|
|
44
|
+
walletId: options.walletId
|
|
45
|
+
});
|
|
46
|
+
case "v3r2": return WalletContractV3R2$1.create({
|
|
47
|
+
workchain,
|
|
48
|
+
publicKey,
|
|
49
|
+
walletId: options.walletId
|
|
50
|
+
});
|
|
51
|
+
case "v4": return WalletContractV4$1.create({
|
|
52
|
+
workchain,
|
|
53
|
+
publicKey,
|
|
54
|
+
walletId: options.walletId
|
|
55
|
+
});
|
|
56
|
+
case "v5beta": return WalletContractV5Beta$1.create({ publicKey });
|
|
57
|
+
case "v5r1": return WalletContractV5R1$1.create({
|
|
58
|
+
publicKey,
|
|
59
|
+
walletId: {
|
|
60
|
+
networkGlobalId: options.networkGlobalId ?? -239,
|
|
61
|
+
context: {
|
|
62
|
+
walletVersion: "v5r1",
|
|
63
|
+
workchain,
|
|
64
|
+
subwalletNumber: options.walletId ?? 0
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
export { DEFAULT_TON_WALLET_VERSION, TON_WALLET_VERSIONS, WalletContractV1R1, WalletContractV1R2, WalletContractV1R3, WalletContractV2R1, WalletContractV2R2, WalletContractV3R1, WalletContractV3R2, WalletContractV4, WalletContractV5Beta, WalletContractV5R1, createTonWalletContract };
|
package/package.json
CHANGED
|
@@ -1,6 +1,170 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"name": "@pizzaton/ton",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Typed TON blockchain primitives, contract wrappers, and protocol adapters",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.mjs",
|
|
7
|
+
"module": "./dist/index.mjs",
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.mts",
|
|
12
|
+
"import": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"./airdrop": {
|
|
15
|
+
"types": "./dist/airdrop/index.d.mts",
|
|
16
|
+
"import": "./dist/airdrop/index.mjs"
|
|
17
|
+
},
|
|
18
|
+
"./core": {
|
|
19
|
+
"types": "./dist/core/index.d.mts",
|
|
20
|
+
"import": "./dist/core/index.mjs"
|
|
21
|
+
},
|
|
22
|
+
"./jetton": {
|
|
23
|
+
"types": "./dist/jetton/index.d.mts",
|
|
24
|
+
"import": "./dist/jetton/index.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./jetton/details": {
|
|
27
|
+
"types": "./dist/jetton/details.d.mts",
|
|
28
|
+
"import": "./dist/jetton/details.mjs"
|
|
29
|
+
},
|
|
30
|
+
"./nft": {
|
|
31
|
+
"types": "./dist/nft/index.d.mts",
|
|
32
|
+
"import": "./dist/nft/index.mjs"
|
|
33
|
+
},
|
|
34
|
+
"./vesting": {
|
|
35
|
+
"types": "./dist/vesting/index.d.mts",
|
|
36
|
+
"import": "./dist/vesting/index.mjs"
|
|
37
|
+
},
|
|
38
|
+
"./transactions": {
|
|
39
|
+
"types": "./dist/transactions/index.d.mts",
|
|
40
|
+
"import": "./dist/transactions/index.mjs"
|
|
41
|
+
},
|
|
42
|
+
"./provider": {
|
|
43
|
+
"types": "./dist/provider/index.d.mts",
|
|
44
|
+
"import": "./dist/provider/index.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./indexer": {
|
|
47
|
+
"types": "./dist/indexer/index.d.mts",
|
|
48
|
+
"import": "./dist/indexer/index.mjs"
|
|
49
|
+
},
|
|
50
|
+
"./connect": {
|
|
51
|
+
"types": "./dist/connect/index.d.mts",
|
|
52
|
+
"import": "./dist/connect/index.mjs"
|
|
53
|
+
},
|
|
54
|
+
"./contracts": {
|
|
55
|
+
"types": "./dist/contracts/index.d.mts",
|
|
56
|
+
"import": "./dist/contracts/index.mjs"
|
|
57
|
+
},
|
|
58
|
+
"./contracts/catalog": {
|
|
59
|
+
"types": "./dist/contracts/catalog/index.d.mts",
|
|
60
|
+
"import": "./dist/contracts/catalog/index.mjs"
|
|
61
|
+
},
|
|
62
|
+
"./contracts/hipo": {
|
|
63
|
+
"types": "./dist/contracts/hipo.d.mts",
|
|
64
|
+
"import": "./dist/contracts/hipo.mjs"
|
|
65
|
+
},
|
|
66
|
+
"./contracts/wrappers": {
|
|
67
|
+
"types": "./dist/contracts/wrappers/index.d.mts",
|
|
68
|
+
"import": "./dist/contracts/wrappers/index.mjs"
|
|
69
|
+
},
|
|
70
|
+
"./emulator": {
|
|
71
|
+
"types": "./dist/emulator/index.d.mts",
|
|
72
|
+
"import": "./dist/emulator/index.mjs"
|
|
73
|
+
},
|
|
74
|
+
"./simulation": {
|
|
75
|
+
"types": "./dist/simulation/index.d.mts",
|
|
76
|
+
"import": "./dist/simulation/index.mjs"
|
|
77
|
+
},
|
|
78
|
+
"./react": {
|
|
79
|
+
"types": "./dist/react/index.d.mts",
|
|
80
|
+
"import": "./dist/react/index.mjs"
|
|
81
|
+
},
|
|
82
|
+
"./server": {
|
|
83
|
+
"types": "./dist/server/index.d.mts",
|
|
84
|
+
"import": "./dist/server/index.mjs"
|
|
85
|
+
},
|
|
86
|
+
"./wallet": {
|
|
87
|
+
"types": "./dist/wallet/index.d.mts",
|
|
88
|
+
"import": "./dist/wallet/index.mjs"
|
|
89
|
+
},
|
|
90
|
+
"./package.json": "./package.json"
|
|
91
|
+
},
|
|
92
|
+
"files": [
|
|
93
|
+
"dist",
|
|
94
|
+
"README.md",
|
|
95
|
+
"CONTRACTS.md"
|
|
96
|
+
],
|
|
97
|
+
"sideEffects": false,
|
|
98
|
+
"repository": {
|
|
99
|
+
"type": "git",
|
|
100
|
+
"url": "git+https://github.com/PizzaTon/monorepo.git",
|
|
101
|
+
"directory": "packages/ton"
|
|
102
|
+
},
|
|
103
|
+
"bugs": {
|
|
104
|
+
"url": "https://github.com/PizzaTon/monorepo/issues"
|
|
105
|
+
},
|
|
106
|
+
"homepage": "https://github.com/PizzaTon/monorepo/tree/main/packages/ton#readme",
|
|
107
|
+
"keywords": [
|
|
108
|
+
"ton",
|
|
109
|
+
"ton-blockchain",
|
|
110
|
+
"jetton",
|
|
111
|
+
"nft",
|
|
112
|
+
"ton-connect",
|
|
113
|
+
"smart-contracts"
|
|
114
|
+
],
|
|
115
|
+
"publishConfig": {
|
|
116
|
+
"access": "public",
|
|
117
|
+
"registry": "https://registry.npmjs.org/"
|
|
118
|
+
},
|
|
119
|
+
"engines": {
|
|
120
|
+
"node": ">=20"
|
|
121
|
+
},
|
|
122
|
+
"scripts": {
|
|
123
|
+
"build": "tsdown --tsconfig tsconfig.build.json",
|
|
124
|
+
"check-types": "tsc --noEmit",
|
|
125
|
+
"lint": "biome check",
|
|
126
|
+
"test": "bun test",
|
|
127
|
+
"prepack": "npm run build",
|
|
128
|
+
"prepublishOnly": "npm run check-types && npm run lint && npm test"
|
|
129
|
+
},
|
|
130
|
+
"dependencies": {
|
|
131
|
+
"@ton/crypto": "^3.3.0",
|
|
132
|
+
"@ton/ton": "^16.3.0",
|
|
133
|
+
"@tonconnect/sdk": "^4.0.2",
|
|
134
|
+
"zod": "^4.5.4"
|
|
135
|
+
},
|
|
136
|
+
"peerDependencies": {
|
|
137
|
+
"@ton/core": "^0.63.1",
|
|
138
|
+
"@types/node": ">=20",
|
|
139
|
+
"@ton/sandbox": "^0.44.0",
|
|
140
|
+
"@ton-api/client": "^0.4.0",
|
|
141
|
+
"react": ">=18",
|
|
142
|
+
"@types/react": "^18.0.0 || ^19.0.0"
|
|
143
|
+
},
|
|
144
|
+
"peerDependenciesMeta": {
|
|
145
|
+
"@ton/sandbox": {
|
|
146
|
+
"optional": true
|
|
147
|
+
},
|
|
148
|
+
"@ton-api/client": {
|
|
149
|
+
"optional": true
|
|
150
|
+
},
|
|
151
|
+
"react": {
|
|
152
|
+
"optional": true
|
|
153
|
+
},
|
|
154
|
+
"@types/react": {
|
|
155
|
+
"optional": true
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"devDependencies": {
|
|
159
|
+
"@biomejs/biome": "^2.5.12",
|
|
160
|
+
"@ton-api/client": "^0.4.0",
|
|
161
|
+
"@ton/core": "^0.63.1",
|
|
162
|
+
"@ton/sandbox": "^0.44.0",
|
|
163
|
+
"@types/bun": "^1.4.2",
|
|
164
|
+
"@types/node": "^26.5.0",
|
|
165
|
+
"@types/react": "^19.2.18",
|
|
166
|
+
"react": "^19.2.8",
|
|
167
|
+
"tsdown": "^0.23.0",
|
|
168
|
+
"typescript": "^6.0.3"
|
|
169
|
+
}
|
|
170
|
+
}
|