@ottochain/sdk 2.4.0 → 2.6.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 +1 -1
- package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +126 -148
- package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +153 -174
- package/dist/cjs/apps/contracts/state-machines/contract-universal.js +46 -58
- package/dist/cjs/apps/corporate/state-machines/corp-board.js +415 -481
- package/dist/cjs/apps/corporate/state-machines/corp-entity.js +368 -440
- package/dist/cjs/apps/corporate/state-machines/corp-securities.js +532 -647
- package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +499 -603
- package/dist/cjs/apps/governance/index.js +7 -7
- package/dist/cjs/apps/governance/state-machines/dao-multisig.js +170 -209
- package/dist/cjs/apps/governance/state-machines/dao-reputation.js +161 -214
- package/dist/cjs/apps/governance/state-machines/dao-single.js +92 -92
- package/dist/cjs/apps/governance/state-machines/dao-token.js +169 -223
- package/dist/cjs/apps/governance/state-machines/governance-simple.js +185 -217
- package/dist/cjs/apps/governance/state-machines/governance-universal.js +64 -64
- package/dist/cjs/apps/identity/constants.js +16 -24
- package/dist/cjs/apps/identity/index.js +1 -1
- package/dist/cjs/apps/identity/state-machines/identity-agent.js +124 -158
- package/dist/cjs/apps/identity/state-machines/identity-oracle.js +151 -169
- package/dist/cjs/apps/identity/state-machines/identity-registry.js +89 -115
- package/dist/cjs/apps/identity/state-machines/identity-universal.js +51 -57
- package/dist/cjs/apps/index.js +4 -1
- package/dist/cjs/apps/lending/assets.js +41 -17
- package/dist/cjs/apps/lending/credit-scoring.js +4 -4
- package/dist/cjs/apps/lending/eligibility.js +9 -25
- package/dist/cjs/apps/lending/index.js +1 -1
- package/dist/cjs/apps/lending/state-machines/lending-zk-loan.js +177 -156
- package/dist/cjs/apps/markets/index.js +1 -1
- package/dist/cjs/apps/markets/state-machines/market-auction.js +115 -134
- package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +122 -137
- package/dist/cjs/apps/markets/state-machines/market-group-buy.js +158 -177
- package/dist/cjs/apps/markets/state-machines/market-prediction.js +193 -227
- package/dist/cjs/apps/markets/state-machines/market-universal.js +65 -80
- package/dist/cjs/apps/oracles/index.js +1 -1
- 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/generated/google/protobuf/struct.js +1 -1
- package/dist/cjs/generated/google/protobuf/timestamp.js +1 -1
- package/dist/cjs/generated/ottochain/apps/contracts/v1/contract.js +1 -1
- package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +1 -1
- package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +1 -1
- package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +1 -1
- package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +1 -1
- package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +1 -1
- package/dist/cjs/generated/ottochain/v1/common.js +1 -1
- package/dist/cjs/generated/ottochain/v1/fiber.js +40 -2
- 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 +21 -3
- package/dist/cjs/ottochain/genesis-manifest.js +6 -0
- package/dist/cjs/ottochain/metagraph-client.js +63 -11
- package/dist/cjs/ottochain/snapshot.js +2 -4
- package/dist/cjs/ottochain/transaction.js +10 -0
- package/dist/cjs/privacy/sealed-bid.js +85 -82
- package/dist/cjs/privacy/shield-app.js +32 -32
- package/dist/cjs/schema/effects.js +145 -1
- package/dist/cjs/schema/fiber-app.js +139 -5
- package/dist/cjs/schema/guard-lint.js +3 -12
- package/dist/cjs/schema/guards.js +38 -38
- 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/validation.js +1 -3
- 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 +4 -4
- package/dist/esm/apps/contracts/state-machines/contract-agreement.js +128 -150
- package/dist/esm/apps/contracts/state-machines/contract-escrow.js +155 -176
- 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 +418 -484
- package/dist/esm/apps/corporate/state-machines/corp-entity.js +371 -443
- package/dist/esm/apps/corporate/state-machines/corp-securities.js +535 -650
- package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +502 -606
- package/dist/esm/apps/governance/index.js +10 -10
- package/dist/esm/apps/governance/state-machines/dao-multisig.js +172 -211
- package/dist/esm/apps/governance/state-machines/dao-reputation.js +163 -216
- package/dist/esm/apps/governance/state-machines/dao-single.js +94 -94
- package/dist/esm/apps/governance/state-machines/dao-token.js +171 -225
- package/dist/esm/apps/governance/state-machines/governance-simple.js +187 -219
- package/dist/esm/apps/governance/state-machines/governance-universal.js +65 -65
- package/dist/esm/apps/identity/constants.js +18 -26
- package/dist/esm/apps/identity/index.js +8 -8
- package/dist/esm/apps/identity/state-machines/identity-agent.js +125 -159
- package/dist/esm/apps/identity/state-machines/identity-oracle.js +153 -171
- package/dist/esm/apps/identity/state-machines/identity-registry.js +91 -117
- package/dist/esm/apps/identity/state-machines/identity-universal.js +52 -58
- package/dist/esm/apps/index.js +9 -6
- package/dist/esm/apps/lending/assets.js +41 -17
- package/dist/esm/apps/lending/credit-scoring.js +6 -6
- package/dist/esm/apps/lending/eligibility.js +10 -26
- package/dist/esm/apps/lending/index.js +5 -5
- package/dist/esm/apps/lending/state-machines/lending-zk-loan.js +178 -157
- package/dist/esm/apps/markets/index.js +5 -5
- package/dist/esm/apps/markets/state-machines/market-auction.js +117 -136
- package/dist/esm/apps/markets/state-machines/market-crowdfund.js +124 -139
- package/dist/esm/apps/markets/state-machines/market-group-buy.js +160 -179
- package/dist/esm/apps/markets/state-machines/market-prediction.js +195 -229
- 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/ottochain/apps/contracts/v1/contract.js +1 -1
- 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 +1 -1
- package/dist/esm/generated/ottochain/apps/markets/v1/market.js +1 -1
- 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 +10 -4
- package/dist/esm/ottochain/genesis-manifest.js +6 -0
- package/dist/esm/ottochain/metagraph-client.js +63 -11
- package/dist/esm/ottochain/snapshot.js +2 -4
- package/dist/esm/ottochain/transaction.js +8 -0
- package/dist/esm/privacy/index.js +2 -2
- package/dist/esm/privacy/sealed-bid.js +87 -84
- package/dist/esm/privacy/shield-app.js +33 -33
- package/dist/esm/schema/effects.js +137 -0
- package/dist/esm/schema/fiber-app.js +134 -5
- package/dist/esm/schema/guard-lint.js +3 -12
- package/dist/esm/schema/guards.js +36 -37
- 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/zk/index.js +4 -4
- 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 +14 -14
- package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +3 -3
- package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +3 -3
- package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +4 -4
- package/dist/types/apps/corporate/index.d.ts +162 -162
- package/dist/types/apps/corporate/state-machines/corp-board.d.ts +88 -88
- package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +14 -14
- package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +18 -18
- package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +43 -43
- package/dist/types/apps/governance/index.d.ts +81 -81
- package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +16 -16
- package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +22 -22
- package/dist/types/apps/governance/state-machines/dao-token.d.ts +21 -21
- package/dist/types/apps/governance/state-machines/governance-simple.d.ts +11 -11
- package/dist/types/apps/governance/state-machines/governance-universal.d.ts +4 -4
- package/dist/types/apps/identity/constants.d.ts +2 -2
- package/dist/types/apps/identity/index.d.ts +70 -70
- package/dist/types/apps/identity/state-machines/identity-agent.d.ts +23 -23
- package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +11 -11
- package/dist/types/apps/identity/state-machines/identity-registry.d.ts +27 -27
- package/dist/types/apps/identity/state-machines/identity-universal.d.ts +4 -4
- package/dist/types/apps/index.d.ts +9 -6
- package/dist/types/apps/lending/assets.d.ts +2 -2
- package/dist/types/apps/lending/credit-scoring.d.ts +5 -5
- package/dist/types/apps/lending/eligibility.d.ts +2 -2
- package/dist/types/apps/lending/index.d.ts +20 -12
- package/dist/types/apps/lending/state-machines/lending-zk-loan.d.ts +15 -7
- package/dist/types/apps/markets/index.d.ts +76 -76
- package/dist/types/apps/markets/state-machines/market-auction.d.ts +12 -12
- package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +19 -19
- package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +18 -18
- package/dist/types/apps/markets/state-machines/market-prediction.d.ts +15 -15
- package/dist/types/apps/markets/state-machines/market-universal.d.ts +7 -7
- 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/openapi.d.ts +13 -0
- package/dist/types/generated/ottochain/v1/fiber.d.ts +7 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/types/openapi.d.ts +4 -2
- package/dist/types/ottochain/genesis-manifest.d.ts +6 -0
- package/dist/types/ottochain/index.d.ts +1 -1
- package/dist/types/ottochain/metagraph-client.d.ts +69 -15
- package/dist/types/ottochain/transaction.d.ts +9 -1
- package/dist/types/ottochain/types.d.ts +1 -1
- package/dist/types/privacy/index.d.ts +2 -2
- package/dist/types/privacy/sealed-bid.d.ts +9 -9
- package/dist/types/privacy/shield-app.d.ts +1 -1
- package/dist/types/schema/effects.d.ts +132 -0
- package/dist/types/schema/fiber-app.d.ts +281 -0
- package/dist/types/schema/guards.d.ts +12 -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/zk/index.d.ts +4 -4
- package/package.json +31 -13
|
@@ -4,6 +4,121 @@
|
|
|
4
4
|
* TypeScript-first definitions for fiber apps. This is the source of truth —
|
|
5
5
|
* no JSON, no code generation. Import types directly.
|
|
6
6
|
*/
|
|
7
|
+
/**
|
|
8
|
+
* The wire (and authoring) tag for the `Immutable` policy VARIANT: the bare JSON string
|
|
9
|
+
* `"Immutable"`. EXACT casing, capital-I — this is the POLICY-LEVEL variant name and is
|
|
10
|
+
* DISTINCT from the `upgradePolicy` dial VALUE `"immutable"` (lowercase). The chain emits
|
|
11
|
+
* exactly this capital-I string for `Immutable`, so the SDK must too, byte-for-byte.
|
|
12
|
+
*/
|
|
13
|
+
export const IMMUTABLE_POLICY = 'Immutable';
|
|
14
|
+
/** The names of the 15 policy dials, in declaration order. Used by the projector. */
|
|
15
|
+
const FIBER_POLICY_DIALS = [
|
|
16
|
+
'selfReproducing',
|
|
17
|
+
'allowedEffects',
|
|
18
|
+
'spawnOwnerPolicy',
|
|
19
|
+
'maxGenerations',
|
|
20
|
+
'maxSpawnFanout',
|
|
21
|
+
'acceptedCallers',
|
|
22
|
+
'sealedStates',
|
|
23
|
+
'transitionPolicy',
|
|
24
|
+
'transferPolicy',
|
|
25
|
+
'dependencyPolicy',
|
|
26
|
+
'upgradePolicy',
|
|
27
|
+
'version',
|
|
28
|
+
'compatibleWith',
|
|
29
|
+
'interfaces',
|
|
30
|
+
'migrationAuthority',
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* The canonical UNCONSTRAINED policy: omission. Provided as a named export for
|
|
34
|
+
* readability at call sites — `policy: unconstrained()` documents intent, and projects
|
|
35
|
+
* to NO `policy` key (identical to leaving `policy` off entirely).
|
|
36
|
+
*/
|
|
37
|
+
export function unconstrained() {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The canonical IMMUTABLE policy: the definition is permanently locked. Projects to the
|
|
42
|
+
* bare JSON string `"Immutable"` ({@link IMMUTABLE_POLICY}), the chain's `Immutable`
|
|
43
|
+
* variant tag. Semantically equivalent to `constrained({ upgradePolicy: 'immutable' })`
|
|
44
|
+
* with no other dial set — which `constrained()`/`projectFiberPolicy()` collapse to the
|
|
45
|
+
* same string for wire parity (see {@link constrained}).
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const def = defineFiberApp({ ...spec, policy: immutable() });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export function immutable() {
|
|
53
|
+
return IMMUTABLE_POLICY;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Build a CONSTRAINED `FiberPolicy` from any subset of the 15 dials.
|
|
57
|
+
*
|
|
58
|
+
* Pass only the dials you want to set. Dials left `undefined`/`null` are dropped so the
|
|
59
|
+
* result is a clean, minimal object that serializes identically to the chain's
|
|
60
|
+
* `dropNulls`-stripped `Constrained`. If NO dial is effectively set, this returns
|
|
61
|
+
* `undefined` (an empty constraint == `Unconstrained`), which projects to no `policy`
|
|
62
|
+
* key — preserving wire parity.
|
|
63
|
+
*
|
|
64
|
+
* CANONICAL COLLAPSE: `constrained({ upgradePolicy: 'immutable' })` with NO other dial set
|
|
65
|
+
* collapses to the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}), because the chain
|
|
66
|
+
* collapses that exact `Constrained` into the `Immutable` variant. NOTE the casing: the
|
|
67
|
+
* collapse triggers on the chain's LOWERCASE upgradePolicy dial value `"immutable"`, and
|
|
68
|
+
* the result is the capital-I policy-variant tag `"Immutable"`. Signing the dials object
|
|
69
|
+
* `{ "upgradePolicy": "immutable" }` instead would diverge the canonical (the chain
|
|
70
|
+
* re-encodes it as `"Immutable"`) and break the create signature. Adding ANY other dial
|
|
71
|
+
* keeps it a dials object.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* const policy = constrained({
|
|
76
|
+
* selfReproducing: false,
|
|
77
|
+
* maxGenerations: 3,
|
|
78
|
+
* allowedEffects: ['EMIT', 'TRANSFER'],
|
|
79
|
+
* sealedStates: ['ARCHIVED'],
|
|
80
|
+
* });
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export function constrained(dials) {
|
|
84
|
+
const out = {};
|
|
85
|
+
for (const k of FIBER_POLICY_DIALS) {
|
|
86
|
+
const v = dials[k];
|
|
87
|
+
if (v === undefined || v === null)
|
|
88
|
+
continue;
|
|
89
|
+
out[k] = v;
|
|
90
|
+
}
|
|
91
|
+
const keys = Object.keys(out);
|
|
92
|
+
if (keys.length === 0)
|
|
93
|
+
return undefined;
|
|
94
|
+
// Canonical collapse: a lone LOWERCASE `upgradePolicy: 'immutable'` (the chain's dial
|
|
95
|
+
// value) IS the `Immutable` variant — emit the capital-I `"Immutable"` tag, not the dials.
|
|
96
|
+
if (keys.length === 1 && out.upgradePolicy === 'immutable')
|
|
97
|
+
return IMMUTABLE_POLICY;
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Project an authoring `policy` value onto the wire form. Returns one of:
|
|
102
|
+
* - `undefined` when the policy is (effectively) `Unconstrained` — i.e. omit the `policy`
|
|
103
|
+
* key entirely;
|
|
104
|
+
* - the bare string `"Immutable"` ({@link IMMUTABLE_POLICY}) for the `Immutable` variant
|
|
105
|
+
* (also the collapse of a lone LOWERCASE `upgradePolicy: 'immutable'`); or
|
|
106
|
+
* - the minimal `Constrained` dials object otherwise.
|
|
107
|
+
*
|
|
108
|
+
* Centralizes the omit-on-unconstrained AND the Immutable-collapse parity rules so every
|
|
109
|
+
* projection path (`toProtoDefinition`, the genesis manifest) stays consistent.
|
|
110
|
+
*/
|
|
111
|
+
export function projectFiberPolicy(policy) {
|
|
112
|
+
if (policy === undefined || policy === null)
|
|
113
|
+
return undefined;
|
|
114
|
+
// The Immutable variant is already its canonical bare-string wire form.
|
|
115
|
+
if (policy === IMMUTABLE_POLICY)
|
|
116
|
+
return IMMUTABLE_POLICY;
|
|
117
|
+
// Re-run the dial filter so a hand-built object with explicit-undefined/empty dials
|
|
118
|
+
// collapses to Unconstrained, and a lone `upgradePolicy: 'immutable'` collapses to
|
|
119
|
+
// `"Immutable"`, exactly like `constrained()` does.
|
|
120
|
+
return constrained(policy);
|
|
121
|
+
}
|
|
7
122
|
// =============================================================================
|
|
8
123
|
// Helper: defineFiberApp
|
|
9
124
|
// =============================================================================
|
|
@@ -31,11 +146,11 @@ export function defineFiberApp(definition) {
|
|
|
31
146
|
}
|
|
32
147
|
/** Get valid transitions from a given state */
|
|
33
148
|
export function getTransitionsFrom(def, state) {
|
|
34
|
-
return def.transitions.filter(t => t.from === state);
|
|
149
|
+
return def.transitions.filter((t) => t.from === state);
|
|
35
150
|
}
|
|
36
151
|
/** Get valid event names from a given state */
|
|
37
152
|
export function getEventsFrom(def, state) {
|
|
38
|
-
return getTransitionsFrom(def, state).map(t => t.eventName);
|
|
153
|
+
return getTransitionsFrom(def, state).map((t) => t.eventName);
|
|
39
154
|
}
|
|
40
155
|
/** Check if a state is final */
|
|
41
156
|
export function isFinalState(def, state) {
|
|
@@ -62,12 +177,17 @@ export function toProtoDefinition(def) {
|
|
|
62
177
|
const protoDef = {
|
|
63
178
|
states: {},
|
|
64
179
|
initialState: def.initialState,
|
|
65
|
-
transitions: def.transitions.map(t => ({
|
|
180
|
+
transitions: def.transitions.map((t) => ({
|
|
66
181
|
from: t.from,
|
|
67
182
|
to: t.to,
|
|
68
183
|
eventName: t.eventName,
|
|
69
|
-
|
|
70
|
-
|
|
184
|
+
// guard/effect are REQUIRED by the Scala `Transition` case class (no defaults). The authoring
|
|
185
|
+
// `Transition` types them OPTIONAL for ergonomics, so ALWAYS project a concrete value here — an
|
|
186
|
+
// omitted key would serialize to `undefined`, get dropped, and fail the chain's decode (HTTP 400).
|
|
187
|
+
// The defaults are the exact shapes the chain's `PublishVersionSigningCanonicalSuite` accepts:
|
|
188
|
+
// an always-true guard `{"==":[1,1]}` and an empty (no-op) effect `{}`.
|
|
189
|
+
guard: t.guard ?? { '==': [1, 1] },
|
|
190
|
+
effect: t.effect ?? {},
|
|
71
191
|
// Chain `Transition.dependencies: Set[UUID]` is REQUIRED (no Scala default), and each
|
|
72
192
|
// element must be a fiber UUID string. A `DependencySpec` object is a build-time-only
|
|
73
193
|
// authoring affordance with no wire representation (concrete dependency UUIDs are per
|
|
@@ -90,5 +210,14 @@ export function toProtoDefinition(def) {
|
|
|
90
210
|
// change the signed digest of an otherwise-identical machine), so it is deliberately NOT emitted
|
|
91
211
|
// (the chain's `StateMachineDefinition.metadata` stays absent → `None`). A caller that genuinely
|
|
92
212
|
// needs on-chain metadata sets `ProtoStateMachineDefinition.metadata` explicitly after conversion.
|
|
213
|
+
// Fiber constitution. OMIT the `policy` key entirely for `Unconstrained` (the chain
|
|
214
|
+
// emits nothing for it); emit the bare string `"Immutable"` for `Immutable`; emit a bare
|
|
215
|
+
// object of only the SET dials for `Constrained`. `projectFiberPolicy` returns `undefined`
|
|
216
|
+
// for an (effectively) unconstrained policy, so we assign only when it is a real policy —
|
|
217
|
+
// keeping the wire byte-for-byte identical to the chain's encoding.
|
|
218
|
+
const policy = projectFiberPolicy(def.policy);
|
|
219
|
+
if (policy !== undefined) {
|
|
220
|
+
protoDef.policy = policy;
|
|
221
|
+
}
|
|
93
222
|
return protoDef;
|
|
94
223
|
}
|
|
@@ -58,11 +58,7 @@ export const LINT_CODES = {
|
|
|
58
58
|
* The ONLY `$`-prefixed keys the engine injects (`ReservedKeys`). Anything else
|
|
59
59
|
* (`$timestamp`, `$now`, ...) resolves to null on chain.
|
|
60
60
|
*/
|
|
61
|
-
export const INJECTED_RESERVED_VARS = new Set([
|
|
62
|
-
'$ordinal',
|
|
63
|
-
'$lastSnapshotHash',
|
|
64
|
-
'$epochProgress',
|
|
65
|
-
]);
|
|
61
|
+
export const INJECTED_RESERVED_VARS = new Set(['$ordinal', '$lastSnapshotHash', '$epochProgress']);
|
|
66
62
|
/**
|
|
67
63
|
* Tags that LOOK like opcodes and appear in real definitions but are NOT valid
|
|
68
64
|
* JLVM operators — metakit mis-decodes each as a literal Map. These are always
|
|
@@ -117,11 +113,7 @@ export function lintGuardExpression(node, ctx, path, inDataLiteral = false) {
|
|
|
117
113
|
const ref = obj.var;
|
|
118
114
|
// The reference may be a string, or `[path, default]`, or (rarely) a
|
|
119
115
|
// nested expression; only string refs carry the patterns we check.
|
|
120
|
-
const refStr = typeof ref === 'string'
|
|
121
|
-
? ref
|
|
122
|
-
: Array.isArray(ref) && typeof ref[0] === 'string'
|
|
123
|
-
? ref[0]
|
|
124
|
-
: undefined;
|
|
116
|
+
const refStr = typeof ref === 'string' ? ref : Array.isArray(ref) && typeof ref[0] === 'string' ? ref[0] : undefined;
|
|
125
117
|
if (refStr !== undefined) {
|
|
126
118
|
// rule 1 — unknown reserved `$`-key
|
|
127
119
|
if (refStr.startsWith('$') && !INJECTED_RESERVED_VARS.has(refStr)) {
|
|
@@ -150,8 +142,7 @@ export function lintGuardExpression(node, ctx, path, inDataLiteral = false) {
|
|
|
150
142
|
});
|
|
151
143
|
}
|
|
152
144
|
// rule 3 — `witness.*` read inside a fiber transition
|
|
153
|
-
if (ctx.flagWitness &&
|
|
154
|
-
(refStr === 'witness' || refStr.startsWith('witness.'))) {
|
|
145
|
+
if (ctx.flagWitness && (refStr === 'witness' || refStr.startsWith('witness.'))) {
|
|
155
146
|
out.push({
|
|
156
147
|
app: ctx.app,
|
|
157
148
|
transition: ctx.transition,
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* replacement for `{"===":[{"var":"event.agent"}, {"var":partyVar}]}`.
|
|
18
18
|
*/
|
|
19
19
|
export const signerIsParty = (partyVar) => ({
|
|
20
|
-
in: [{ var: partyVar }, { map: [{ var:
|
|
20
|
+
in: [{ var: partyVar }, { map: [{ var: 'proofs' }, { var: 'address' }] }],
|
|
21
21
|
});
|
|
22
22
|
/** FIBER-transition authorization where ANY of the pinned parties signed (e.g. borrower OR lender). */
|
|
23
23
|
export const signerIsAnyParty = (partyVars) => ({
|
|
@@ -29,17 +29,14 @@ export const signerIsAnyParty = (partyVars) => ({
|
|
|
29
29
|
* The replay-safe replacement for `{"in":[{"var":"event.agent"}, {"var":setVar}]}`.
|
|
30
30
|
*/
|
|
31
31
|
export const signerInSet = (setVar) => ({
|
|
32
|
-
some: [
|
|
33
|
-
{ map: [{ var: "proofs" }, { var: "address" }] },
|
|
34
|
-
{ in: [{ var: "" }, { var: setVar }] },
|
|
35
|
-
],
|
|
32
|
+
some: [{ map: [{ var: 'proofs' }, { var: 'address' }] }, { in: [{ var: '' }, { var: setVar }] }],
|
|
36
33
|
});
|
|
37
34
|
/**
|
|
38
35
|
* FIBER-transition ANTI-SELF guard: NO verified signer is the pinned party (e.g. a proposal author may
|
|
39
36
|
* not vote on their own proposal). The replay-safe replacement for `{"!==":[{"var":"event.agent"}, {"var":partyVar}]}`.
|
|
40
37
|
*/
|
|
41
38
|
export const signerIsNotParty = (partyVar) => ({
|
|
42
|
-
|
|
39
|
+
'!': [signerIsParty(partyVar)],
|
|
43
40
|
});
|
|
44
41
|
/**
|
|
45
42
|
* FIBER-transition authorization / dedup over a state MAP keyed by address: at least one VERIFIED signer
|
|
@@ -50,10 +47,7 @@ export const signerIsNotParty = (partyVar) => ({
|
|
|
50
47
|
* `{"some":[{"map":[proofs,address]},{">=":[{"get":[mapVar,{"var":""}]}, N]}]}`.
|
|
51
48
|
*/
|
|
52
49
|
export const signerHasEntry = (mapVar) => ({
|
|
53
|
-
some: [
|
|
54
|
-
{ map: [{ var: "proofs" }, { var: "address" }] },
|
|
55
|
-
{ has: [{ var: mapVar }, { var: "" }] },
|
|
56
|
-
],
|
|
50
|
+
some: [{ map: [{ var: 'proofs' }, { var: 'address' }] }, { has: [{ var: mapVar }, { var: '' }] }],
|
|
57
51
|
});
|
|
58
52
|
/**
|
|
59
53
|
* ASSET-op authorization (mintPolicy / burnPolicy / MorphismSpec.guard): the address at `addressVar`
|
|
@@ -61,7 +55,7 @@ export const signerHasEntry = (mapVar) => ({
|
|
|
61
55
|
* `event` or `proofs` — it injects `signers` directly.
|
|
62
56
|
*/
|
|
63
57
|
export const assetSignerIs = (addressVar) => ({
|
|
64
|
-
in: [{ var: addressVar }, { var:
|
|
58
|
+
in: [{ var: addressVar }, { var: 'signers' }],
|
|
65
59
|
});
|
|
66
60
|
/**
|
|
67
61
|
* EFFECT-KEY BINDING: prove the event's claimed actor (`actorVar`, default `event.agent`) is a
|
|
@@ -75,7 +69,7 @@ export const assetSignerIs = (addressVar) => ({
|
|
|
75
69
|
* both signed and is authorized, and the effect can only write under that one verified key.
|
|
76
70
|
* Structurally identical to {@link signerIsParty}; named for intent + greppability at write sites.
|
|
77
71
|
*/
|
|
78
|
-
export const actorIsSigner = (actorVar =
|
|
72
|
+
export const actorIsSigner = (actorVar = 'event.agent') => signerIsParty(actorVar);
|
|
79
73
|
/**
|
|
80
74
|
* EFFECT-KEY-BINDING membership: the event's claimed actor (`actorVar`, default `event.agent`) is BOTH
|
|
81
75
|
* a CHAIN-VERIFIED signer AND a member of the pinned set `setVar` (e.g. `"state.signers"`,
|
|
@@ -86,7 +80,7 @@ export const actorIsSigner = (actorVar = "event.agent") => signerIsParty(actorVa
|
|
|
86
80
|
* verified-but-unauthorized address as the key (padding a signature/vote tally). `actorInSet` pins both
|
|
87
81
|
* to the same `actorVar`.
|
|
88
82
|
*/
|
|
89
|
-
export const actorInSet = (setVar, actorVar =
|
|
83
|
+
export const actorInSet = (setVar, actorVar = 'event.agent') => ({
|
|
90
84
|
and: [actorIsSigner(actorVar), { in: [{ var: actorVar }, { var: setVar }] }],
|
|
91
85
|
});
|
|
92
86
|
/**
|
|
@@ -98,7 +92,7 @@ export const actorInSet = (setVar, actorVar = "event.agent") => ({
|
|
|
98
92
|
* is an authorized member, closing the vote/signature-stuffing gap that bare {@link signerHasEntry}
|
|
99
93
|
* leaves open (which only proves SOME verified signer is a key, not that the written key is).
|
|
100
94
|
*/
|
|
101
|
-
export const actorHasEntry = (mapVar, actorVar =
|
|
95
|
+
export const actorHasEntry = (mapVar, actorVar = 'event.agent') => ({
|
|
102
96
|
and: [actorIsSigner(actorVar), { has: [{ var: mapVar }, { var: actorVar }] }],
|
|
103
97
|
});
|
|
104
98
|
/**
|
|
@@ -112,9 +106,9 @@ export const actorHasEntry = (mapVar, actorVar = "event.agent") => ({
|
|
|
112
106
|
*/
|
|
113
107
|
export const signerHasReputation = (repMapVar, thresholdVar) => ({
|
|
114
108
|
some: [
|
|
115
|
-
{ map: [{ var:
|
|
109
|
+
{ map: [{ var: 'proofs' }, { var: 'address' }] },
|
|
116
110
|
{
|
|
117
|
-
|
|
111
|
+
'>=': [{ get: [{ var: repMapVar }, { var: '' }] }, { var: thresholdVar }],
|
|
118
112
|
},
|
|
119
113
|
],
|
|
120
114
|
});
|
|
@@ -139,26 +133,23 @@ export const signerHasRole = (roleMapVar) => signerHasEntry(roleMapVar);
|
|
|
139
133
|
*/
|
|
140
134
|
export const signerHasReputationVia = (registryIdVar, thresholdVar) => ({
|
|
141
135
|
if: [
|
|
142
|
-
{ has: [{ var:
|
|
136
|
+
{ has: [{ var: 'machines' }, { var: registryIdVar }] },
|
|
143
137
|
{
|
|
144
138
|
some: [
|
|
145
|
-
{ map: [{ var:
|
|
139
|
+
{ map: [{ var: 'proofs' }, { var: 'address' }] },
|
|
146
140
|
{
|
|
147
|
-
|
|
141
|
+
'>=': [
|
|
148
142
|
{
|
|
149
143
|
get: [
|
|
150
144
|
{
|
|
151
145
|
get: [
|
|
152
146
|
{
|
|
153
|
-
get: [
|
|
154
|
-
{ get: [{ var: "machines" }, { var: registryIdVar }] },
|
|
155
|
-
"state",
|
|
156
|
-
],
|
|
147
|
+
get: [{ get: [{ var: 'machines' }, { var: registryIdVar }] }, 'state'],
|
|
157
148
|
},
|
|
158
|
-
|
|
149
|
+
'reputations',
|
|
159
150
|
],
|
|
160
151
|
},
|
|
161
|
-
{ var:
|
|
152
|
+
{ var: '' },
|
|
162
153
|
],
|
|
163
154
|
},
|
|
164
155
|
{ var: thresholdVar },
|
|
@@ -179,24 +170,21 @@ export const signerHasReputationVia = (registryIdVar, thresholdVar) => ({
|
|
|
179
170
|
*/
|
|
180
171
|
export const signerHasRoleVia = (registryIdVar, roleField) => ({
|
|
181
172
|
if: [
|
|
182
|
-
{ has: [{ var:
|
|
173
|
+
{ has: [{ var: 'machines' }, { var: registryIdVar }] },
|
|
183
174
|
{
|
|
184
175
|
some: [
|
|
185
|
-
{ map: [{ var:
|
|
176
|
+
{ map: [{ var: 'proofs' }, { var: 'address' }] },
|
|
186
177
|
{
|
|
187
178
|
has: [
|
|
188
179
|
{
|
|
189
180
|
get: [
|
|
190
181
|
{
|
|
191
|
-
get: [
|
|
192
|
-
{ get: [{ var: "machines" }, { var: registryIdVar }] },
|
|
193
|
-
"state",
|
|
194
|
-
],
|
|
182
|
+
get: [{ get: [{ var: 'machines' }, { var: registryIdVar }] }, 'state'],
|
|
195
183
|
},
|
|
196
184
|
roleField,
|
|
197
185
|
],
|
|
198
186
|
},
|
|
199
|
-
{ var:
|
|
187
|
+
{ var: '' },
|
|
200
188
|
],
|
|
201
189
|
},
|
|
202
190
|
],
|
|
@@ -215,14 +203,25 @@ export const signerHasRoleVia = (registryIdVar, roleField) => ({
|
|
|
215
203
|
* so a single gated transition is split into a bind step then this assert step. See
|
|
216
204
|
* docs/design/app-hardening-identity-integration.md §5–§6.
|
|
217
205
|
*/
|
|
206
|
+
/**
|
|
207
|
+
* EFFECT-KEY-BINDING dedup over an ARRAY of records: no existing element of the array at `arrayVar`
|
|
208
|
+
* (e.g. `"state.submissions"`, shaped `[ { addr, value }, … ]`) has its `field` (default `"addr"`)
|
|
209
|
+
* equal to the actor at `actorVar` (default `"event.agent"`). The array analog of the map-keyed
|
|
210
|
+
* `{"!":[has(...)]}` dedup — used where the collection is an append-only array of `{addr,…}` records
|
|
211
|
+
* (there is no `(array,string)` key check, but `none` over the array with a per-element `===` is total).
|
|
212
|
+
*
|
|
213
|
+
* The bare-element callback context inside `none` sees each record map directly, so `{get:[{var:""},field]}`
|
|
214
|
+
* is a valid `(map,string)` read. Pair with an `actorIsSigner`/`actorHasEntry` clause on the same
|
|
215
|
+
* `actorVar` (the dedup proves "not yet present", not "is the verified signer").
|
|
216
|
+
*/
|
|
217
|
+
export const actorNotInArray = (arrayVar, field = 'addr', actorVar = 'event.agent') => ({
|
|
218
|
+
none: [{ var: arrayVar }, { '===': [{ get: [{ var: '' }, field] }, { var: actorVar }] }],
|
|
219
|
+
});
|
|
218
220
|
export const depInState = (refVar, requiredState) => ({
|
|
219
221
|
if: [
|
|
220
|
-
{ has: [{ var:
|
|
222
|
+
{ has: [{ var: 'machines' }, { var: refVar }] },
|
|
221
223
|
{
|
|
222
|
-
|
|
223
|
-
{ get: [{ get: [{ var: "machines" }, { var: refVar }] }, "currentStateId"] },
|
|
224
|
-
requiredState,
|
|
225
|
-
],
|
|
224
|
+
'==': [{ get: [{ get: [{ var: 'machines' }, { var: refVar }] }, 'currentStateId'] }, requiredState],
|
|
226
225
|
},
|
|
227
226
|
false,
|
|
228
227
|
],
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset-policy preset builders (§1.1 of the SDK std-lib/templates handoff).
|
|
3
|
+
*
|
|
4
|
+
* Each builder is a PURE function that emits the exact {@link CreateAssetPolicy} wire body the chain
|
|
5
|
+
* re-derives — no `Date.now()`/`Math.random()`/`crypto.randomUUID()`; fixed inputs → fixed output. The
|
|
6
|
+
* on-chain policy `schemaHash` and `logicHash` are both `RegistryShape.AssetPolicy.computeDigest` over
|
|
7
|
+
* `behavior`/`supply`/`morphisms`/`stateShape` (no JSON-Logic body), so these presets are pure data.
|
|
8
|
+
*
|
|
9
|
+
* Hard invariants (CLAUDE.md rule #1 — the signed canonical is frozen):
|
|
10
|
+
* - `behavior` is ALWAYS summed from {@link TOKEN_BEHAVIOR_BITS} (T=16, S=8, C=4, E=2, G=1), never a
|
|
11
|
+
* magic literal int.
|
|
12
|
+
* - `morphisms` is REQUIRED on the wire (presence required, emptiness meaningful) — emit `{}` when empty,
|
|
13
|
+
* NEVER omit it.
|
|
14
|
+
* - `supply` is REQUIRED — emit `{}` when there is no supply authority, never omit it.
|
|
15
|
+
* - Absent optionals are OMITTED, never emitted as `null`/`undefined` (the chain signs over
|
|
16
|
+
* `JCS(dropNulls(payload))`).
|
|
17
|
+
*
|
|
18
|
+
* @see src/ottochain/types.ts — CreateAssetPolicy, SupplyPolicy, MorphismSpec, MorphismKind, TOKEN_BEHAVIOR_BITS
|
|
19
|
+
*/
|
|
20
|
+
import { TOKEN_BEHAVIOR_BITS, } from '../ottochain/types.js';
|
|
21
|
+
/** The default mint/burn guard the riverdale presets use: an always-true predicate `{"==":[1,1]}`. */
|
|
22
|
+
const alwaysTrue = () => ({ '==': [1, 1] });
|
|
23
|
+
/** A `PUBLIC`-visibility morphism spec (the riverdale preset visibility). Fresh object per call. */
|
|
24
|
+
const publicMorphism = () => ({ visibility: 'PUBLIC' });
|
|
25
|
+
/** Sum behavior bits from their NAMES — never a magic literal int (CLAUDE.md #1). */
|
|
26
|
+
export function sumBehavior(bits) {
|
|
27
|
+
return bits.reduce((acc, name) => acc + TOKEN_BEHAVIOR_BITS[name], 0);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Derive the default `stateShape.typeName`: strip a trailing `.asset` label, PascalCase the remainder
|
|
31
|
+
* (splitting on `.`/`-`/`_`/space), then append `State`.
|
|
32
|
+
* `rvd.asset` → `RvdState`, `goods.asset` → `GoodsState`, `capped.asset` → `CappedState`.
|
|
33
|
+
*/
|
|
34
|
+
export function defaultStateTypeName(name) {
|
|
35
|
+
const ASSET_SUFFIX = '.asset';
|
|
36
|
+
const base = name.endsWith(ASSET_SUFFIX) ? name.slice(0, -ASSET_SUFFIX.length) : name;
|
|
37
|
+
const pascal = base
|
|
38
|
+
.split(/[.\-_\s]+/)
|
|
39
|
+
.filter(Boolean)
|
|
40
|
+
.map((seg) => seg.charAt(0).toUpperCase() + seg.slice(1))
|
|
41
|
+
.join('');
|
|
42
|
+
return `${pascal}State`;
|
|
43
|
+
}
|
|
44
|
+
/** Build a {@link SupplyPolicy}, OMITTING every absent field (no `undefined`/`null` keys). */
|
|
45
|
+
function buildSupply(opts) {
|
|
46
|
+
const supply = {};
|
|
47
|
+
if (opts.maxSupply !== undefined)
|
|
48
|
+
supply.maxSupply = opts.maxSupply;
|
|
49
|
+
if (opts.mintPolicy !== undefined)
|
|
50
|
+
supply.mintPolicy = opts.mintPolicy;
|
|
51
|
+
if (opts.burnPolicy !== undefined)
|
|
52
|
+
supply.burnPolicy = opts.burnPolicy;
|
|
53
|
+
if (opts.decimals !== undefined)
|
|
54
|
+
supply.decimals = opts.decimals;
|
|
55
|
+
return supply;
|
|
56
|
+
}
|
|
57
|
+
/** Assemble the final {@link CreateAssetPolicy}, attaching `metadata` only when present. */
|
|
58
|
+
function assemble(args) {
|
|
59
|
+
const stateShape = {
|
|
60
|
+
typeName: args.stateTypeName ?? defaultStateTypeName(args.name),
|
|
61
|
+
fields: [],
|
|
62
|
+
};
|
|
63
|
+
const policy = {
|
|
64
|
+
name: args.name,
|
|
65
|
+
version: args.version,
|
|
66
|
+
behavior: args.behavior,
|
|
67
|
+
supply: args.supply,
|
|
68
|
+
morphisms: args.morphisms,
|
|
69
|
+
stateShape,
|
|
70
|
+
};
|
|
71
|
+
if (args.metadata !== undefined)
|
|
72
|
+
policy.metadata = args.metadata;
|
|
73
|
+
return policy;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fungible currency. Behavior `T|S|C = 28` (transferable + splittable + combinable). Standard morphism
|
|
77
|
+
* set TRANSFER + FRACTIONALIZE + STAKE (`stakeable`, default true) + BURN (when `burnable`), all PUBLIC.
|
|
78
|
+
*
|
|
79
|
+
* Reproduces `riverdale-economy/rvd-policy.json` exactly via
|
|
80
|
+
* `fungiblePolicy({ name: 'rvd.asset', version: '1.0.0', mintable: true, burnable: true })`.
|
|
81
|
+
*/
|
|
82
|
+
export function fungiblePolicy(p) {
|
|
83
|
+
const behavior = sumBehavior(['transferable', 'splittable', 'combinable']); // 28
|
|
84
|
+
const morphisms = {
|
|
85
|
+
TRANSFER: publicMorphism(),
|
|
86
|
+
FRACTIONALIZE: publicMorphism(),
|
|
87
|
+
};
|
|
88
|
+
if (p.stakeable !== false)
|
|
89
|
+
morphisms.STAKE = publicMorphism();
|
|
90
|
+
if (p.burnable)
|
|
91
|
+
morphisms.BURN = publicMorphism();
|
|
92
|
+
let mintPolicy;
|
|
93
|
+
if (p.mintGuard !== undefined)
|
|
94
|
+
mintPolicy = p.mintGuard;
|
|
95
|
+
else if (p.mintable)
|
|
96
|
+
mintPolicy = alwaysTrue();
|
|
97
|
+
const supply = buildSupply({
|
|
98
|
+
maxSupply: p.maxSupply,
|
|
99
|
+
mintPolicy,
|
|
100
|
+
burnPolicy: p.burnable ? alwaysTrue() : undefined,
|
|
101
|
+
decimals: p.decimals,
|
|
102
|
+
});
|
|
103
|
+
return assemble({
|
|
104
|
+
name: p.name,
|
|
105
|
+
version: p.version,
|
|
106
|
+
behavior,
|
|
107
|
+
supply,
|
|
108
|
+
morphisms,
|
|
109
|
+
stateTypeName: p.stateTypeName,
|
|
110
|
+
metadata: p.metadata,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Non-fungible token. Behavior `T = 16`, or `T|C = 20` with `combinable: true` (the riverdale
|
|
115
|
+
* `goods.asset`); `transferable: false` drops the T bit (a bound collectible). `morphisms` is `{}` by
|
|
116
|
+
* default (emitted explicitly, never omitted). Mintable by default ⇒ `supply.mintPolicy = {"==":[1,1]}`.
|
|
117
|
+
*
|
|
118
|
+
* Reproduces `riverdale-economy/goods-policy.json` exactly via
|
|
119
|
+
* `nftPolicy({ name: 'goods.asset', version: '1.0.0', combinable: true })`.
|
|
120
|
+
*/
|
|
121
|
+
export function nftPolicy(p) {
|
|
122
|
+
const bits = [];
|
|
123
|
+
if (p.transferable !== false)
|
|
124
|
+
bits.push('transferable');
|
|
125
|
+
if (p.combinable)
|
|
126
|
+
bits.push('combinable');
|
|
127
|
+
const behavior = sumBehavior(bits);
|
|
128
|
+
let mintPolicy;
|
|
129
|
+
if (p.mintGuard !== undefined)
|
|
130
|
+
mintPolicy = p.mintGuard;
|
|
131
|
+
else if (p.mintable !== false)
|
|
132
|
+
mintPolicy = alwaysTrue();
|
|
133
|
+
const supply = buildSupply({ maxSupply: p.maxSupply, mintPolicy });
|
|
134
|
+
return assemble({
|
|
135
|
+
name: p.name,
|
|
136
|
+
version: p.version,
|
|
137
|
+
behavior,
|
|
138
|
+
supply,
|
|
139
|
+
morphisms: {},
|
|
140
|
+
stateTypeName: p.stateTypeName,
|
|
141
|
+
metadata: p.metadata,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Soulbound token: non-transferable, governable only (`G = 1`; `+E = 3` when `expirable`). No TRANSFER
|
|
146
|
+
* morphism (`morphisms: {}`); minting is closed after issue (empty `supply`).
|
|
147
|
+
*/
|
|
148
|
+
export function soulboundPolicy(p) {
|
|
149
|
+
const bits = ['governable'];
|
|
150
|
+
if (p.expirable)
|
|
151
|
+
bits.push('expirable');
|
|
152
|
+
const behavior = sumBehavior(bits);
|
|
153
|
+
return assemble({
|
|
154
|
+
name: p.name,
|
|
155
|
+
version: p.version,
|
|
156
|
+
behavior,
|
|
157
|
+
supply: buildSupply({}), // mint closed after issue
|
|
158
|
+
morphisms: {}, // non-transferable: no TRANSFER morphism
|
|
159
|
+
stateTypeName: p.stateTypeName,
|
|
160
|
+
metadata: p.metadata,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Escape hatch: declare `behavior` by NAME (summed from {@link TOKEN_BEHAVIOR_BITS}, never a magic int)
|
|
165
|
+
* and pass `supply` + `morphisms` through raw. Use when no preset fits.
|
|
166
|
+
*
|
|
167
|
+
* Reproduces `riverdale-economy/capped-policy.json` exactly via
|
|
168
|
+
* `customPolicy({ name: 'capped.asset', version: '1.0.0',
|
|
169
|
+
* behavior: ['transferable', 'splittable', 'combinable'],
|
|
170
|
+
* supply: { maxSupply: 100, mintPolicy: { '==': [1, 1] } }, morphisms: {} })`.
|
|
171
|
+
*/
|
|
172
|
+
export function customPolicy(p) {
|
|
173
|
+
return assemble({
|
|
174
|
+
name: p.name,
|
|
175
|
+
version: p.version,
|
|
176
|
+
behavior: sumBehavior(p.behavior),
|
|
177
|
+
supply: p.supply,
|
|
178
|
+
morphisms: p.morphisms,
|
|
179
|
+
stateTypeName: p.stateTypeName,
|
|
180
|
+
metadata: p.metadata,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@ottochain/sdk/templates` — the fiber & asset authoring template catalog.
|
|
3
|
+
*
|
|
4
|
+
* Typed builders that emit the EXACT canonical wire shapes app authors otherwise hand-roll as raw
|
|
5
|
+
* JSON-Logic (asset policies, versioned machines, effect directives, migrations, seeded state). Every
|
|
6
|
+
* builder is additive and pure — it returns the same wire shape the chain re-derives, so a template
|
|
7
|
+
* output signs to byte-identical `JCS(dropNulls(payload))` (CLAUDE.md rule #1). Hand-rolled JSON keeps
|
|
8
|
+
* working; these just make the recurring shapes typed, named, and mistake-resistant.
|
|
9
|
+
*
|
|
10
|
+
* Origin: the fiber-ergonomics program (ottochain `docs/proposals/fiber-ergonomics/`), Phase A — the
|
|
11
|
+
* `riverdale-economy` e2e is the migration proof (each preset reproduces its checked-in golden JSON).
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* import {
|
|
15
|
+
* fungiblePolicy, machine, transition, effect, guard,
|
|
16
|
+
* transferAsset, triggers, spawn, seedState, seedFields,
|
|
17
|
+
* } from '@ottochain/sdk/templates';
|
|
18
|
+
*/
|
|
19
|
+
// ─── 1.1 Asset-policy presets ────────────────────────────────────────────────
|
|
20
|
+
// fungiblePolicy / nftPolicy / soulboundPolicy / customPolicy (+ sumBehavior, defaultStateTypeName,
|
|
21
|
+
// BehaviorBitName) — emit a `CreateAssetPolicy`; behavior is summed from TOKEN_BEHAVIOR_BITS, never a literal.
|
|
22
|
+
export * from './asset-policy.js';
|
|
23
|
+
// ─── 1.2 Versioned-machine skeleton + transition()/effect() ──────────────────
|
|
24
|
+
// machine / transition / effect (+ TransitionSpec, MachineSpec, Machine, …). The skeleton owns ONE
|
|
25
|
+
// canonical wire definition, so publish + create cannot drift (verified binding, F9).
|
|
26
|
+
export * from './machine.js';
|
|
27
|
+
// ─── 1.4 Migration helpers ───────────────────────────────────────────────────
|
|
28
|
+
// seedFields / migration — hides the bare-state-root ({"var":""}) foot-gun.
|
|
29
|
+
export * from './migration.js';
|
|
30
|
+
// ─── 1.5 State-shape-with-defaults ───────────────────────────────────────────
|
|
31
|
+
// seedState / declaredFields / StateShape — auto-seed accumulators so no field reads null (F5).
|
|
32
|
+
export * from './state-shape.js';
|
|
33
|
+
// ─── 1.3 Effect-directive builders ───────────────────────────────────────────
|
|
34
|
+
// transferAsset / triggers / spawn / emit / toFiber / toWallet / addDependency / setDependencyActive /
|
|
35
|
+
// RESERVED_EFFECT_KEYS — a typo'd directive is a TS error, not a silent state field (F4).
|
|
36
|
+
export * from '../schema/effects.js';
|
|
37
|
+
// ─── Authorization-guard builders (namespace) ────────────────────────────────
|
|
38
|
+
// `guard.signerIsParty('state.borrower')` reads as intent at the call site.
|
|
39
|
+
export * as guard from '../schema/guards.js';
|
|
40
|
+
// ─── Existing machine/policy primitives re-surfaced for one-import authoring ──
|
|
41
|
+
export { defineFiberApp, toProtoDefinition, constrained, unconstrained, immutable, projectFiberPolicy, } from '../schema/fiber-app.js';
|