@ottochain/sdk 2.6.0 → 2.7.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/lending/assets.js +11 -1
- package/dist/cjs/index.js +8 -2
- package/dist/cjs/ottochain/index.js +11 -1
- package/dist/cjs/ottochain/morphism-lint.js +99 -0
- package/dist/cjs/ottochain/state-proof.js +118 -0
- package/dist/cjs/ottochain/transaction.js +7 -1
- package/dist/cjs/ottochain/webhook-notifications.js +33 -0
- package/dist/cjs/schema/effects.js +14 -5
- package/dist/cjs/schema/guard-lint.js +102 -0
- package/dist/esm/apps/lending/assets.js +11 -1
- package/dist/esm/index.js +3 -0
- package/dist/esm/ottochain/index.js +4 -0
- package/dist/esm/ottochain/morphism-lint.js +95 -0
- package/dist/esm/ottochain/state-proof.js +113 -0
- package/dist/esm/ottochain/transaction.js +7 -1
- package/dist/esm/ottochain/webhook-notifications.js +30 -0
- package/dist/esm/schema/effects.js +14 -5
- package/dist/esm/schema/guard-lint.js +102 -0
- package/dist/types/apps/lending/assets.d.ts +11 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/ottochain/index.d.ts +6 -0
- package/dist/types/ottochain/morphism-lint.d.ts +56 -0
- package/dist/types/ottochain/state-proof.d.ts +51 -0
- package/dist/types/ottochain/transaction.d.ts +7 -1
- package/dist/types/ottochain/types.d.ts +22 -0
- package/dist/types/ottochain/webhook-notifications.d.ts +91 -0
- package/dist/types/schema/effects.d.ts +14 -5
- package/dist/types/schema/guard-lint.d.ts +6 -0
- package/package.json +6 -6
|
@@ -741,15 +741,32 @@ export interface MintAsset {
|
|
|
741
741
|
* Optional fields carry per-kind directives (recipient for Transfer/Wrap; otherAssetIds + compositeId
|
|
742
742
|
* for Compose; shardIds for Fractionalize; nonce for a commit-reveal symmetric Compose;
|
|
743
743
|
* priorComponents is the Decompose reveal witness).
|
|
744
|
+
*
|
|
745
|
+
* C2 — cross-holder Compose/Pool consent is MANDATORY. As of the fiber-engine permissionless-hardening
|
|
746
|
+
* (chain branch `fix/fiber-engine-permissionless-hardening`, audit finding C2) a `Compose`/`Pool` that
|
|
747
|
+
* folds in a counter-party the signer does NOT hold is REJECTED (graceful `CombineRejected`) UNLESS a
|
|
748
|
+
* live {@link AuthorizeCompose} nonce authorizes that counter-party. A SAME-holder compose (every part in
|
|
749
|
+
* `otherAssetIds` is signer-owned) still needs no nonce. `otherAssetIds` may no longer contain duplicates
|
|
750
|
+
* or the `assetId` itself (the old self/duplicate-inflation path is rejected).
|
|
744
751
|
*/
|
|
745
752
|
export interface ApplyMorphism {
|
|
746
753
|
assetId: string;
|
|
747
754
|
kind: MorphismKind;
|
|
748
755
|
targetSequenceNumber: number;
|
|
749
756
|
recipient?: AssetHolder;
|
|
757
|
+
/**
|
|
758
|
+
* Compose/Pool counter-party asset ids folded into the composite. Each id the signer does NOT hold is a
|
|
759
|
+
* CROSS-HOLDER part and now REQUIRES a live {@link AuthorizeCompose} nonce (see `nonce`) authorizing it
|
|
760
|
+
* — else the whole morphism is rejected (C2). Must be free of duplicates and must not include `assetId`.
|
|
761
|
+
*/
|
|
750
762
|
otherAssetIds?: string[];
|
|
751
763
|
compositeId?: string;
|
|
752
764
|
shardIds?: string[];
|
|
765
|
+
/**
|
|
766
|
+
* The cross-holder Compose consent nonce: the reveal half of the {@link AuthorizeCompose} handshake.
|
|
767
|
+
* REQUIRED whenever any `otherAssetIds` entry is not signer-owned (C2); omit it only for a same-holder
|
|
768
|
+
* compose. A nonce-less cross-holder compose is no longer accepted.
|
|
769
|
+
*/
|
|
753
770
|
nonce?: number;
|
|
754
771
|
priorComponents?: ComponentWitness[];
|
|
755
772
|
/** ZkVerify-gated morphism: optional witness a `Governed` morphism's guard reads (see {@link MorphismSpec}). */
|
|
@@ -758,6 +775,11 @@ export interface ApplyMorphism {
|
|
|
758
775
|
/**
|
|
759
776
|
* Authorize a counter-party policy to Compose with this asset (the commit half of the commit-reveal
|
|
760
777
|
* symmetric-compose handshake). `nonce` and `expiresAt` are REQUIRED (no sentinel defaults).
|
|
778
|
+
*
|
|
779
|
+
* C2 — this consent is now MANDATORY, not opt-in. A `Compose`/`Pool` ({@link ApplyMorphism}) that consumes
|
|
780
|
+
* a counter-party the signer does not own is rejected unless a matching, unexpired `AuthorizeCompose` nonce
|
|
781
|
+
* is live for that counter-party (chain branch `fix/fiber-engine-permissionless-hardening`, finding C2).
|
|
782
|
+
* The composing party echoes this `nonce` in `ApplyMorphism.nonce`. A same-holder compose needs none.
|
|
761
783
|
*/
|
|
762
784
|
export interface AuthorizeCompose {
|
|
763
785
|
assetId: string;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Webhook notification PAYLOAD types — the server-initiated push the chain POSTs to a subscribed
|
|
3
|
+
* callback, NOT part of the client's request surface.
|
|
4
|
+
*
|
|
5
|
+
* These are hand-authored (not generated from the OpenAPI contract) because the push is an OUTBOUND
|
|
6
|
+
* POST from the metagraph to the subscriber's callback URL — it is not an endpoint the chain's tapir
|
|
7
|
+
* `ApiEndpoints` serves, so it never appears in `openapi/ottochain-openapi-ml0.json`. They mirror the
|
|
8
|
+
* chain's shared network DTOs byte-for-byte:
|
|
9
|
+
*
|
|
10
|
+
* chain: modules/models/src/main/scala/xyz/kd5ujc/schema/api/webhooks/Subscriber.scala
|
|
11
|
+
* (SnapshotNotification / NotificationStats / SnapshotRejection)
|
|
12
|
+
* emit: modules/l0/.../webhooks/WebhookDispatcher.scala — `notification.asJson.noSpaces`
|
|
13
|
+
*
|
|
14
|
+
* Field-shape notes tied to the chain source:
|
|
15
|
+
* - The dispatcher serializes with a plain derived encoder (`.asJson`, NO `dropNullValues`), so an
|
|
16
|
+
* `Option[Long]` that is `None` is emitted as an explicit `null` — the KEY is always present, the
|
|
17
|
+
* VALUE is nullable. Hence `number | null` (a required key), not `number | undefined` (an optional
|
|
18
|
+
* key). Consumers must handle `null`.
|
|
19
|
+
* - `Long` → JSON number; `Instant` → ISO-8601 string; `UUID` → string.
|
|
20
|
+
* - The dispatcher only ever emits `"snapshot.finalized"` today (there is a dead, never-dispatched
|
|
21
|
+
* `RejectionNotification`/`transaction.rejected` type in the chain models — deliberately NOT mirrored
|
|
22
|
+
* here, because the SDK should model only what is actually sent). Rejections now ride the finalized
|
|
23
|
+
* snapshot's `rejections[]`, drained from its committed `RejectionReceipt`s.
|
|
24
|
+
*
|
|
25
|
+
* @see modules/models/.../schema/api/webhooks/Subscriber.scala
|
|
26
|
+
* @see modules/l0/.../webhooks/WebhookDispatcher.scala
|
|
27
|
+
* @packageDocumentation
|
|
28
|
+
*/
|
|
29
|
+
/** The only event the chain's `WebhookDispatcher` currently emits. */
|
|
30
|
+
export declare const SNAPSHOT_FINALIZED_EVENT: "snapshot.finalized";
|
|
31
|
+
/**
|
|
32
|
+
* Aggregate counters for the finalized snapshot, mirrors chain `NotificationStats`.
|
|
33
|
+
*/
|
|
34
|
+
export interface NotificationStats {
|
|
35
|
+
/** Number of data updates processed into this snapshot. */
|
|
36
|
+
updatesProcessed: number;
|
|
37
|
+
/** Count of active state-machine fibers after this snapshot. */
|
|
38
|
+
stateMachinesActive: number;
|
|
39
|
+
/** Count of active script fibers after this snapshot. */
|
|
40
|
+
scriptsActive: number;
|
|
41
|
+
/** Number of updates rejected while combining this snapshot (== `rejections.length`). */
|
|
42
|
+
rejectedCount: number;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A single post-finalization rejection, batched onto the `snapshot.finalized` notification. Drained
|
|
46
|
+
* from the committed snapshot's `RejectionReceipt`s, so it reflects committed state (not a pre-combine
|
|
47
|
+
* guess). Mirrors chain `SnapshotRejection`.
|
|
48
|
+
*/
|
|
49
|
+
export interface SnapshotRejection {
|
|
50
|
+
/** The rejected update's type, e.g. `"TransitionStateMachine"`, `"CreateStateMachine"`. */
|
|
51
|
+
updateType: string;
|
|
52
|
+
/** UUID of the target fiber. */
|
|
53
|
+
fiberId: string;
|
|
54
|
+
/**
|
|
55
|
+
* The transition's target sequence number, or `null` for non-sequenced updates. Chain
|
|
56
|
+
* `Option[Long]`, emitted as an explicit `null` when absent (dispatcher does not drop nulls).
|
|
57
|
+
*/
|
|
58
|
+
targetSequenceNumber: number | null;
|
|
59
|
+
/**
|
|
60
|
+
* The fiber's actual sequence number at rejection time (for a sequence mismatch), or `null`. Chain
|
|
61
|
+
* `Option[Long]`, emitted as an explicit `null` when absent.
|
|
62
|
+
*/
|
|
63
|
+
actualSequenceNumber: number | null;
|
|
64
|
+
/** Human-readable rejection reason (the combiner's `CombineRejected` code/message). */
|
|
65
|
+
reason: string;
|
|
66
|
+
/** Hash of the signed update, for correlation with a submitted transaction. */
|
|
67
|
+
updateHash: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The payload POSTed to a subscribed webhook callback when a snapshot finalizes — the confirm TICK.
|
|
71
|
+
* Mirrors chain `SnapshotNotification`.
|
|
72
|
+
*
|
|
73
|
+
* There is NO per-update "accepted" event: an update is accepted iff its `updateHash` lands in a
|
|
74
|
+
* finalized snapshot AND is absent from every `rejections[]` of the snapshots up to that ordinal.
|
|
75
|
+
*/
|
|
76
|
+
export interface SnapshotNotification {
|
|
77
|
+
/** Always `"snapshot.finalized"`. */
|
|
78
|
+
event: typeof SNAPSHOT_FINALIZED_EVENT;
|
|
79
|
+
/** The finalized snapshot ordinal. Chain `Long`. */
|
|
80
|
+
ordinal: number;
|
|
81
|
+
/** The finalized snapshot hash. */
|
|
82
|
+
hash: string;
|
|
83
|
+
/** ISO-8601 dispatch timestamp. Chain `Instant`. */
|
|
84
|
+
timestamp: string;
|
|
85
|
+
/** The metagraph token identifier this notification is for. */
|
|
86
|
+
metagraphId: string;
|
|
87
|
+
/** Aggregate counters for the snapshot. */
|
|
88
|
+
stats: NotificationStats;
|
|
89
|
+
/** Updates rejected while combining this snapshot (empty if none). */
|
|
90
|
+
rejections: SnapshotRejection[];
|
|
91
|
+
}
|
|
@@ -108,11 +108,20 @@ export declare const triggers: (ts: {
|
|
|
108
108
|
* MUST be a literal {@link ProtoStateMachineDefinition} (e.g. a nested `machine().wireDefinition()` /
|
|
109
109
|
* `toProtoDefinition(child)` output) — NOT an expression the engine would evaluate at runtime.
|
|
110
110
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
111
|
+
* H1 constraint — child `owners` MUST be a SUBSET of the SPAWNING PARENT fiber's `owners`. As of the
|
|
112
|
+
* fiber-engine permissionless-hardening (chain branch `fix/fiber-engine-permissionless-hardening`, audit
|
|
113
|
+
* finding H1) the chain FAILS-CLOSED — it aborts the whole transition under EVERY `spawnOwnerPolicy` — if
|
|
114
|
+
* a `_spawn`'s resolved child `owners` are not ⊆ the parent's owners. Assigning arbitrary, unsigned owners
|
|
115
|
+
* (the old "auction owned by all its bidders" pattern, where the bidders are NOT parent owners) is no
|
|
116
|
+
* longer valid: those events are not silently rejected, the spawn itself is rejected.
|
|
117
|
+
*
|
|
118
|
+
* So DO NOT try to enroll later participants by listing them here. A spawned child's transitions are gated
|
|
119
|
+
* by `owners ∪ authorizedSigners` for the DIRECT (wallet-signed) path; admit additional drivers through
|
|
120
|
+
* the child's OWN transitions (`authorizedSigners`), or drive it via the cascade (`_triggers`) subject to
|
|
121
|
+
* its `acceptedCallers` — never by widening `owners` beyond the parent's set. `owners` may be a literal id
|
|
122
|
+
* array or an expression (e.g. `{ var: "state.owners" }` — resolve it WITHIN the parent's owners), but a
|
|
123
|
+
* value the parent does not own (e.g. `{ var: "event.auctionOwners" }` supplied by the caller) will be
|
|
124
|
+
* rejected on-chain. `childId` / `initialData` likewise accept literals or expressions.
|
|
116
125
|
*/
|
|
117
126
|
export declare const spawn: (ds: {
|
|
118
127
|
childId: JsonLogicValue;
|
|
@@ -32,6 +32,11 @@
|
|
|
32
32
|
*
|
|
33
33
|
* leading-dot — `{"var":".foo"}` resolves to null on chain.
|
|
34
34
|
*
|
|
35
|
+
* H1 — a `_spawn` whose child `owners` are not provably a SUBSET of the spawning
|
|
36
|
+
* parent's owners. The chain now fails-closed (aborts the transition) under
|
|
37
|
+
* every spawnOwnerPolicy when child owners ⊄ parent owners; this advisory
|
|
38
|
+
* flags the strong not-subset signals (hardcoded / `event.*`-derived owners).
|
|
39
|
+
*
|
|
35
40
|
* This is a STANDALONE validator. It is deliberately NOT wired into
|
|
36
41
|
* `defineFiberApp` / `toProtoDefinition`: doing so would break the build until
|
|
37
42
|
* every app is remediated. Run it via `scripts/lint-apps.mjs`.
|
|
@@ -58,6 +63,7 @@ export declare const LINT_CODES: {
|
|
|
58
63
|
readonly WITNESS_IN_TRANSITION: "witness-in-transition";
|
|
59
64
|
readonly DROPPED_DIRECTIVE: "dropped-directive";
|
|
60
65
|
readonly LEADING_DOT_VAR: "leading-dot-var";
|
|
66
|
+
readonly SPAWN_OWNERS: "spawn-owners";
|
|
61
67
|
};
|
|
62
68
|
/**
|
|
63
69
|
* The ONLY `$`-prefixed keys the engine injects (`ReservedKeys`). Anything else
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ottochain/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.0",
|
|
4
4
|
"description": "TypeScript SDK for ottochain metagraph operations - signing, encoding, and network interactions",
|
|
5
5
|
"main": "dist/cjs/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -148,12 +148,12 @@
|
|
|
148
148
|
},
|
|
149
149
|
"devDependencies": {
|
|
150
150
|
"@babel/preset-env": "^7.29.7",
|
|
151
|
-
"@commitlint/cli": "^21.
|
|
152
|
-
"@commitlint/config-conventional": "^21.
|
|
151
|
+
"@commitlint/cli": "^21.2.0",
|
|
152
|
+
"@commitlint/config-conventional": "^21.2.0",
|
|
153
153
|
"@eslint/js": "^10.0.1",
|
|
154
154
|
"@jest/globals": "^30.3.0",
|
|
155
155
|
"@types/jest": "^30.0.0",
|
|
156
|
-
"@types/node": "^26.0
|
|
156
|
+
"@types/node": "^26.1.0",
|
|
157
157
|
"@typescript-eslint/eslint-plugin": "^8.62.0",
|
|
158
158
|
"@typescript-eslint/parser": "^8.62.0",
|
|
159
159
|
"eslint": "^10.6.0",
|
|
@@ -161,8 +161,8 @@
|
|
|
161
161
|
"openapi-typescript": "^7.13.0",
|
|
162
162
|
"prettier": "^3.9.1",
|
|
163
163
|
"ts-jest": "29.4.9",
|
|
164
|
-
"ts-proto": "^2.
|
|
165
|
-
"typedoc": "^0.28.
|
|
164
|
+
"ts-proto": "^2.12.0",
|
|
165
|
+
"typedoc": "^0.28.20",
|
|
166
166
|
"typescript": "^6.0.3"
|
|
167
167
|
},
|
|
168
168
|
"peerDependencies": {
|