@xyo-network/chain-orchestration 1.19.8 → 1.19.10
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/dist/neutral/actor/ValidatorActor.d.ts +10 -31
- package/dist/neutral/actor/ValidatorActor.d.ts.map +1 -1
- package/dist/neutral/actor/index.d.ts +0 -2
- package/dist/neutral/actor/index.d.ts.map +1 -1
- package/dist/neutral/index.mjs +93 -213
- package/dist/neutral/index.mjs.map +1 -1
- package/dist/neutral/init/initWallet.d.ts +2 -0
- package/dist/neutral/init/initWallet.d.ts.map +1 -1
- package/package.json +10 -11
- package/src/actor/ValidatorActor.ts +24 -57
- package/src/actor/index.ts +0 -2
- package/src/init/initWallet.ts +10 -0
- package/dist/neutral/actor/BalanceActor.d.ts +0 -17
- package/dist/neutral/actor/BalanceActor.d.ts.map +0 -1
- package/dist/neutral/actor/MempoolActor.d.ts +0 -41
- package/dist/neutral/actor/MempoolActor.d.ts.map +0 -1
- package/src/actor/BalanceActor.ts +0 -41
- package/src/actor/MempoolActor.ts +0 -105
|
@@ -1,62 +1,46 @@
|
|
|
1
1
|
import type { Hash } from '@xylabs/sdk-js'
|
|
2
|
-
import {
|
|
3
|
-
import { AccountInstance } from '@xyo-network/account-model'
|
|
4
|
-
import { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
2
|
+
import { creatable } from '@xylabs/sdk-js'
|
|
5
3
|
import { processPendingBlocks } from '@xyo-network/chain-sdk'
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Actor,
|
|
10
|
-
ActorParams,
|
|
11
|
-
BlockViewer,
|
|
4
|
+
import type {
|
|
5
|
+
ActorParamsV3, BlockBoundWitness, BlockViewer, Config,
|
|
6
|
+
FinalizationRunner,
|
|
12
7
|
MempoolViewer,
|
|
13
8
|
} from '@xyo-network/xl1-sdk'
|
|
9
|
+
import {
|
|
10
|
+
ActorV3, BlockViewerMoniker, FinalizationRunnerMoniker,
|
|
11
|
+
MempoolViewerMoniker,
|
|
12
|
+
} from '@xyo-network/xl1-sdk'
|
|
14
13
|
|
|
15
|
-
export type ValidatorActorParams =
|
|
14
|
+
export type ValidatorActorParams = ActorParamsV3<
|
|
16
15
|
{
|
|
17
|
-
|
|
18
|
-
blockViewer: BlockViewer
|
|
19
|
-
finalizedArchivist: ArchivistInstance
|
|
20
|
-
mempoolViewer: MempoolViewer
|
|
16
|
+
config: Config
|
|
21
17
|
}>
|
|
22
18
|
|
|
23
19
|
@creatable()
|
|
24
|
-
export class ValidatorActor extends
|
|
20
|
+
export class ValidatorActor extends ActorV3<ValidatorActorParams> {
|
|
21
|
+
protected _blockViewer!: BlockViewer
|
|
22
|
+
protected _finalizationRunner!: FinalizationRunner
|
|
25
23
|
protected _lastValidatedBlock: BlockBoundWitness | undefined
|
|
26
24
|
protected _lastValidatedBlockHash: Hash | undefined
|
|
25
|
+
protected _mempoolViewer!: MempoolViewer
|
|
27
26
|
|
|
28
27
|
protected get blockViewer() {
|
|
29
|
-
return this.
|
|
28
|
+
return this._blockViewer
|
|
30
29
|
}
|
|
31
30
|
|
|
32
|
-
protected get
|
|
33
|
-
return
|
|
31
|
+
protected get finalizationRunner() {
|
|
32
|
+
return this._finalizationRunner
|
|
34
33
|
}
|
|
35
34
|
|
|
36
35
|
protected get mempoolViewer() {
|
|
37
|
-
return this.
|
|
36
|
+
return this._mempoolViewer
|
|
38
37
|
}
|
|
39
38
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
() => 'mempoolViewer is required for ValidatorActor',
|
|
46
|
-
),
|
|
47
|
-
blockViewer: assertEx(
|
|
48
|
-
params?.blockViewer,
|
|
49
|
-
() => 'blockViewer is required for ValidatorActor',
|
|
50
|
-
),
|
|
51
|
-
finalizedArchivist: assertEx(
|
|
52
|
-
params?.finalizedArchivist,
|
|
53
|
-
() => 'finalizedArchivist is required for ValidatorActor',
|
|
54
|
-
),
|
|
55
|
-
account: assertEx(
|
|
56
|
-
params?.account,
|
|
57
|
-
() => 'account is required for ValidatorActor',
|
|
58
|
-
),
|
|
59
|
-
} satisfies ValidatorActorParams
|
|
39
|
+
override async createHandler() {
|
|
40
|
+
await super.startHandler()
|
|
41
|
+
this._blockViewer = await this.locator.getInstance(BlockViewerMoniker)
|
|
42
|
+
this._finalizationRunner = await this.locator.getInstance(FinalizationRunnerMoniker)
|
|
43
|
+
this._mempoolViewer = await this.locator.getInstance(MempoolViewerMoniker)
|
|
60
44
|
}
|
|
61
45
|
|
|
62
46
|
override async startHandler(): Promise<void> {
|
|
@@ -69,26 +53,9 @@ export class ValidatorActor extends Actor<ValidatorActorParams> {
|
|
|
69
53
|
logger: this.logger,
|
|
70
54
|
mempoolViewer: this.mempoolViewer,
|
|
71
55
|
blockViewer: this.blockViewer,
|
|
72
|
-
|
|
56
|
+
finalizationRunner: this.finalizationRunner,
|
|
73
57
|
})
|
|
74
58
|
}, { ...this.context, timeBudgetLimit: 1500 })
|
|
75
59
|
}, 2000, 1500/* 500 */)
|
|
76
60
|
}
|
|
77
|
-
|
|
78
|
-
protected async slashInvalidBlock(_block: BlockBoundWitness): Promise<boolean> {
|
|
79
|
-
// TODO: Handle slashing logic
|
|
80
|
-
const slashed = await Promise.resolve(true)
|
|
81
|
-
return slashed
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
protected async validateBlock(block: BlockBoundWitness): Promise<boolean> {
|
|
85
|
-
// TODO: Validate using validation logic
|
|
86
|
-
const valid = await Promise.resolve(true)
|
|
87
|
-
// Store the last validated block and its hash
|
|
88
|
-
this._lastValidatedBlock = block
|
|
89
|
-
this._lastValidatedBlockHash = await PayloadBuilder.hash(block)
|
|
90
|
-
|
|
91
|
-
// Return the validation result
|
|
92
|
-
return valid
|
|
93
|
-
}
|
|
94
61
|
}
|
package/src/actor/index.ts
CHANGED
package/src/init/initWallet.ts
CHANGED
|
@@ -20,6 +20,11 @@ export async function initApiWallet({ config, logger }: ConfigContext) {
|
|
|
20
20
|
return await initWallet({ config, logger }, mnemonic)
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
export async function initBridgeWallet({ config, logger }: ConfigContext) {
|
|
24
|
+
const { mnemonic } = config.actors.bridge
|
|
25
|
+
return await initWallet({ config, logger }, mnemonic)
|
|
26
|
+
}
|
|
27
|
+
|
|
23
28
|
export async function initMempoolWallet({ config, logger }: ConfigContext) {
|
|
24
29
|
const { mnemonic } = config.actors.mempool
|
|
25
30
|
return await initWallet({ config, logger }, mnemonic)
|
|
@@ -34,3 +39,8 @@ export async function initRewardsRedemptionApiWallet({ config, logger }: ConfigC
|
|
|
34
39
|
const { mnemonic } = config.actors.rewardRedemption
|
|
35
40
|
return await initWallet({ config, logger }, mnemonic)
|
|
36
41
|
}
|
|
42
|
+
|
|
43
|
+
export async function initValidatorWallet({ config, logger }: ConfigContext) {
|
|
44
|
+
const { mnemonic } = config.actors.mempool
|
|
45
|
+
return await initWallet({ config, logger }, mnemonic)
|
|
46
|
+
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { AccountBalanceViewer, ActorParams, BlockViewer, Config } from '@xyo-network/xl1-sdk';
|
|
2
|
-
import { Actor } from '@xyo-network/xl1-sdk';
|
|
3
|
-
import { Mutex } from 'async-mutex';
|
|
4
|
-
export type BalanceActorParams = ActorParams<{
|
|
5
|
-
accountBalanceViewer: AccountBalanceViewer;
|
|
6
|
-
blockViewer: BlockViewer;
|
|
7
|
-
} & {
|
|
8
|
-
config: Config;
|
|
9
|
-
}>;
|
|
10
|
-
export declare class BalanceActor extends Actor<BalanceActorParams> {
|
|
11
|
-
protected _updateMutex: Mutex;
|
|
12
|
-
protected get accountBalanceViewer(): AccountBalanceViewer;
|
|
13
|
-
protected get blockViewer(): BlockViewer<"BlockViewer">;
|
|
14
|
-
startHandler(): Promise<void>;
|
|
15
|
-
protected updateBalance(): Promise<void>;
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=BalanceActor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceActor.d.ts","sourceRoot":"","sources":["../../../src/actor/BalanceActor.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,WAAW,EAAE,WAAW,EAAE,MAAM,EACjC,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC5C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAC1C;IACE,oBAAoB,EAAE,oBAAoB,CAAA;IAC1C,WAAW,EAAE,WAAW,CAAA;CACzB,GACC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAEvB,qBAAa,YAAa,SAAQ,KAAK,CAAC,kBAAkB,CAAC;IACzD,SAAS,CAAC,YAAY,QAAc;IAEpC,SAAS,KAAK,oBAAoB,yBAEjC;IAED,SAAS,KAAK,WAAW,+BAExB;IAEc,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;cAO5B,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAO/C"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { ArchivistInstance } from '@xyo-network/archivist-model';
|
|
2
|
-
import { Actor, ActorParams, MempoolRunner } from '@xyo-network/xl1-sdk';
|
|
3
|
-
export type MempoolActorParams = ActorParams<{
|
|
4
|
-
mempoolRunner: MempoolRunner;
|
|
5
|
-
pendingBlocksArchivist: ArchivistInstance;
|
|
6
|
-
pendingTransactionsArchivist: ArchivistInstance;
|
|
7
|
-
}>;
|
|
8
|
-
export declare class MempoolActor extends Actor<MempoolActorParams> {
|
|
9
|
-
private _blockTimerId;
|
|
10
|
-
private _blockTimerMutex;
|
|
11
|
-
private _transactionTimerId;
|
|
12
|
-
private _transactionTimerMutex;
|
|
13
|
-
protected get mempoolRunner(): MempoolRunner;
|
|
14
|
-
protected get pendingBlocksArchivist(): ArchivistInstance<import("@xyo-network/archivist-model").ArchivistParams<import("@xyo-network/module-model").AnyConfigSchema<import("@xyo-network/archivist-model").ArchivistConfig>>, import("@xyo-network/archivist-model").ArchivistModuleEventData, import("@xyo-network/payload-model").Payload>;
|
|
15
|
-
protected get pendingTransactionsArchivist(): ArchivistInstance<import("@xyo-network/archivist-model").ArchivistParams<import("@xyo-network/module-model").AnyConfigSchema<import("@xyo-network/archivist-model").ArchivistConfig>>, import("@xyo-network/archivist-model").ArchivistModuleEventData, import("@xyo-network/payload-model").Payload>;
|
|
16
|
-
static paramsHandler(params?: Partial<MempoolActorParams>): Promise<{
|
|
17
|
-
mempoolRunner: MempoolRunner;
|
|
18
|
-
pendingBlocksArchivist: ArchivistInstance<import("@xyo-network/archivist-model").ArchivistParams<import("@xyo-network/module-model").AnyConfigSchema<import("@xyo-network/archivist-model").ArchivistConfig>>, import("@xyo-network/archivist-model").ArchivistModuleEventData, import("@xyo-network/payload-model").Payload>;
|
|
19
|
-
pendingTransactionsArchivist: ArchivistInstance<import("@xyo-network/archivist-model").ArchivistParams<import("@xyo-network/module-model").AnyConfigSchema<import("@xyo-network/archivist-model").ArchivistConfig>>, import("@xyo-network/archivist-model").ArchivistModuleEventData, import("@xyo-network/payload-model").Payload>;
|
|
20
|
-
name?: import("@xylabs/sdk-js").CreatableName;
|
|
21
|
-
statusReporter?: import("@xylabs/sdk-js").CreatableStatusReporter<void> | undefined;
|
|
22
|
-
logger: import("@xylabs/sdk-js").Logger;
|
|
23
|
-
meterProvider?: import("@opentelemetry/api").MeterProvider;
|
|
24
|
-
traceProvider?: import("@opentelemetry/api").TracerProvider;
|
|
25
|
-
account: import("@xyo-network/account-model").AccountInstance;
|
|
26
|
-
context: import("@xyo-network/xl1-sdk").ActorContext;
|
|
27
|
-
displayName: string | (string & {
|
|
28
|
-
__baseClassName: true;
|
|
29
|
-
}) | undefined;
|
|
30
|
-
id: string | (string & {
|
|
31
|
-
__baseClassName: true;
|
|
32
|
-
});
|
|
33
|
-
}>;
|
|
34
|
-
startHandler(): Promise<void>;
|
|
35
|
-
stopHandler(): Promise<void>;
|
|
36
|
-
private restartBlockTimer;
|
|
37
|
-
private restartTransactionTimer;
|
|
38
|
-
private stopBlockTimer;
|
|
39
|
-
private stopTransactionTimer;
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=MempoolActor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MempoolActor.d.ts","sourceRoot":"","sources":["../../../src/actor/MempoolActor.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EACL,KAAK,EAAE,WAAW,EAClB,aAAa,EACd,MAAM,sBAAsB,CAAA;AAG7B,MAAM,MAAM,kBAAkB,GAAG,WAAW,CAAC;IAC3C,aAAa,EAAE,aAAa,CAAA;IAC5B,sBAAsB,EAAE,iBAAiB,CAAA;IACzC,4BAA4B,EAAE,iBAAiB,CAAA;CAChD,CAAC,CAAA;AAEF,qBACa,YAAa,SAAQ,KAAK,CAAC,kBAAkB,CAAC;IACzD,OAAO,CAAC,aAAa,CAA8C;IACnE,OAAO,CAAC,gBAAgB,CAAc;IAEtC,OAAO,CAAC,mBAAmB,CAA8C;IACzE,OAAO,CAAC,sBAAsB,CAAc;IAE5C,SAAS,KAAK,aAAa,kBAE1B;IAED,SAAS,KAAK,sBAAsB,0SAEnC;IAED,SAAS,KAAK,4BAA4B,0SAEzC;WAEqB,aAAa,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC;;;;;;;;;;;;;;;;;;IAkBzD,YAAY;IAMZ,WAAW;IAM1B,OAAO,CAAC,iBAAiB;IAYzB,OAAO,CAAC,uBAAuB;IAY/B,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,oBAAoB;CAM7B"}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { assertEx } from '@xylabs/sdk-js'
|
|
2
|
-
import type {
|
|
3
|
-
AccountBalanceViewer,
|
|
4
|
-
ActorParams, BlockViewer, Config,
|
|
5
|
-
} from '@xyo-network/xl1-sdk'
|
|
6
|
-
import { Actor } from '@xyo-network/xl1-sdk'
|
|
7
|
-
import { Mutex } from 'async-mutex'
|
|
8
|
-
|
|
9
|
-
export type BalanceActorParams = ActorParams<
|
|
10
|
-
{
|
|
11
|
-
accountBalanceViewer: AccountBalanceViewer
|
|
12
|
-
blockViewer: BlockViewer
|
|
13
|
-
}
|
|
14
|
-
& { config: Config }>
|
|
15
|
-
|
|
16
|
-
export class BalanceActor extends Actor<BalanceActorParams> {
|
|
17
|
-
protected _updateMutex = new Mutex()
|
|
18
|
-
|
|
19
|
-
protected get accountBalanceViewer() {
|
|
20
|
-
return assertEx(this.params.accountBalanceViewer, () => 'balanceService not set')
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
protected get blockViewer() {
|
|
24
|
-
return assertEx(this.params.blockViewer, () => 'blockViewer not set')
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
override async startHandler(): Promise<void> {
|
|
28
|
-
await super.startHandler()
|
|
29
|
-
this.registerTimer('BalanceTimer', async () => {
|
|
30
|
-
await this.updateBalance()
|
|
31
|
-
}, 1000, 10_000/* 1000 */)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
protected async updateBalance(): Promise<void> {
|
|
35
|
-
if (this._updateMutex.isLocked()) return
|
|
36
|
-
await this._updateMutex.runExclusive(async () => {
|
|
37
|
-
const head = await this.blockViewer.currentBlockHash()
|
|
38
|
-
await this.accountBalanceViewer.accountBalances([], { head })
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
assertEx,
|
|
3
|
-
creatable,
|
|
4
|
-
} from '@xylabs/sdk-js'
|
|
5
|
-
import { ArchivistInstance } from '@xyo-network/archivist-model'
|
|
6
|
-
import {
|
|
7
|
-
Actor, ActorParams,
|
|
8
|
-
MempoolRunner,
|
|
9
|
-
} from '@xyo-network/xl1-sdk'
|
|
10
|
-
import { Mutex } from 'async-mutex'
|
|
11
|
-
|
|
12
|
-
export type MempoolActorParams = ActorParams<{
|
|
13
|
-
mempoolRunner: MempoolRunner
|
|
14
|
-
pendingBlocksArchivist: ArchivistInstance
|
|
15
|
-
pendingTransactionsArchivist: ArchivistInstance
|
|
16
|
-
}>
|
|
17
|
-
|
|
18
|
-
@creatable()
|
|
19
|
-
export class MempoolActor extends Actor<MempoolActorParams> {
|
|
20
|
-
private _blockTimerId: ReturnType<typeof setInterval> | null = null
|
|
21
|
-
private _blockTimerMutex = new Mutex()
|
|
22
|
-
|
|
23
|
-
private _transactionTimerId: ReturnType<typeof setInterval> | null = null
|
|
24
|
-
private _transactionTimerMutex = new Mutex()
|
|
25
|
-
|
|
26
|
-
protected get mempoolRunner() {
|
|
27
|
-
return this.params.mempoolRunner
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
protected get pendingBlocksArchivist() {
|
|
31
|
-
return this.params.pendingBlocksArchivist
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
protected get pendingTransactionsArchivist() {
|
|
35
|
-
return this.params.pendingTransactionsArchivist
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
static override async paramsHandler(params?: Partial<MempoolActorParams>) {
|
|
39
|
-
return {
|
|
40
|
-
...await super.paramsHandler(params),
|
|
41
|
-
mempoolRunner: assertEx(
|
|
42
|
-
params?.mempoolRunner,
|
|
43
|
-
() => 'mempoolRunner is required for MempoolActor',
|
|
44
|
-
),
|
|
45
|
-
pendingBlocksArchivist: assertEx(
|
|
46
|
-
params?.pendingBlocksArchivist,
|
|
47
|
-
() => 'pendingBlocksArchivist is required for MempoolActor',
|
|
48
|
-
),
|
|
49
|
-
pendingTransactionsArchivist: assertEx(
|
|
50
|
-
params?.pendingTransactionsArchivist,
|
|
51
|
-
() => 'pendingTransactionsArchivist is required for MempoolActor',
|
|
52
|
-
),
|
|
53
|
-
} satisfies MempoolActorParams
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
override async startHandler() {
|
|
57
|
-
await super.startHandler()
|
|
58
|
-
// this.restartTransactionTimer()
|
|
59
|
-
this.restartBlockTimer()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
override async stopHandler() {
|
|
63
|
-
await super.stopHandler()
|
|
64
|
-
// this.stopTransactionTimer()
|
|
65
|
-
this.stopBlockTimer()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
private restartBlockTimer() {
|
|
69
|
-
this.stopBlockTimer()
|
|
70
|
-
this._blockTimerId = setInterval(() => {
|
|
71
|
-
if (this._blockTimerMutex.isLocked()) {
|
|
72
|
-
return
|
|
73
|
-
}
|
|
74
|
-
void this._blockTimerMutex.runExclusive(async () => {
|
|
75
|
-
await this.mempoolRunner.prunePendingBlocks({ batchSize: 50 })
|
|
76
|
-
})
|
|
77
|
-
}, 1000)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
private restartTransactionTimer() {
|
|
81
|
-
this.stopTransactionTimer()
|
|
82
|
-
this._transactionTimerId = setInterval(() => {
|
|
83
|
-
if (this._transactionTimerMutex.isLocked()) {
|
|
84
|
-
return
|
|
85
|
-
}
|
|
86
|
-
void this._transactionTimerMutex.runExclusive(async () => {
|
|
87
|
-
await this.mempoolRunner.prunePendingTransactions({ batchSize: 50 })
|
|
88
|
-
})
|
|
89
|
-
}, 1000)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
private stopBlockTimer() {
|
|
93
|
-
if (this._blockTimerId !== null) {
|
|
94
|
-
clearInterval(this._blockTimerId)
|
|
95
|
-
}
|
|
96
|
-
this._blockTimerId = null
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
private stopTransactionTimer() {
|
|
100
|
-
if (this._transactionTimerId !== null) {
|
|
101
|
-
clearInterval(this._transactionTimerId)
|
|
102
|
-
}
|
|
103
|
-
this._transactionTimerId = null
|
|
104
|
-
}
|
|
105
|
-
}
|