@ottochain/sdk 2.3.0 → 2.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/dist/cjs/apps/compute/index.js +33 -0
- package/dist/cjs/apps/compute/state-machines/compute-rule110.js +164 -0
- package/dist/cjs/apps/compute/state-machines/index.js +9 -0
- package/dist/cjs/apps/contracts/index.js +16 -9
- package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +134 -161
- package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +192 -170
- package/dist/cjs/apps/contracts/state-machines/contract-universal.js +46 -58
- package/dist/cjs/apps/corporate/index.js +2 -2
- package/dist/cjs/apps/corporate/state-machines/corp-board.js +500 -456
- package/dist/cjs/apps/corporate/state-machines/corp-entity.js +487 -361
- package/dist/cjs/apps/corporate/state-machines/corp-securities.js +769 -576
- package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +567 -557
- package/dist/cjs/apps/governance/index.js +21 -21
- package/dist/cjs/apps/governance/state-machines/dao-multisig.js +188 -209
- package/dist/cjs/apps/governance/state-machines/dao-reputation.js +181 -228
- package/dist/cjs/apps/governance/state-machines/dao-single.js +105 -88
- package/dist/cjs/apps/governance/state-machines/dao-token.js +199 -227
- package/dist/cjs/apps/governance/state-machines/governance-simple.js +231 -231
- package/dist/cjs/apps/governance/state-machines/governance-universal.js +64 -64
- package/dist/cjs/apps/identity/constants.js +55 -22
- package/dist/cjs/apps/identity/index.js +28 -12
- package/dist/cjs/apps/identity/state-machines/identity-agent.js +124 -158
- package/dist/cjs/apps/identity/state-machines/identity-oracle.js +158 -173
- package/dist/cjs/apps/identity/state-machines/identity-registry.js +262 -0
- package/dist/cjs/apps/identity/state-machines/identity-universal.js +51 -57
- package/dist/cjs/apps/identity/state-machines/index.js +3 -1
- package/dist/cjs/apps/index.js +22 -8
- package/dist/cjs/apps/lending/assets.js +247 -0
- package/dist/cjs/apps/lending/credit-scoring.js +87 -0
- package/dist/cjs/apps/lending/eligibility.js +105 -0
- package/dist/cjs/apps/lending/index.js +91 -0
- package/dist/cjs/apps/lending/state-machines/index.js +9 -0
- package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +433 -0
- package/dist/cjs/apps/markets/index.js +22 -12
- package/dist/cjs/apps/markets/state-machines/market-auction.js +116 -134
- package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +131 -141
- package/dist/cjs/apps/markets/state-machines/market-group-buy.js +163 -184
- package/dist/cjs/apps/markets/state-machines/market-prediction.js +226 -233
- package/dist/cjs/apps/markets/state-machines/market-universal.js +65 -80
- package/dist/cjs/apps/oracles/index.js +3 -3
- package/dist/cjs/apps/privacy/index.js +67 -0
- package/dist/cjs/apps/privacy/state-machines/index.js +17 -0
- package/dist/cjs/apps/privacy/state-machines/mixer-ddhRing.js +286 -0
- package/dist/cjs/apps/privacy/state-machines/note-pool.js +476 -0
- package/dist/cjs/apps/staked-pool/assets.js +103 -0
- package/dist/cjs/apps/staked-pool/base.js +498 -0
- package/dist/cjs/apps/staked-pool/consumer.js +55 -0
- package/dist/cjs/apps/staked-pool/index.js +83 -0
- package/dist/cjs/apps/staked-pool/state-machines/index.js +12 -0
- package/dist/cjs/apps/staked-pool/state-machines/staked-pool-base.js +49 -0
- package/dist/cjs/apps/staked-pool/state-machines/staked-pool-oracle.js +131 -0
- package/dist/cjs/errors.js +3 -3
- package/dist/cjs/generated/google/protobuf/struct.js +5 -5
- package/dist/cjs/generated/google/protobuf/timestamp.js +1 -1
- package/dist/cjs/generated/index.js +11 -7
- package/dist/cjs/generated/openapi.js +6 -0
- package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +51 -51
- package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +20 -21
- package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +14 -14
- package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +5 -5
- package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +125 -131
- package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +108 -108
- package/dist/cjs/generated/ottochain/v1/common.js +5 -5
- package/dist/cjs/generated/ottochain/v1/fiber.js +44 -6
- package/dist/cjs/generated/ottochain/v1/messages.js +1 -1
- package/dist/cjs/generated/ottochain/v1/records.js +1 -1
- package/dist/cjs/index.js +58 -7
- package/dist/cjs/openapi.js +2 -0
- package/dist/cjs/ottochain/drop-nulls.js +1 -2
- package/dist/cjs/ottochain/genesis-manifest.js +17 -11
- package/dist/cjs/ottochain/index.js +23 -13
- package/dist/cjs/ottochain/metagraph-client.js +81 -16
- package/dist/cjs/ottochain/snapshot.js +13 -16
- package/dist/cjs/ottochain/transaction.js +67 -14
- package/dist/cjs/ottochain/types.js +16 -2
- package/dist/cjs/privacy/index.js +14 -0
- package/dist/cjs/privacy/sealed-bid.js +213 -0
- package/dist/cjs/privacy/shield-app.js +131 -0
- package/dist/cjs/schema/effects.js +156 -0
- package/dist/cjs/schema/fiber-app.js +150 -15
- package/dist/cjs/schema/guard-lint.js +343 -0
- package/dist/cjs/schema/guards.js +246 -0
- package/dist/cjs/signing.js +80 -0
- package/dist/cjs/templates/asset-policy.js +190 -0
- package/dist/cjs/templates/index.js +86 -0
- package/dist/cjs/templates/machine.js +130 -0
- package/dist/cjs/templates/migration.js +39 -0
- package/dist/cjs/templates/state-shape.js +38 -0
- package/dist/cjs/types.js +2 -3
- package/dist/cjs/validation.js +9 -11
- package/dist/cjs/verify.js +9 -4
- package/dist/cjs/zk/commit.js +53 -0
- package/dist/cjs/zk/guard.js +107 -0
- package/dist/cjs/zk/index.js +48 -0
- package/dist/cjs/zk/preimage.js +37 -0
- package/dist/cjs/zk/prover.js +87 -0
- package/dist/cjs/zk/registry.js +62 -0
- package/dist/cjs/zk/types.js +28 -0
- package/dist/cjs/zk/witness.js +19 -0
- package/dist/esm/apps/compute/index.js +29 -0
- package/dist/esm/apps/compute/state-machines/compute-rule110.js +161 -0
- package/dist/esm/apps/compute/state-machines/index.js +5 -0
- package/dist/esm/apps/contracts/index.js +9 -5
- package/dist/esm/apps/contracts/state-machines/contract-agreement.js +135 -162
- package/dist/esm/apps/contracts/state-machines/contract-escrow.js +193 -171
- package/dist/esm/apps/contracts/state-machines/contract-universal.js +47 -59
- package/dist/esm/apps/corporate/index.js +2 -2
- package/dist/esm/apps/corporate/state-machines/corp-board.js +501 -457
- package/dist/esm/apps/corporate/state-machines/corp-entity.js +488 -362
- package/dist/esm/apps/corporate/state-machines/corp-securities.js +770 -577
- package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +568 -558
- package/dist/esm/apps/governance/index.js +10 -10
- package/dist/esm/apps/governance/state-machines/dao-multisig.js +189 -210
- package/dist/esm/apps/governance/state-machines/dao-reputation.js +182 -229
- package/dist/esm/apps/governance/state-machines/dao-single.js +106 -89
- package/dist/esm/apps/governance/state-machines/dao-token.js +200 -228
- package/dist/esm/apps/governance/state-machines/governance-simple.js +232 -232
- package/dist/esm/apps/governance/state-machines/governance-universal.js +65 -65
- package/dist/esm/apps/identity/constants.js +52 -21
- package/dist/esm/apps/identity/index.js +14 -9
- package/dist/esm/apps/identity/state-machines/identity-agent.js +125 -159
- package/dist/esm/apps/identity/state-machines/identity-oracle.js +159 -174
- package/dist/esm/apps/identity/state-machines/identity-registry.js +259 -0
- package/dist/esm/apps/identity/state-machines/identity-universal.js +52 -58
- package/dist/esm/apps/identity/state-machines/index.js +1 -0
- package/dist/esm/apps/index.js +9 -5
- package/dist/esm/apps/lending/assets.js +231 -0
- package/dist/esm/apps/lending/credit-scoring.js +81 -0
- package/dist/esm/apps/lending/eligibility.js +99 -0
- package/dist/esm/apps/lending/index.js +69 -0
- package/dist/esm/apps/lending/state-machines/index.js +5 -0
- package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +430 -0
- package/dist/esm/apps/markets/index.js +11 -7
- package/dist/esm/apps/markets/state-machines/market-auction.js +117 -135
- package/dist/esm/apps/markets/state-machines/market-crowdfund.js +132 -142
- package/dist/esm/apps/markets/state-machines/market-group-buy.js +164 -185
- package/dist/esm/apps/markets/state-machines/market-prediction.js +227 -234
- package/dist/esm/apps/markets/state-machines/market-universal.js +66 -81
- package/dist/esm/apps/oracles/index.js +3 -3
- package/dist/esm/apps/privacy/index.js +56 -0
- package/dist/esm/apps/privacy/state-machines/index.js +6 -0
- package/dist/esm/apps/privacy/state-machines/mixer-ddhRing.js +282 -0
- package/dist/esm/apps/privacy/state-machines/note-pool.js +470 -0
- package/dist/esm/apps/staked-pool/assets.js +91 -0
- package/dist/esm/apps/staked-pool/base.js +493 -0
- package/dist/esm/apps/staked-pool/consumer.js +49 -0
- package/dist/esm/apps/staked-pool/index.js +60 -0
- package/dist/esm/apps/staked-pool/state-machines/index.js +6 -0
- package/dist/esm/apps/staked-pool/state-machines/staked-pool-base.js +46 -0
- package/dist/esm/apps/staked-pool/state-machines/staked-pool-oracle.js +127 -0
- package/dist/esm/generated/google/protobuf/struct.js +1 -1
- package/dist/esm/generated/google/protobuf/timestamp.js +1 -1
- package/dist/esm/generated/index.js +9 -5
- package/dist/esm/generated/openapi.js +5 -0
- package/dist/esm/generated/ottochain/apps/contracts/v1/contract.js +47 -47
- package/dist/esm/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
- package/dist/esm/generated/ottochain/apps/governance/v1/governance.js +1 -1
- package/dist/esm/generated/ottochain/apps/identity/v1/attestation.js +1 -1
- package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +115 -121
- package/dist/esm/generated/ottochain/apps/markets/v1/market.js +101 -101
- package/dist/esm/generated/ottochain/v1/common.js +1 -1
- package/dist/esm/generated/ottochain/v1/fiber.js +40 -2
- package/dist/esm/generated/ottochain/v1/messages.js +1 -1
- package/dist/esm/generated/ottochain/v1/records.js +1 -1
- package/dist/esm/index.js +28 -3
- package/dist/esm/openapi.js +1 -0
- package/dist/esm/ottochain/genesis-manifest.js +15 -9
- package/dist/esm/ottochain/index.js +2 -3
- package/dist/esm/ottochain/metagraph-client.js +81 -16
- package/dist/esm/ottochain/snapshot.js +6 -8
- package/dist/esm/ottochain/transaction.js +51 -3
- package/dist/esm/ottochain/types.js +15 -1
- package/dist/esm/privacy/index.js +6 -0
- package/dist/esm/privacy/sealed-bid.js +209 -0
- package/dist/esm/privacy/shield-app.js +127 -0
- package/dist/esm/schema/effects.js +145 -0
- package/dist/esm/schema/fiber-app.js +139 -8
- package/dist/esm/schema/guard-lint.js +337 -0
- package/dist/esm/schema/guards.js +228 -0
- package/dist/esm/signing.js +74 -0
- package/dist/esm/templates/asset-policy.js +182 -0
- package/dist/esm/templates/index.js +41 -0
- package/dist/esm/templates/machine.js +125 -0
- package/dist/esm/templates/migration.js +34 -0
- package/dist/esm/templates/state-shape.js +34 -0
- package/dist/esm/validation.js +1 -3
- package/dist/esm/verify.js +8 -2
- package/dist/esm/zk/commit.js +44 -0
- package/dist/esm/zk/guard.js +99 -0
- package/dist/esm/zk/index.js +19 -0
- package/dist/esm/zk/preimage.js +30 -0
- package/dist/esm/zk/prover.js +82 -0
- package/dist/esm/zk/registry.js +55 -0
- package/dist/esm/zk/types.js +25 -0
- package/dist/esm/zk/witness.js +15 -0
- package/dist/types/apps/compute/index.d.ts +176 -0
- package/dist/types/apps/compute/state-machines/compute-rule110.d.ts +157 -0
- package/dist/types/apps/compute/state-machines/index.d.ts +5 -0
- package/dist/types/apps/contracts/index.d.ts +81 -221
- package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +23 -98
- package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +49 -115
- package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +4 -4
- package/dist/types/apps/corporate/index.d.ts +1176 -440
- package/dist/types/apps/corporate/state-machines/corp-board.d.ts +271 -135
- package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +279 -74
- package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +373 -149
- package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +252 -80
- package/dist/types/apps/governance/index.d.ts +368 -470
- package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +92 -107
- package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +61 -85
- package/dist/types/apps/governance/state-machines/dao-single.d.ts +25 -47
- package/dist/types/apps/governance/state-machines/dao-token.d.ts +79 -68
- package/dist/types/apps/governance/state-machines/governance-simple.d.ts +95 -125
- package/dist/types/apps/governance/state-machines/governance-universal.d.ts +6 -6
- package/dist/types/apps/identity/constants.d.ts +33 -5
- package/dist/types/apps/identity/index.d.ts +415 -131
- package/dist/types/apps/identity/state-machines/identity-agent.d.ts +23 -23
- package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +27 -98
- package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
- package/dist/types/apps/identity/state-machines/identity-universal.d.ts +4 -4
- package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
- package/dist/types/apps/index.d.ts +9 -5
- package/dist/types/apps/lending/assets.d.ts +258 -0
- package/dist/types/apps/lending/credit-scoring.d.ts +80 -0
- package/dist/types/apps/lending/eligibility.d.ts +83 -0
- package/dist/types/apps/lending/index.d.ts +556 -0
- package/dist/types/apps/lending/state-machines/index.d.ts +5 -0
- package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +536 -0
- package/dist/types/apps/markets/index.d.ts +181 -276
- package/dist/types/apps/markets/state-machines/market-auction.d.ts +25 -49
- package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +35 -53
- package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +35 -61
- package/dist/types/apps/markets/state-machines/market-prediction.d.ts +65 -86
- package/dist/types/apps/markets/state-machines/market-universal.d.ts +12 -12
- package/dist/types/apps/oracles/index.d.ts +1 -1
- package/dist/types/apps/privacy/index.d.ts +328 -0
- package/dist/types/apps/privacy/state-machines/index.d.ts +6 -0
- package/dist/types/apps/privacy/state-machines/mixer-ddhRing.d.ts +337 -0
- package/dist/types/apps/privacy/state-machines/note-pool.d.ts +196 -0
- package/dist/types/apps/staked-pool/assets.d.ts +53 -0
- package/dist/types/apps/staked-pool/base.d.ts +80 -0
- package/dist/types/apps/staked-pool/consumer.d.ts +29 -0
- package/dist/types/apps/staked-pool/index.d.ts +51 -0
- package/dist/types/apps/staked-pool/state-machines/index.d.ts +6 -0
- package/dist/types/apps/staked-pool/state-machines/staked-pool-base.d.ts +8 -0
- package/dist/types/apps/staked-pool/state-machines/staked-pool-oracle.d.ts +34 -0
- package/dist/types/generated/index.d.ts +5 -5
- package/dist/types/generated/openapi.d.ts +1270 -0
- package/dist/types/generated/ottochain/apps/contracts/v1/contract.d.ts +5 -5
- package/dist/types/generated/ottochain/apps/identity/v1/identity.d.ts +12 -12
- package/dist/types/generated/ottochain/apps/markets/v1/market.d.ts +11 -11
- package/dist/types/generated/ottochain/v1/fiber.d.ts +7 -0
- package/dist/types/index.d.ts +7 -3
- package/dist/types/openapi.d.ts +24 -0
- package/dist/types/ottochain/genesis-manifest.d.ts +11 -5
- package/dist/types/ottochain/index.d.ts +5 -6
- package/dist/types/ottochain/metagraph-client.d.ts +49 -7
- package/dist/types/ottochain/snapshot.d.ts +6 -6
- package/dist/types/ottochain/transaction.d.ts +41 -1
- package/dist/types/ottochain/types.d.ts +336 -31
- package/dist/types/privacy/index.d.ts +6 -0
- package/dist/types/privacy/sealed-bid.d.ts +348 -0
- package/dist/types/privacy/shield-app.d.ts +48 -0
- package/dist/types/schema/effects.d.ts +141 -0
- package/dist/types/schema/fiber-app.d.ts +282 -2
- package/dist/types/schema/guard-lint.d.ts +111 -0
- package/dist/types/schema/guards.d.ts +146 -0
- package/dist/types/signing.d.ts +45 -0
- package/dist/types/templates/asset-policy.d.ts +119 -0
- package/dist/types/templates/index.d.ts +26 -0
- package/dist/types/templates/machine.d.ts +139 -0
- package/dist/types/templates/migration.d.ts +34 -0
- package/dist/types/templates/state-shape.d.ts +30 -0
- package/dist/types/validation.d.ts +22 -217
- package/dist/types/verify.d.ts +4 -0
- package/dist/types/zk/commit.d.ts +28 -0
- package/dist/types/zk/guard.d.ts +46 -0
- package/dist/types/zk/index.d.ts +19 -0
- package/dist/types/zk/preimage.d.ts +10 -0
- package/dist/types/zk/prover.d.ts +34 -0
- package/dist/types/zk/registry.d.ts +34 -0
- package/dist/types/zk/types.d.ts +33 -0
- package/dist/types/zk/witness.d.ts +40 -0
- package/package.json +47 -15
- package/dist/cjs/ottochain/normalize.js +0 -186
- package/dist/esm/ottochain/normalize.js +0 -179
- package/dist/types/ottochain/normalize.d.ts +0 -79
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staked-pool BASE factory — a reusable staked-epoch-pool lifecycle skeleton.
|
|
3
|
+
*
|
|
4
|
+
* Lifecycle: FORMING → COLLECTING → SETTLED → COLLECTING (reset) … → CLOSED.
|
|
5
|
+
* FORMING (initial) — accepting stake/join; registry bound; not yet running epochs.
|
|
6
|
+
* COLLECTING — epoch open; participants submit datapoints/votes.
|
|
7
|
+
* SETTLED — result published; entitlement ledger credited; result readable cross-fiber.
|
|
8
|
+
* CLOSED (final) — wound down; stakes + unclaimed rewards still withdrawable/claimable.
|
|
9
|
+
*
|
|
10
|
+
* The base composes EXISTING SDK primitives only:
|
|
11
|
+
* - `signerIsParty` (authority gate), `actorIsSigner`/`actorHasEntry` (effect-key↔signer coupling),
|
|
12
|
+
* `signerHasReputationVia` (the #24 dynamic-dep reputation-gated join), `actorNotInArray` (array dedup),
|
|
13
|
+
* `depInState` (cross-fiber consumer read — used by the consumer, not the pool itself) — `src/schema/guards.ts`.
|
|
14
|
+
* - `addDependency` (#24 bind), `transferAsset` (whole-instance custody move) — `src/schema/effects.ts`.
|
|
15
|
+
*
|
|
16
|
+
* Value model (design §2.1, §4 — resolved):
|
|
17
|
+
* - Submissions are an APPEND-ONLY ARRAY of `{ addr, value }` records (no map-keyed-by-address, because
|
|
18
|
+
* there is no `(array,int)` element-index op). Append is `merge[state.submissions, [record]]` — verified.
|
|
19
|
+
* - finalize emits ZERO asset transfers: it publishes `result` and records the in-consensus address set
|
|
20
|
+
* into `inConsensus` (the entitlement ledger). No reward map-fold (a map-valued `reduce` accumulator is
|
|
21
|
+
* rejected by the VM — `isPrimitive` guard in `opReduce`); entitlement is membership in `inConsensus`.
|
|
22
|
+
* - reward = PER-CLAIM on a shared fungible: `claim_reward` moves ONE whole reward instance the pool holds
|
|
23
|
+
* to a verified, in-consensus, not-yet-claimed signer, and marks `claimed[addr] = true`. ≤1 transfer.
|
|
24
|
+
* - withdraw_stake / hard-slash each emit exactly ONE whole `_transferAsset` ⇒ never the 32-cap.
|
|
25
|
+
*
|
|
26
|
+
* Multi-`from` arms are SPLIT into one transition per source state (chain `from` is a single string):
|
|
27
|
+
* stake_and_join ×2, claim_reward ×2, withdraw_stake ×2, close ×3.
|
|
28
|
+
*/
|
|
29
|
+
import { defineFiberApp } from '../../schema/fiber-app.js';
|
|
30
|
+
import { signerIsParty, actorIsSigner, signerHasReputationVia, actorNotInArray } from '../../schema/guards.js';
|
|
31
|
+
import { addDependency, transferAsset, toWallet } from '../../schema/effects.js';
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Shared guard fragments (composed from the canonical builders)
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
/** event.agent is among the verified signers (proofs[].address). */
|
|
36
|
+
const isSigner = () => actorIsSigner('event.agent');
|
|
37
|
+
/** event.agent is a verified signer AND a key in the flat membership map `state.participants`. */
|
|
38
|
+
const isJoinedParticipant = () => ({
|
|
39
|
+
and: [isSigner(), { has: [{ var: 'state.participants' }, { var: 'event.agent' }] }],
|
|
40
|
+
});
|
|
41
|
+
/** The submit window is still open: $ordinal <= epochStartedAt + epochLength. */
|
|
42
|
+
const withinEpochWindow = () => ({
|
|
43
|
+
'<=': [{ var: '$ordinal' }, { '+': [{ var: 'state.epochStartedAt' }, { var: 'state.epochLength' }] }],
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* H5 stake-reality: the pool actually holds `event.stakeAssetId` with `amount >= state.stakeAmount`.
|
|
47
|
+
* `heldAssets` is injected keyed by assetId and is BY CONSTRUCTION only the assets this fiber holds.
|
|
48
|
+
*/
|
|
49
|
+
const poolHoldsStake = () => ({
|
|
50
|
+
and: [
|
|
51
|
+
{ has: [{ var: 'heldAssets' }, { var: 'event.stakeAssetId' }] },
|
|
52
|
+
{
|
|
53
|
+
'>=': [
|
|
54
|
+
{
|
|
55
|
+
get: [{ get: [{ var: 'heldAssets' }, { var: 'event.stakeAssetId' }] }, 'amount'],
|
|
56
|
+
},
|
|
57
|
+
{ var: 'state.stakeAmount' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
// Base transition bodies (parameterized by `from`/`to` for the split arms)
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
const dep0 = { dependencies: [] };
|
|
66
|
+
/** bind_registry FORMING→FORMING — #24 genesis bind site; MUST precede all reputation-gated joins. */
|
|
67
|
+
function bindRegistryArm() {
|
|
68
|
+
return {
|
|
69
|
+
from: 'FORMING',
|
|
70
|
+
to: 'FORMING',
|
|
71
|
+
eventName: 'bind_registry',
|
|
72
|
+
guard: signerIsParty('state.authority'),
|
|
73
|
+
// Only effect: bind the identity registry so machines.<registryId> is readable NEXT transition (#24).
|
|
74
|
+
effect: {
|
|
75
|
+
merge: [{ var: 'state' }, { ...addDependency({ var: 'state.registryId' }) }],
|
|
76
|
+
},
|
|
77
|
+
...dep0,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* stake_and_join {from}→{from} — reputation-gated join + stake-custody VERIFICATION (H5).
|
|
82
|
+
* actorIsSigner is load-bearing: it pins the written participant key to the verified signer (anti-S1).
|
|
83
|
+
*/
|
|
84
|
+
function stakeAndJoinArm(state) {
|
|
85
|
+
return {
|
|
86
|
+
from: state,
|
|
87
|
+
to: state,
|
|
88
|
+
eventName: 'stake_and_join',
|
|
89
|
+
guard: {
|
|
90
|
+
and: [
|
|
91
|
+
isSigner(), // anti-S1: the written key == verified signer
|
|
92
|
+
{ '===': [{ var: 'event.stakeAmount' }, { var: 'state.stakeAmount' }] },
|
|
93
|
+
{
|
|
94
|
+
'!': [{ has: [{ var: 'state.participants' }, { var: 'event.agent' }] }],
|
|
95
|
+
}, // dedup
|
|
96
|
+
poolHoldsStake(), // H5
|
|
97
|
+
signerHasReputationVia('state.registryId', 'state.minReputation'), // #24 reputation gate
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
effect: {
|
|
101
|
+
merge: [
|
|
102
|
+
{ var: 'state' },
|
|
103
|
+
{
|
|
104
|
+
participants: {
|
|
105
|
+
set: [{ var: 'state.participants' }, { var: 'event.agent' }, true],
|
|
106
|
+
},
|
|
107
|
+
stakes: {
|
|
108
|
+
set: [{ var: 'state.stakes' }, { var: 'event.agent' }, { var: 'event.stakeAmount' }],
|
|
109
|
+
},
|
|
110
|
+
stakeAssetIds: {
|
|
111
|
+
set: [{ var: 'state.stakeAssetIds' }, { var: 'event.agent' }, { var: 'event.stakeAssetId' }],
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
...dep0,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/** open_first_epoch FORMING→COLLECTING — authority opens epoch 1. */
|
|
120
|
+
function openFirstEpochArm() {
|
|
121
|
+
return {
|
|
122
|
+
from: 'FORMING',
|
|
123
|
+
to: 'COLLECTING',
|
|
124
|
+
eventName: 'open_first_epoch',
|
|
125
|
+
guard: signerIsParty('state.authority'),
|
|
126
|
+
effect: {
|
|
127
|
+
merge: [
|
|
128
|
+
{ var: 'state' },
|
|
129
|
+
{
|
|
130
|
+
status: 'COLLECTING',
|
|
131
|
+
epoch: 1,
|
|
132
|
+
epochStartedAt: { var: '$ordinal' },
|
|
133
|
+
submissions: [],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
...dep0,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
/** reset_epoch SETTLED→COLLECTING — authority advances the epoch; clears submissions + inConsensus + claimed. */
|
|
141
|
+
function resetEpochArm() {
|
|
142
|
+
return {
|
|
143
|
+
from: 'SETTLED',
|
|
144
|
+
to: 'COLLECTING',
|
|
145
|
+
eventName: 'reset_epoch',
|
|
146
|
+
guard: signerIsParty('state.authority'),
|
|
147
|
+
effect: {
|
|
148
|
+
merge: [
|
|
149
|
+
{ var: 'state' },
|
|
150
|
+
{
|
|
151
|
+
status: 'COLLECTING',
|
|
152
|
+
epoch: { '+': [{ var: 'state.epoch' }, 1] },
|
|
153
|
+
epochStartedAt: { var: '$ordinal' },
|
|
154
|
+
submissions: [],
|
|
155
|
+
inConsensus: [],
|
|
156
|
+
claimed: {},
|
|
157
|
+
},
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
...dep0,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* submit COLLECTING→COLLECTING — append one `{addr,value}` datapoint. OVERRIDABLE per specialization.
|
|
165
|
+
* Guard = joined participant (signer-pinned) AND within window AND not-yet-submitted-this-epoch (array dedup).
|
|
166
|
+
*/
|
|
167
|
+
export function defaultSubmitArm() {
|
|
168
|
+
return {
|
|
169
|
+
from: 'COLLECTING',
|
|
170
|
+
to: 'COLLECTING',
|
|
171
|
+
eventName: 'submit',
|
|
172
|
+
guard: {
|
|
173
|
+
and: [isJoinedParticipant(), withinEpochWindow(), actorNotInArray('state.submissions', 'addr', 'event.agent')],
|
|
174
|
+
},
|
|
175
|
+
// Array append via merge (verified: merge[arr, [record]] concatenates).
|
|
176
|
+
effect: {
|
|
177
|
+
merge: [
|
|
178
|
+
{ var: 'state' },
|
|
179
|
+
{
|
|
180
|
+
submissions: {
|
|
181
|
+
merge: [{ var: 'state.submissions' }, [{ addr: { var: 'event.agent' }, value: { var: 'event.value' } }]],
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
],
|
|
185
|
+
},
|
|
186
|
+
...dep0,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* claim_reward {from}→{from} — pull ONE whole reward instance for an in-consensus, not-yet-claimed entitlement.
|
|
191
|
+
* Reward = per-claim on a shared fungible: the pool transfers one held reward instance to the claimant.
|
|
192
|
+
*/
|
|
193
|
+
function claimRewardArm(state) {
|
|
194
|
+
return {
|
|
195
|
+
from: state,
|
|
196
|
+
to: state,
|
|
197
|
+
eventName: 'claim_reward',
|
|
198
|
+
guard: {
|
|
199
|
+
and: [
|
|
200
|
+
isSigner(), // anti-S1: recipient/claimed key == verified signer
|
|
201
|
+
{
|
|
202
|
+
some: [{ var: 'state.inConsensus' }, { '===': [{ var: '' }, { var: 'event.agent' }] }],
|
|
203
|
+
}, // entitled
|
|
204
|
+
{ '!': [{ has: [{ var: 'state.claimed' }, { var: 'event.agent' }] }] }, // not already claimed
|
|
205
|
+
{ has: [{ var: 'heldAssets' }, { var: 'event.rewardAssetId' }] }, // pool holds the named instance
|
|
206
|
+
],
|
|
207
|
+
},
|
|
208
|
+
effect: {
|
|
209
|
+
merge: [
|
|
210
|
+
{ var: 'state' },
|
|
211
|
+
{
|
|
212
|
+
claimed: {
|
|
213
|
+
set: [{ var: 'state.claimed' }, { var: 'event.agent' }, true],
|
|
214
|
+
},
|
|
215
|
+
...transferAsset([
|
|
216
|
+
{
|
|
217
|
+
assetId: { var: 'event.rewardAssetId' },
|
|
218
|
+
recipient: toWallet({ var: 'event.agent' }),
|
|
219
|
+
},
|
|
220
|
+
]),
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
},
|
|
224
|
+
...dep0,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* withdraw_stake {from}→{from} — participant reclaims their staked instance (ONE whole transfer).
|
|
229
|
+
* H4: the `_transferAsset.assetId` read of `stakeAssetIds[agent]` and the sibling `unset` BOTH see the
|
|
230
|
+
* PRE-MERGE state (verified) — so reading-then-unsetting in one merge is correct, not a strand.
|
|
231
|
+
*/
|
|
232
|
+
function withdrawStakeArm(state) {
|
|
233
|
+
return {
|
|
234
|
+
from: state,
|
|
235
|
+
to: state,
|
|
236
|
+
eventName: 'withdraw_stake',
|
|
237
|
+
guard: {
|
|
238
|
+
and: [isSigner(), { has: [{ var: 'state.stakeAssetIds' }, { var: 'event.agent' }] }],
|
|
239
|
+
},
|
|
240
|
+
effect: {
|
|
241
|
+
merge: [
|
|
242
|
+
{ var: 'state' },
|
|
243
|
+
{
|
|
244
|
+
stakes: { set: [{ var: 'state.stakes' }, { var: 'event.agent' }, 0] },
|
|
245
|
+
stakeAssetIds: {
|
|
246
|
+
unset: [{ var: 'state.stakeAssetIds' }, { var: 'event.agent' }],
|
|
247
|
+
},
|
|
248
|
+
...transferAsset([
|
|
249
|
+
{
|
|
250
|
+
assetId: {
|
|
251
|
+
get: [{ var: 'state.stakeAssetIds' }, { var: 'event.agent' }],
|
|
252
|
+
}, // pre-merge read (H4)
|
|
253
|
+
recipient: toWallet({ var: 'event.agent' }),
|
|
254
|
+
},
|
|
255
|
+
]),
|
|
256
|
+
},
|
|
257
|
+
],
|
|
258
|
+
},
|
|
259
|
+
...dep0,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
/** close {from}→CLOSED — authority winds the pool down. Stakes/rewards remain withdrawable/claimable. */
|
|
263
|
+
function closeArm(state) {
|
|
264
|
+
return {
|
|
265
|
+
from: state,
|
|
266
|
+
to: 'CLOSED',
|
|
267
|
+
eventName: 'close',
|
|
268
|
+
guard: signerIsParty('state.authority'),
|
|
269
|
+
effect: {
|
|
270
|
+
merge: [{ var: 'state' }, { status: 'CLOSED', closedAt: { var: '$ordinal' } }],
|
|
271
|
+
},
|
|
272
|
+
...dep0,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
// ---------------------------------------------------------------------------
|
|
276
|
+
// Shared schemas
|
|
277
|
+
// ---------------------------------------------------------------------------
|
|
278
|
+
const baseCreateSchema = {
|
|
279
|
+
required: [
|
|
280
|
+
'authority',
|
|
281
|
+
'registryId',
|
|
282
|
+
'minReputation',
|
|
283
|
+
'stakePolicy',
|
|
284
|
+
'stakeAmount',
|
|
285
|
+
'quorum',
|
|
286
|
+
'epochLength',
|
|
287
|
+
'outlierBound',
|
|
288
|
+
'rewardPerEpoch',
|
|
289
|
+
],
|
|
290
|
+
properties: {
|
|
291
|
+
authority: {
|
|
292
|
+
type: 'address',
|
|
293
|
+
description: 'Pool authority (opens/resets/closes epochs).',
|
|
294
|
+
immutable: true,
|
|
295
|
+
},
|
|
296
|
+
registryId: {
|
|
297
|
+
type: 'uuid',
|
|
298
|
+
description: 'Identity-registry fiber id, bound via _addDependency (#24).',
|
|
299
|
+
immutable: true,
|
|
300
|
+
},
|
|
301
|
+
minReputation: {
|
|
302
|
+
type: 'integer',
|
|
303
|
+
description: 'Join reputation bar (signerHasReputationVia).',
|
|
304
|
+
immutable: true,
|
|
305
|
+
},
|
|
306
|
+
stakePolicy: {
|
|
307
|
+
type: 'string',
|
|
308
|
+
description: 'Asset policy name of the stake token.',
|
|
309
|
+
immutable: true,
|
|
310
|
+
},
|
|
311
|
+
stakeAmount: {
|
|
312
|
+
type: 'integer',
|
|
313
|
+
description: 'Required stake (minor units); checked vs heldAssets (H5).',
|
|
314
|
+
immutable: true,
|
|
315
|
+
},
|
|
316
|
+
quorum: {
|
|
317
|
+
type: 'integer',
|
|
318
|
+
description: 'Min submissions to finalize.',
|
|
319
|
+
immutable: true,
|
|
320
|
+
},
|
|
321
|
+
epochLength: {
|
|
322
|
+
type: 'integer',
|
|
323
|
+
description: 'Ordinals per epoch (submit window).',
|
|
324
|
+
immutable: true,
|
|
325
|
+
},
|
|
326
|
+
outlierBound: {
|
|
327
|
+
type: 'integer',
|
|
328
|
+
description: '|x - center| <= bound ⇒ in-consensus.',
|
|
329
|
+
immutable: true,
|
|
330
|
+
},
|
|
331
|
+
rewardPerEpoch: {
|
|
332
|
+
type: 'integer',
|
|
333
|
+
description: 'Informational per-epoch reward budget.',
|
|
334
|
+
immutable: true,
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
const baseStateSchema = {
|
|
339
|
+
properties: {
|
|
340
|
+
status: { type: 'string', computed: true },
|
|
341
|
+
epoch: { type: 'integer', computed: true },
|
|
342
|
+
epochStartedAt: { type: 'integer', computed: true },
|
|
343
|
+
authority: { type: 'address', immutable: true },
|
|
344
|
+
registryId: { type: 'uuid', immutable: true },
|
|
345
|
+
minReputation: { type: 'integer', immutable: true },
|
|
346
|
+
stakePolicy: { type: 'string', immutable: true },
|
|
347
|
+
stakeAmount: { type: 'integer', immutable: true },
|
|
348
|
+
quorum: { type: 'integer', immutable: true },
|
|
349
|
+
epochLength: { type: 'integer', immutable: true },
|
|
350
|
+
outlierBound: { type: 'integer', immutable: true },
|
|
351
|
+
rewardPerEpoch: { type: 'integer', immutable: true },
|
|
352
|
+
participants: {
|
|
353
|
+
type: 'object',
|
|
354
|
+
computed: true,
|
|
355
|
+
description: '{ <addr>: true } flat membership.',
|
|
356
|
+
},
|
|
357
|
+
stakes: {
|
|
358
|
+
type: 'object',
|
|
359
|
+
computed: true,
|
|
360
|
+
description: '{ <addr>: int } staked amount.',
|
|
361
|
+
},
|
|
362
|
+
stakeAssetIds: {
|
|
363
|
+
type: 'object',
|
|
364
|
+
computed: true,
|
|
365
|
+
description: '{ <addr>: uuid } staked instance.',
|
|
366
|
+
},
|
|
367
|
+
submissions: {
|
|
368
|
+
type: 'array',
|
|
369
|
+
computed: true,
|
|
370
|
+
description: "[ {addr,value} ] this epoch's datapoints.",
|
|
371
|
+
},
|
|
372
|
+
inConsensus: {
|
|
373
|
+
type: 'array',
|
|
374
|
+
computed: true,
|
|
375
|
+
description: "Last epoch's rewarded addresses (entitlement ledger).",
|
|
376
|
+
},
|
|
377
|
+
claimed: {
|
|
378
|
+
type: 'object',
|
|
379
|
+
computed: true,
|
|
380
|
+
description: '{ <addr>: true } reward already claimed this epoch.',
|
|
381
|
+
},
|
|
382
|
+
result: {
|
|
383
|
+
type: 'object',
|
|
384
|
+
computed: true,
|
|
385
|
+
nullable: true,
|
|
386
|
+
description: 'Last finalized published result.',
|
|
387
|
+
},
|
|
388
|
+
closedAt: { type: 'integer', computed: true },
|
|
389
|
+
},
|
|
390
|
+
};
|
|
391
|
+
/**
|
|
392
|
+
* Genesis state — EVERY map init'd to `{}` and EVERY array to `[]` so reads stay total (M1: `has`/`get`
|
|
393
|
+
* on null hard-error). `epoch`/`epochStartedAt` are 0 until `open_first_epoch`.
|
|
394
|
+
*/
|
|
395
|
+
export const baseInitialStateData = {
|
|
396
|
+
status: 'FORMING',
|
|
397
|
+
epoch: 0,
|
|
398
|
+
epochStartedAt: 0,
|
|
399
|
+
participants: {},
|
|
400
|
+
stakes: {},
|
|
401
|
+
stakeAssetIds: {},
|
|
402
|
+
submissions: [],
|
|
403
|
+
inConsensus: [],
|
|
404
|
+
claimed: {},
|
|
405
|
+
result: null,
|
|
406
|
+
};
|
|
407
|
+
const baseStates = {
|
|
408
|
+
FORMING: {
|
|
409
|
+
id: 'FORMING',
|
|
410
|
+
isFinal: false,
|
|
411
|
+
metadata: {
|
|
412
|
+
label: 'Forming',
|
|
413
|
+
description: 'Accepting stake/join; registry bound; no epoch yet.',
|
|
414
|
+
category: 'initial',
|
|
415
|
+
},
|
|
416
|
+
},
|
|
417
|
+
COLLECTING: {
|
|
418
|
+
id: 'COLLECTING',
|
|
419
|
+
isFinal: false,
|
|
420
|
+
metadata: {
|
|
421
|
+
label: 'Collecting',
|
|
422
|
+
description: 'Epoch open; participants submit datapoints.',
|
|
423
|
+
category: 'active',
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
SETTLED: {
|
|
427
|
+
id: 'SETTLED',
|
|
428
|
+
isFinal: false,
|
|
429
|
+
metadata: {
|
|
430
|
+
label: 'Settled',
|
|
431
|
+
description: 'Result published; entitlement ledger credited; readable cross-fiber.',
|
|
432
|
+
category: 'pending',
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
CLOSED: {
|
|
436
|
+
id: 'CLOSED',
|
|
437
|
+
isFinal: true,
|
|
438
|
+
metadata: {
|
|
439
|
+
label: 'Closed',
|
|
440
|
+
description: 'Wound down; stakes + unclaimed rewards still withdrawable/claimable.',
|
|
441
|
+
category: 'terminal',
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
};
|
|
445
|
+
/**
|
|
446
|
+
* Build a staked-pool definition from the shared base + a specialization's `submit`/`finalize` (+ extras).
|
|
447
|
+
* Emits all SPLIT multi-`from` arms; no two emitted entries share both `from` and `eventName`.
|
|
448
|
+
*/
|
|
449
|
+
export function makeStakedPoolDef(overrides) {
|
|
450
|
+
const submit = overrides.submit ?? defaultSubmitArm();
|
|
451
|
+
const transitions = [
|
|
452
|
+
bindRegistryArm(),
|
|
453
|
+
stakeAndJoinArm('FORMING'),
|
|
454
|
+
stakeAndJoinArm('COLLECTING'),
|
|
455
|
+
openFirstEpochArm(),
|
|
456
|
+
resetEpochArm(),
|
|
457
|
+
submit,
|
|
458
|
+
overrides.finalize,
|
|
459
|
+
claimRewardArm('SETTLED'),
|
|
460
|
+
claimRewardArm('CLOSED'),
|
|
461
|
+
withdrawStakeArm('SETTLED'),
|
|
462
|
+
withdrawStakeArm('CLOSED'),
|
|
463
|
+
closeArm('FORMING'),
|
|
464
|
+
closeArm('COLLECTING'),
|
|
465
|
+
closeArm('SETTLED'),
|
|
466
|
+
...(overrides.extraTransitions ?? []),
|
|
467
|
+
];
|
|
468
|
+
return defineFiberApp({
|
|
469
|
+
metadata: {
|
|
470
|
+
name: overrides.metadata.name,
|
|
471
|
+
app: 'staked-pool',
|
|
472
|
+
type: overrides.metadata.type,
|
|
473
|
+
version: overrides.metadata.version ?? '1.0.0',
|
|
474
|
+
description: overrides.metadata.description,
|
|
475
|
+
},
|
|
476
|
+
createSchema: {
|
|
477
|
+
required: baseCreateSchema.required,
|
|
478
|
+
properties: {
|
|
479
|
+
...baseCreateSchema.properties,
|
|
480
|
+
...(overrides.extraCreateProperties ?? {}),
|
|
481
|
+
},
|
|
482
|
+
},
|
|
483
|
+
stateSchema: {
|
|
484
|
+
properties: {
|
|
485
|
+
...baseStateSchema.properties,
|
|
486
|
+
...(overrides.extraStateProperties ?? {}),
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
states: { ...baseStates, ...(overrides.extraStates ?? {}) },
|
|
490
|
+
initialState: 'FORMING',
|
|
491
|
+
transitions,
|
|
492
|
+
});
|
|
493
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-fiber consumer-read helpers for a SETTLED staked/oracle pool ("pull the answer").
|
|
3
|
+
*
|
|
4
|
+
* Two-phase (#24): a consumer first BINDS the pool dependency and PINS the epoch it intends to consume
|
|
5
|
+
* (transition N), then GATES on lifecycle + epoch and READS `result` (transition N+1). The epoch pin
|
|
6
|
+
* (M4) makes the read epoch-EXACT: between bind and read the pool can cycle SETTLED→COLLECTING→SETTLED,
|
|
7
|
+
* so a bare `depInState(SETTLED)` could read a DIFFERENT epoch's answer.
|
|
8
|
+
*
|
|
9
|
+
* Verified against the VM: `machines.<poolId>.state.{epoch,result}` reads resolve, and
|
|
10
|
+
* `depInState`/the epoch-`===` gate evaluate true only for the pinned, settled epoch.
|
|
11
|
+
*/
|
|
12
|
+
import { depInState } from '../../schema/guards.js';
|
|
13
|
+
import { addDependency } from '../../schema/effects.js';
|
|
14
|
+
const machineState = (poolIdVar) => ({
|
|
15
|
+
get: [{ get: [{ var: 'machines' }, { var: poolIdVar }] }, 'state'],
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* PHASE 1 effect fragment — bind the pool dependency AND pin its current epoch into `epochField`
|
|
19
|
+
* (default `"expectedPoolEpoch"`). Spread into the consumer's `merge` effect on the bind transition.
|
|
20
|
+
* NOTE: `machines.<poolId>` is only readable AFTER a prior `_addDependency`, so the epoch pin records the
|
|
21
|
+
* value the consumer observes at bind time; on the first bind the pool dep may be unbound and the pin
|
|
22
|
+
* resolves null — bind in one transition, pin in the next if the registry/pool was not yet a dependency.
|
|
23
|
+
*/
|
|
24
|
+
export function bindAndPinPoolEpoch(poolIdVar = 'state.poolId', epochField = 'expectedPoolEpoch') {
|
|
25
|
+
return {
|
|
26
|
+
[epochField]: { get: [machineState(poolIdVar), 'epoch'] },
|
|
27
|
+
...addDependency({ var: poolIdVar }),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* PHASE 2 guard — the pool is SETTLED for the EXACT epoch the consumer pinned. Compose into the read
|
|
32
|
+
* transition's guard alongside the consumer's own auth.
|
|
33
|
+
*/
|
|
34
|
+
export function poolSettledForPinnedEpoch(poolIdVar = 'state.poolId', epochField = 'state.expectedPoolEpoch') {
|
|
35
|
+
return {
|
|
36
|
+
and: [
|
|
37
|
+
depInState(poolIdVar, 'SETTLED'),
|
|
38
|
+
{ '===': [{ get: [machineState(poolIdVar), 'epoch'] }, { var: epochField }] },
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** PHASE 2 value read — the published `result` object (use `.value` for the scalar answer). */
|
|
43
|
+
export function readPoolResult(poolIdVar = 'state.poolId') {
|
|
44
|
+
return { get: [machineState(poolIdVar), 'result'] };
|
|
45
|
+
}
|
|
46
|
+
/** PHASE 2 value read — the scalar `result.value`. */
|
|
47
|
+
export function readPoolResultValue(poolIdVar = 'state.poolId') {
|
|
48
|
+
return { get: [{ get: [machineState(poolIdVar), 'result'] }, 'value'] };
|
|
49
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Staked-pool Application — a reusable staked-epoch-pool std-lib BASE plus an oracle-pool specialization.
|
|
3
|
+
*
|
|
4
|
+
* The base is a long-lived account-layer fiber proving the chain can carry real economic coordination:
|
|
5
|
+
* registry-gated, stake-backed membership; an append-only submission array; a state-resident claim
|
|
6
|
+
* entitlement ledger (zero finalize-time transfers); and one-whole-asset claim/withdraw custody moves.
|
|
7
|
+
* The oracle specialization adds an outlier-bounded (trimmed-mean) consensus aggregation whose published
|
|
8
|
+
* answer a consumer reads cross-fiber via an epoch-pinned `depInState(SETTLED)` gate.
|
|
9
|
+
*
|
|
10
|
+
* Composes EXISTING SDK primitives only (+ two helpers added this workstream — `transferAsset`,
|
|
11
|
+
* `actorNotInArray`): `signerIsParty` / `actorIsSigner` / `signerHasReputationVia` / `depInState`
|
|
12
|
+
* (`src/schema/guards.ts`), `addDependency` / `transferAsset` (`src/schema/effects.ts`), and the lending
|
|
13
|
+
* family's asset payload builders (`src/apps/lending/assets.ts`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import {
|
|
18
|
+
* getStakedPoolDefinition,
|
|
19
|
+
* makeOraclePoolDef,
|
|
20
|
+
* stakePolicy,
|
|
21
|
+
* rewardPotPolicy,
|
|
22
|
+
* bindAndPinPoolEpoch,
|
|
23
|
+
* poolSettledForPinnedEpoch,
|
|
24
|
+
* readPoolResultValue,
|
|
25
|
+
* } from '@ottochain/sdk/apps/staked-pool';
|
|
26
|
+
*
|
|
27
|
+
* const oracle = getStakedPoolDefinition('oraclePool');
|
|
28
|
+
* const plainMean = makeOraclePoolDef({ aggregation: 'mean' });
|
|
29
|
+
* const stake = stakePolicy();
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @packageDocumentation
|
|
33
|
+
*/
|
|
34
|
+
import { stakedPoolBaseDef, stakedPoolOracleDef } from './state-machines/index.js';
|
|
35
|
+
export { stakedPoolBaseDef, stakedPoolOracleDef };
|
|
36
|
+
/** All staked-pool state machine definitions. */
|
|
37
|
+
export const STAKED_POOL_DEFINITIONS = {
|
|
38
|
+
base: stakedPoolBaseDef,
|
|
39
|
+
oraclePool: stakedPoolOracleDef,
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Get a staked-pool state machine definition by type.
|
|
43
|
+
* @param type - 'base' | 'oraclePool' (default: 'oraclePool')
|
|
44
|
+
*/
|
|
45
|
+
export function getStakedPoolDefinition(type = 'oraclePool') {
|
|
46
|
+
return STAKED_POOL_DEFINITIONS[type];
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// Factory + base building blocks (for downstream specializations)
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
export { makeStakedPoolDef, defaultSubmitArm, baseInitialStateData } from './base.js';
|
|
52
|
+
export { makeOraclePoolDef } from './state-machines/index.js';
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// Asset-subsystem integration (stake + reward policies / lifecycle drivers)
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
export { stakePolicy, rewardPotPolicy, stakeJoinOp, mintRewardInstancesOp, createAssetPolicyPayload, createMintAssetPayload, createApplyMorphismPayload, fiberHolder, walletHolder, TokenBehaviors, } from './assets.js';
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
// Cross-fiber consumer-read interface ("pull the answer", epoch-pinned)
|
|
59
|
+
// ---------------------------------------------------------------------------
|
|
60
|
+
export { bindAndPinPoolEpoch, poolSettledForPinnedEpoch, readPoolResult, readPoolResultValue } from './consumer.js';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The generic staked-pool BASE definition (`StakedPool`) — the reusable epoch-pool skeleton with a
|
|
3
|
+
* minimal pass-through `finalize` (authority settles; publishes a trivial result and an EMPTY in-consensus
|
|
4
|
+
* set, zero transfers). It is the lowest-common-denominator def; downstream apps should prefer a
|
|
5
|
+
* specialization (e.g. the oracle pool) that supplies real aggregation. Exposed for definition-validity
|
|
6
|
+
* round-tripping and as the explicit "base, unspecialized" instance.
|
|
7
|
+
*/
|
|
8
|
+
import { makeStakedPoolDef } from '../base.js';
|
|
9
|
+
/** Minimal finalize: authority settles; no aggregation, empty entitlement set, zero transfers. */
|
|
10
|
+
const baseFinalizeArm = {
|
|
11
|
+
from: 'COLLECTING',
|
|
12
|
+
to: 'SETTLED',
|
|
13
|
+
eventName: 'finalize',
|
|
14
|
+
guard: {
|
|
15
|
+
and: [
|
|
16
|
+
{ in: [{ var: 'state.authority' }, { map: [{ var: 'proofs' }, { var: 'address' }] }] },
|
|
17
|
+
{ '>=': [{ count: [{ var: 'state.submissions' }] }, { var: 'state.quorum' }] },
|
|
18
|
+
],
|
|
19
|
+
},
|
|
20
|
+
effect: {
|
|
21
|
+
merge: [
|
|
22
|
+
{ var: 'state' },
|
|
23
|
+
{
|
|
24
|
+
status: 'SETTLED',
|
|
25
|
+
inConsensus: [],
|
|
26
|
+
claimed: {},
|
|
27
|
+
result: {
|
|
28
|
+
submissionCount: { count: [{ var: 'state.submissions' }] },
|
|
29
|
+
epoch: { var: 'state.epoch' },
|
|
30
|
+
finalizedAt: { var: '$ordinal' },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
dependencies: [],
|
|
36
|
+
};
|
|
37
|
+
export const stakedPoolBaseDef = makeStakedPoolDef({
|
|
38
|
+
metadata: {
|
|
39
|
+
name: 'StakedPool',
|
|
40
|
+
type: 'base',
|
|
41
|
+
description: 'Generic staked-epoch-pool base (FORMING→COLLECTING→SETTLED→COLLECTING…→CLOSED): registry-gated ' +
|
|
42
|
+
'join with stake custody, append-only submissions, a state-resident claim entitlement ledger, and ' +
|
|
43
|
+
'one-whole-asset claim/withdraw transfers. Specialize `submit`/`finalize` for a concrete pool.',
|
|
44
|
+
},
|
|
45
|
+
finalize: baseFinalizeArm,
|
|
46
|
+
});
|