@ottochain/sdk 2.2.5 → 2.4.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/contracts/index.js +15 -8
- package/dist/cjs/apps/contracts/state-machines/contract-agreement.js +89 -46
- package/dist/cjs/apps/contracts/state-machines/contract-escrow.js +152 -45
- package/dist/cjs/apps/contracts/state-machines/contract-universal.js +40 -8
- package/dist/cjs/apps/corporate/index.js +2 -2
- package/dist/cjs/apps/corporate/state-machines/corp-board.js +169 -59
- package/dist/cjs/apps/corporate/state-machines/corp-entity.js +245 -47
- package/dist/cjs/apps/corporate/state-machines/corp-securities.js +407 -99
- package/dist/cjs/apps/corporate/state-machines/corp-shareholders.js +151 -37
- package/dist/cjs/apps/governance/index.js +14 -14
- package/dist/cjs/apps/governance/state-machines/dao-multisig.js +85 -43
- package/dist/cjs/apps/governance/state-machines/dao-reputation.js +73 -43
- package/dist/cjs/apps/governance/state-machines/dao-single.js +55 -14
- package/dist/cjs/apps/governance/state-machines/dao-token.js +103 -45
- package/dist/cjs/apps/governance/state-machines/governance-simple.js +129 -65
- package/dist/cjs/apps/governance/state-machines/governance-universal.js +29 -5
- package/dist/cjs/apps/identity/constants.js +55 -14
- package/dist/cjs/apps/identity/index.js +27 -11
- package/dist/cjs/apps/identity/state-machines/identity-agent.js +57 -9
- package/dist/cjs/apps/identity/state-machines/identity-oracle.js +70 -27
- package/dist/cjs/apps/identity/state-machines/identity-registry.js +288 -0
- package/dist/cjs/apps/identity/state-machines/identity-universal.js +30 -6
- package/dist/cjs/apps/identity/state-machines/index.js +3 -1
- package/dist/cjs/apps/index.js +19 -8
- package/dist/cjs/apps/lending/assets.js +223 -0
- package/dist/cjs/apps/lending/credit-scoring.js +87 -0
- package/dist/cjs/apps/lending/eligibility.js +121 -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 +412 -0
- package/dist/cjs/apps/markets/index.js +21 -11
- package/dist/cjs/apps/markets/state-machines/market-auction.js +44 -19
- package/dist/cjs/apps/markets/state-machines/market-crowdfund.js +54 -29
- package/dist/cjs/apps/markets/state-machines/market-group-buy.js +53 -31
- package/dist/cjs/apps/markets/state-machines/market-prediction.js +120 -61
- package/dist/cjs/apps/markets/state-machines/market-universal.js +50 -10
- package/dist/cjs/apps/oracles/index.js +2 -2
- package/dist/cjs/errors.js +3 -3
- package/dist/cjs/generated/google/protobuf/struct.js +4 -4
- 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 +50 -50
- package/dist/cjs/generated/ottochain/apps/corporate/v1/corporate.js +19 -20
- package/dist/cjs/generated/ottochain/apps/governance/v1/governance.js +13 -13
- package/dist/cjs/generated/ottochain/apps/identity/v1/attestation.js +4 -4
- package/dist/cjs/generated/ottochain/apps/identity/v1/identity.js +124 -130
- package/dist/cjs/generated/ottochain/apps/markets/v1/market.js +107 -107
- package/dist/cjs/generated/ottochain/v1/common.js +1722 -1
- package/dist/cjs/generated/ottochain/v1/fiber.js +355 -5
- package/dist/cjs/generated/ottochain/v1/messages.js +775 -3
- package/dist/cjs/generated/ottochain/v1/records.js +350 -3
- package/dist/cjs/index.js +45 -7
- package/dist/cjs/openapi.js +2 -0
- package/dist/cjs/ottochain/drop-nulls.js +1 -2
- package/dist/cjs/ottochain/genesis-manifest.js +193 -0
- package/dist/cjs/ottochain/index.js +27 -13
- package/dist/cjs/ottochain/metagraph-client.js +65 -8
- package/dist/cjs/ottochain/snapshot.js +11 -12
- package/dist/cjs/ottochain/transaction.js +57 -14
- package/dist/cjs/ottochain/types.js +19 -1
- package/dist/cjs/privacy/index.js +14 -0
- package/dist/cjs/privacy/sealed-bid.js +210 -0
- package/dist/cjs/privacy/shield-app.js +131 -0
- package/dist/cjs/schema/effects.js +40 -0
- package/dist/cjs/schema/fiber-app.js +19 -13
- package/dist/cjs/schema/guard-lint.js +352 -0
- package/dist/cjs/schema/guards.js +246 -0
- package/dist/cjs/signing.js +80 -0
- package/dist/cjs/types.js +2 -3
- package/dist/cjs/validation.js +8 -8
- 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/contracts/index.js +7 -3
- package/dist/esm/apps/contracts/state-machines/contract-agreement.js +89 -46
- package/dist/esm/apps/contracts/state-machines/contract-escrow.js +152 -45
- package/dist/esm/apps/contracts/state-machines/contract-universal.js +40 -8
- package/dist/esm/apps/corporate/state-machines/corp-board.js +169 -59
- package/dist/esm/apps/corporate/state-machines/corp-entity.js +245 -47
- package/dist/esm/apps/corporate/state-machines/corp-securities.js +407 -99
- package/dist/esm/apps/corporate/state-machines/corp-shareholders.js +151 -37
- package/dist/esm/apps/governance/state-machines/dao-multisig.js +85 -43
- package/dist/esm/apps/governance/state-machines/dao-reputation.js +73 -43
- package/dist/esm/apps/governance/state-machines/dao-single.js +55 -14
- package/dist/esm/apps/governance/state-machines/dao-token.js +103 -45
- package/dist/esm/apps/governance/state-machines/governance-simple.js +129 -65
- package/dist/esm/apps/governance/state-machines/governance-universal.js +29 -5
- package/dist/esm/apps/identity/constants.js +51 -12
- package/dist/esm/apps/identity/index.js +12 -7
- package/dist/esm/apps/identity/state-machines/identity-agent.js +57 -9
- package/dist/esm/apps/identity/state-machines/identity-oracle.js +70 -27
- package/dist/esm/apps/identity/state-machines/identity-registry.js +285 -0
- package/dist/esm/apps/identity/state-machines/identity-universal.js +30 -6
- package/dist/esm/apps/identity/state-machines/index.js +1 -0
- package/dist/esm/apps/index.js +1 -0
- package/dist/esm/apps/lending/assets.js +207 -0
- package/dist/esm/apps/lending/credit-scoring.js +81 -0
- package/dist/esm/apps/lending/eligibility.js +115 -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 +409 -0
- package/dist/esm/apps/markets/index.js +8 -4
- package/dist/esm/apps/markets/state-machines/market-auction.js +44 -19
- package/dist/esm/apps/markets/state-machines/market-crowdfund.js +54 -29
- package/dist/esm/apps/markets/state-machines/market-group-buy.js +53 -31
- package/dist/esm/apps/markets/state-machines/market-prediction.js +120 -61
- package/dist/esm/apps/markets/state-machines/market-universal.js +50 -10
- 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 +46 -46
- package/dist/esm/generated/ottochain/apps/identity/v1/identity.js +114 -120
- package/dist/esm/generated/ottochain/apps/markets/v1/market.js +100 -100
- package/dist/esm/generated/ottochain/v1/common.js +1718 -0
- package/dist/esm/generated/ottochain/v1/fiber.js +351 -1
- package/dist/esm/generated/ottochain/v1/messages.js +774 -2
- package/dist/esm/generated/ottochain/v1/records.js +349 -2
- package/dist/esm/index.js +23 -2
- package/dist/esm/openapi.js +1 -0
- package/dist/esm/ottochain/genesis-manifest.js +189 -0
- package/dist/esm/ottochain/index.js +4 -3
- package/dist/esm/ottochain/metagraph-client.js +65 -8
- package/dist/esm/ottochain/snapshot.js +4 -4
- package/dist/esm/ottochain/transaction.js +43 -3
- package/dist/esm/ottochain/types.js +18 -0
- package/dist/esm/privacy/index.js +6 -0
- package/dist/esm/privacy/sealed-bid.js +206 -0
- package/dist/esm/privacy/shield-app.js +127 -0
- package/dist/esm/schema/effects.js +35 -0
- package/dist/esm/schema/fiber-app.js +13 -6
- package/dist/esm/schema/guard-lint.js +346 -0
- package/dist/esm/schema/guards.js +229 -0
- package/dist/esm/signing.js +74 -0
- 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/contracts/index.d.ts +159 -227
- package/dist/types/apps/contracts/state-machines/contract-agreement.d.ts +50 -101
- package/dist/types/apps/contracts/state-machines/contract-escrow.d.ts +86 -120
- package/dist/types/apps/contracts/state-machines/contract-universal.d.ts +20 -4
- package/dist/types/apps/corporate/index.d.ts +1040 -304
- package/dist/types/apps/corporate/state-machines/corp-board.d.ts +188 -52
- package/dist/types/apps/corporate/state-machines/corp-entity.d.ts +267 -62
- package/dist/types/apps/corporate/state-machines/corp-securities.d.ts +355 -131
- package/dist/types/apps/corporate/state-machines/corp-shareholders.d.ts +225 -53
- package/dist/types/apps/governance/index.d.ts +396 -417
- package/dist/types/apps/governance/state-machines/dao-multisig.d.ts +92 -95
- package/dist/types/apps/governance/state-machines/dao-reputation.d.ts +57 -69
- package/dist/types/apps/governance/state-machines/dao-single.d.ts +40 -50
- package/dist/types/apps/governance/state-machines/dao-token.d.ts +80 -53
- package/dist/types/apps/governance/state-machines/governance-simple.d.ts +107 -121
- package/dist/types/apps/governance/state-machines/governance-universal.d.ts +17 -5
- package/dist/types/apps/identity/constants.d.ts +32 -4
- package/dist/types/apps/identity/index.d.ts +449 -100
- package/dist/types/apps/identity/state-machines/identity-agent.d.ts +30 -0
- package/dist/types/apps/identity/state-machines/identity-oracle.d.ts +41 -87
- package/dist/types/apps/identity/state-machines/identity-registry.d.ts +379 -0
- package/dist/types/apps/identity/state-machines/identity-universal.d.ts +15 -0
- package/dist/types/apps/identity/state-machines/index.d.ts +1 -0
- package/dist/types/apps/index.d.ts +1 -0
- 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 +548 -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 +528 -0
- package/dist/types/apps/markets/index.d.ts +184 -204
- package/dist/types/apps/markets/state-machines/market-auction.d.ts +25 -37
- package/dist/types/apps/markets/state-machines/market-crowdfund.d.ts +26 -34
- package/dist/types/apps/markets/state-machines/market-group-buy.d.ts +31 -43
- package/dist/types/apps/markets/state-machines/market-prediction.d.ts +67 -72
- package/dist/types/apps/markets/state-machines/market-universal.d.ts +30 -10
- package/dist/types/generated/index.d.ts +5 -5
- package/dist/types/generated/openapi.d.ts +1257 -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/common.d.ts +228 -0
- package/dist/types/generated/ottochain/v1/fiber.d.ts +32 -1
- package/dist/types/generated/ottochain/v1/messages.d.ts +84 -0
- package/dist/types/generated/ottochain/v1/records.d.ts +34 -0
- package/dist/types/index.d.ts +8 -2
- package/dist/types/openapi.d.ts +22 -0
- package/dist/types/ottochain/genesis-manifest.d.ts +130 -0
- package/dist/types/ottochain/index.d.ts +6 -5
- 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 +33 -1
- package/dist/types/ottochain/types.d.ts +602 -11
- 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 +34 -0
- package/dist/types/schema/fiber-app.d.ts +41 -3
- package/dist/types/schema/guard-lint.d.ts +111 -0
- package/dist/types/schema/guards.d.ts +134 -0
- package/dist/types/signing.d.ts +45 -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 +52 -35
- 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,409 @@
|
|
|
1
|
+
import { defineFiberApp } from "../../../schema/fiber-app.js";
|
|
2
|
+
/**
|
|
3
|
+
* Privacy-preserving zk-loan — a private-finance lending fiber modeled on Midnight's
|
|
4
|
+
* zkLoan example, integrated with OttoChain's asset subsystem.
|
|
5
|
+
*
|
|
6
|
+
* The borrower proves, in zero-knowledge, that their PRIVATE financials satisfy the
|
|
7
|
+
* PUBLIC lending rule (collateral coverage and/or a credit-score floor) WITHOUT
|
|
8
|
+
* revealing the financials. The lender originates the loan. The collateral, principal,
|
|
9
|
+
* and repayment are ASSETS, driven through typed morphisms by the loan lifecycle.
|
|
10
|
+
*
|
|
11
|
+
* Privacy boundary (see docs/design/zk-loan-app.md):
|
|
12
|
+
* - PRIVATE (witness only): collateralValue, credit/income financials (income, score),
|
|
13
|
+
* outstanding debt, and the blinding salts. Never on-chain, never in the event.
|
|
14
|
+
* - PUBLIC (revealed): the loan principal amount, the collateral asset id (a locked
|
|
15
|
+
* handle, not its private valuation), the lending-rule logicHash, loan status, and
|
|
16
|
+
* the boolean "eligible" outcome — the chain learns *whether* the borrower qualifies,
|
|
17
|
+
* never *why*.
|
|
18
|
+
*
|
|
19
|
+
* The ORIGINATION guard (`originate`, COLLATERAL_LOCKED -> ACTIVE) is the semi-private
|
|
20
|
+
* gate: it verifies an SP1-Groth16 eligibility proof over `witness.{publicValues,proof}`
|
|
21
|
+
* with the lender's pinned verifying key, AND binds the proof's committed public values
|
|
22
|
+
* (parsed out of the opaque `publicValues` blob with native JLVM `cat`/`substr`) to the
|
|
23
|
+
* PUBLIC lending rule — `exprHash == $lendingRuleLogicHash`, `outputHash == $keccakTrue`,
|
|
24
|
+
* and the `ok` bit — so a proof can only originate a loan if it proves THE pinned rule
|
|
25
|
+
* evaluated to `true` on the borrower's hidden data. A missing/garbage witness makes the
|
|
26
|
+
* guard false and the transition is gracefully rejected (state untouched).
|
|
27
|
+
*
|
|
28
|
+
* The pinned public constants ($lendingRuleVKey, $lendingRuleLogicHash, $keccakTrue) live
|
|
29
|
+
* on the loan's create-state so the guard is a closed expression. They are produced
|
|
30
|
+
* client-side by `src/apps/lending` helpers (`buildOriginationGuard`, `pinLendingRule`)
|
|
31
|
+
* over `src/zk` (`exprHash`, `KECCAK_TRUE`).
|
|
32
|
+
*/
|
|
33
|
+
export const lendingZkLoanDef = defineFiberApp({
|
|
34
|
+
metadata: {
|
|
35
|
+
name: "LendingZkLoan",
|
|
36
|
+
app: "lending",
|
|
37
|
+
type: "zkLoan",
|
|
38
|
+
version: "1.0.0",
|
|
39
|
+
description: "Privacy-preserving collateralized loan: the borrower proves loan eligibility (collateral coverage / credit-score floor) in zero-knowledge without revealing the financials; collateral, principal and repayment are asset-subsystem tokens driven by the loan lifecycle.",
|
|
40
|
+
crossReferences: {
|
|
41
|
+
borrowerIdentityId: "Links to the borrower's IdentityAgent",
|
|
42
|
+
lenderIdentityId: "Links to the lender's IdentityAgent (loan originator)",
|
|
43
|
+
collateralAssetId: "Asset instance locked as collateral (held by the loan's escrow fiber)",
|
|
44
|
+
debtAssetId: "Asset instance representing the outstanding loan principal/debt minted to the borrower",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
createSchema: {
|
|
48
|
+
required: [
|
|
49
|
+
"borrower",
|
|
50
|
+
"lender",
|
|
51
|
+
"principalAmount",
|
|
52
|
+
"collateralAssetId",
|
|
53
|
+
"collateralPolicy",
|
|
54
|
+
"debtPolicy",
|
|
55
|
+
"lendingRuleVKey",
|
|
56
|
+
"lendingRuleLogicHash",
|
|
57
|
+
"keccakTrue",
|
|
58
|
+
],
|
|
59
|
+
properties: {
|
|
60
|
+
borrower: {
|
|
61
|
+
type: "address",
|
|
62
|
+
description: "DAG address of the borrower",
|
|
63
|
+
immutable: true,
|
|
64
|
+
},
|
|
65
|
+
lender: {
|
|
66
|
+
type: "address",
|
|
67
|
+
description: "DAG address of the lender / loan originator",
|
|
68
|
+
immutable: true,
|
|
69
|
+
},
|
|
70
|
+
principalAmount: {
|
|
71
|
+
type: "integer",
|
|
72
|
+
description: "PUBLIC loan principal (asset minor-units). The financials backing eligibility stay private.",
|
|
73
|
+
minimum: 1,
|
|
74
|
+
immutable: true,
|
|
75
|
+
},
|
|
76
|
+
collateralAssetId: {
|
|
77
|
+
type: "uuid",
|
|
78
|
+
description: "Asset instance id pledged as collateral (its private valuation is never revealed).",
|
|
79
|
+
immutable: true,
|
|
80
|
+
},
|
|
81
|
+
collateralPolicy: {
|
|
82
|
+
type: "string",
|
|
83
|
+
description: "Collateral asset policy name (e.g. 'collateral-vault-v1.asset').",
|
|
84
|
+
immutable: true,
|
|
85
|
+
},
|
|
86
|
+
debtPolicy: {
|
|
87
|
+
type: "string",
|
|
88
|
+
description: "Debt/loan-token asset policy name (e.g. 'loan-debt-v1.asset').",
|
|
89
|
+
immutable: true,
|
|
90
|
+
},
|
|
91
|
+
escrowFiberId: {
|
|
92
|
+
type: "uuid",
|
|
93
|
+
description: "Fiber that custodies the locked collateral (AssetHolder.Fiber). Defaults to this loan fiber.",
|
|
94
|
+
},
|
|
95
|
+
lendingRuleVKey: {
|
|
96
|
+
type: "hash",
|
|
97
|
+
description: "PINNED SP1 program verifying key (bytes32, 0x-hex) for the eligibility circuit.",
|
|
98
|
+
immutable: true,
|
|
99
|
+
},
|
|
100
|
+
lendingRuleLogicHash: {
|
|
101
|
+
type: "hash",
|
|
102
|
+
description: "PINNED logicHash of the public lending rule = keccak256(canonicalize(rule)). The proof's committed exprHash must equal this.",
|
|
103
|
+
immutable: true,
|
|
104
|
+
},
|
|
105
|
+
keccakTrue: {
|
|
106
|
+
type: "hash",
|
|
107
|
+
description: "PINNED keccak256(canonicalize(true)) — the outputHash a 'rule returned true' proof must commit.",
|
|
108
|
+
immutable: true,
|
|
109
|
+
},
|
|
110
|
+
dueOrdinal: {
|
|
111
|
+
type: "integer",
|
|
112
|
+
description: "Optional snapshot ordinal by which repayment is due.",
|
|
113
|
+
minimum: 0,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
stateSchema: {
|
|
118
|
+
properties: {
|
|
119
|
+
status: { type: "string", computed: true },
|
|
120
|
+
borrower: { type: "address", immutable: true },
|
|
121
|
+
lender: { type: "address", immutable: true },
|
|
122
|
+
principalAmount: { type: "integer", immutable: true },
|
|
123
|
+
collateralAssetId: { type: "uuid", immutable: true },
|
|
124
|
+
collateralPolicy: { type: "string", immutable: true },
|
|
125
|
+
debtPolicy: { type: "string", immutable: true },
|
|
126
|
+
escrowFiberId: { type: "uuid" },
|
|
127
|
+
debtAssetId: { type: "uuid", computed: true },
|
|
128
|
+
lendingRuleVKey: { type: "hash", immutable: true },
|
|
129
|
+
lendingRuleLogicHash: { type: "hash", immutable: true },
|
|
130
|
+
keccakTrue: { type: "hash", immutable: true },
|
|
131
|
+
dueOrdinal: { type: "integer" },
|
|
132
|
+
lockedAt: { type: "integer", computed: true },
|
|
133
|
+
originatedAt: { type: "integer", computed: true },
|
|
134
|
+
repaidAt: { type: "integer", computed: true },
|
|
135
|
+
defaultedAt: { type: "integer", computed: true },
|
|
136
|
+
liquidatedAt: { type: "integer", computed: true },
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
eventSchemas: {
|
|
140
|
+
lock_collateral: {
|
|
141
|
+
description: "Borrower locks the pledged collateral asset into the loan escrow fiber (drives an asset Transfer/Mint into AssetHolder.Fiber).",
|
|
142
|
+
},
|
|
143
|
+
originate: {
|
|
144
|
+
description: "Lender originates the loan after the borrower's zk eligibility proof verifies. The witness carries the SP1-Groth16 {publicValues, proof}; the guard binds them to the pinned public lending rule. The effect mints the debt/principal asset to the borrower.",
|
|
145
|
+
required: ["witness", "debtAssetId"],
|
|
146
|
+
properties: {
|
|
147
|
+
witness: {
|
|
148
|
+
type: "object",
|
|
149
|
+
description: "Eligibility-proof witness: { publicValues: 0x-hex, proof: 0x-hex }. Exposed to the guard under the reserved `witness` key.",
|
|
150
|
+
properties: {
|
|
151
|
+
publicValues: { type: "string", description: "abi_encode(JlvmPublicValues), 0x-hex." },
|
|
152
|
+
proof: { type: "string", description: "SP1-Groth16 proof bytes, 0x-hex." },
|
|
153
|
+
},
|
|
154
|
+
required: ["publicValues", "proof"],
|
|
155
|
+
},
|
|
156
|
+
debtAssetId: {
|
|
157
|
+
type: "uuid",
|
|
158
|
+
description: "Asset instance id for the debt/principal token minted to the borrower.",
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
repay: {
|
|
163
|
+
description: "Borrower repays the principal (drives a Burn of the debt token); on success the collateral is released back to the borrower via the escrow fiber.",
|
|
164
|
+
},
|
|
165
|
+
default_loan: {
|
|
166
|
+
description: "Mark the loan defaulted once past due (drives the collateral toward liquidation).",
|
|
167
|
+
},
|
|
168
|
+
liquidate: {
|
|
169
|
+
description: "Lender liquidates a defaulted loan: the locked collateral is transferred to the lender via the escrow fiber.",
|
|
170
|
+
},
|
|
171
|
+
cancel: {
|
|
172
|
+
description: "Cancel a loan request before collateral is locked.",
|
|
173
|
+
properties: { reason: { type: "string" } },
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
states: {
|
|
177
|
+
REQUESTED: {
|
|
178
|
+
id: "REQUESTED",
|
|
179
|
+
isFinal: false,
|
|
180
|
+
metadata: {
|
|
181
|
+
label: "Requested",
|
|
182
|
+
description: "Loan requested; collateral not yet locked, eligibility not yet proven.",
|
|
183
|
+
category: "initial",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
COLLATERAL_LOCKED: {
|
|
187
|
+
id: "COLLATERAL_LOCKED",
|
|
188
|
+
isFinal: false,
|
|
189
|
+
metadata: {
|
|
190
|
+
label: "Collateral Locked",
|
|
191
|
+
description: "Collateral asset escrowed in the loan fiber; awaiting the lender's zk-gated origination.",
|
|
192
|
+
category: "pending",
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
ACTIVE: {
|
|
196
|
+
id: "ACTIVE",
|
|
197
|
+
isFinal: false,
|
|
198
|
+
metadata: {
|
|
199
|
+
label: "Active",
|
|
200
|
+
description: "Loan originated (eligibility proven in zk); principal minted to the borrower.",
|
|
201
|
+
category: "active",
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
DEFAULTED: {
|
|
205
|
+
id: "DEFAULTED",
|
|
206
|
+
isFinal: false,
|
|
207
|
+
metadata: {
|
|
208
|
+
label: "Defaulted",
|
|
209
|
+
description: "Loan past due and unpaid; collateral pending liquidation.",
|
|
210
|
+
category: "pending",
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
REPAID: {
|
|
214
|
+
id: "REPAID",
|
|
215
|
+
isFinal: true,
|
|
216
|
+
metadata: {
|
|
217
|
+
label: "Repaid",
|
|
218
|
+
description: "Principal repaid (debt burned) and collateral released to the borrower.",
|
|
219
|
+
category: "terminal",
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
LIQUIDATED: {
|
|
223
|
+
id: "LIQUIDATED",
|
|
224
|
+
isFinal: true,
|
|
225
|
+
metadata: {
|
|
226
|
+
label: "Liquidated",
|
|
227
|
+
description: "Defaulted loan settled by transferring the collateral to the lender.",
|
|
228
|
+
category: "terminal",
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
CANCELLED: {
|
|
232
|
+
id: "CANCELLED",
|
|
233
|
+
isFinal: true,
|
|
234
|
+
metadata: {
|
|
235
|
+
label: "Cancelled",
|
|
236
|
+
description: "Loan request cancelled before any collateral was locked.",
|
|
237
|
+
category: "terminal",
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
initialState: "REQUESTED",
|
|
242
|
+
transitions: [
|
|
243
|
+
// Borrower locks collateral into the escrow fiber.
|
|
244
|
+
{
|
|
245
|
+
from: "REQUESTED",
|
|
246
|
+
to: "COLLATERAL_LOCKED",
|
|
247
|
+
eventName: "lock_collateral",
|
|
248
|
+
guard: {
|
|
249
|
+
and: [
|
|
250
|
+
{ in: [{ var: "state.borrower" }, { map: [{ var: "proofs" }, { var: "address" }] }] },
|
|
251
|
+
{ "===": [{ var: "event.assetId" }, { var: "state.collateralAssetId" }] },
|
|
252
|
+
],
|
|
253
|
+
},
|
|
254
|
+
effect: {
|
|
255
|
+
merge: [
|
|
256
|
+
{ var: "state" },
|
|
257
|
+
{ status: "COLLATERAL_LOCKED", lockedAt: { var: "$ordinal" } },
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
dependencies: [],
|
|
261
|
+
},
|
|
262
|
+
// Cancel a request before any collateral is locked.
|
|
263
|
+
{
|
|
264
|
+
from: "REQUESTED",
|
|
265
|
+
to: "CANCELLED",
|
|
266
|
+
eventName: "cancel",
|
|
267
|
+
guard: {
|
|
268
|
+
or: [
|
|
269
|
+
{ in: [{ var: "state.borrower" }, { map: [{ var: "proofs" }, { var: "address" }] }] },
|
|
270
|
+
{ in: [{ var: "state.lender" }, { map: [{ var: "proofs" }, { var: "address" }] }] },
|
|
271
|
+
],
|
|
272
|
+
},
|
|
273
|
+
effect: {
|
|
274
|
+
merge: [
|
|
275
|
+
{ var: "state" },
|
|
276
|
+
{
|
|
277
|
+
status: "CANCELLED",
|
|
278
|
+
cancelledAt: { var: "$ordinal" },
|
|
279
|
+
reason: { var: "event.reason" },
|
|
280
|
+
},
|
|
281
|
+
],
|
|
282
|
+
},
|
|
283
|
+
dependencies: [],
|
|
284
|
+
},
|
|
285
|
+
// ─── ORIGINATION: the zk eligibility gate ─────────────────────────────────
|
|
286
|
+
// The lender originates iff the borrower's SP1-Groth16 eligibility proof verifies
|
|
287
|
+
// against the pinned vkey AND its committed public values bind to the pinned PUBLIC
|
|
288
|
+
// lending rule. publicValues = abi_encode(JlvmPublicValues{exprHash|dataHash|outputHash|ok}):
|
|
289
|
+
// four 32-byte words, so as a 0x-hex string each word is 64 hex chars at offset
|
|
290
|
+
// 2 + 64*i. We slice with native JLVM `substr` (start, len) and re-`cat` the `0x`
|
|
291
|
+
// prefix to compare to the pinned hashes — there is no jlvm_pv_decode opcode by design.
|
|
292
|
+
// The clauses, in order:
|
|
293
|
+
// 1. agent == lender — only the lender originates
|
|
294
|
+
// 2. groth16_verify(vkey, publicValues, proof) — the proof is valid
|
|
295
|
+
// 3. exprHash == lendingRuleLogicHash — it proved THE pinned rule
|
|
296
|
+
// 4. outputHash == keccakTrue — the rule evaluated to true
|
|
297
|
+
// 5. ok bit (last hex pair of word 3) == "01" — the JLVM run did not error
|
|
298
|
+
{
|
|
299
|
+
from: "COLLATERAL_LOCKED",
|
|
300
|
+
to: "ACTIVE",
|
|
301
|
+
eventName: "originate",
|
|
302
|
+
guard: {
|
|
303
|
+
and: [
|
|
304
|
+
{ in: [{ var: "state.lender" }, { map: [{ var: "proofs" }, { var: "address" }] }] },
|
|
305
|
+
{
|
|
306
|
+
groth16_verify: [
|
|
307
|
+
{ var: "state.lendingRuleVKey" },
|
|
308
|
+
{ var: "event.witness.publicValues" },
|
|
309
|
+
{ var: "event.witness.proof" },
|
|
310
|
+
],
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"===": [
|
|
314
|
+
{ cat: ["0x", { substr: [{ var: "event.witness.publicValues" }, 2, 64] }] },
|
|
315
|
+
{ var: "state.lendingRuleLogicHash" },
|
|
316
|
+
],
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"===": [
|
|
320
|
+
{ cat: ["0x", { substr: [{ var: "event.witness.publicValues" }, 130, 64] }] },
|
|
321
|
+
{ var: "state.keccakTrue" },
|
|
322
|
+
],
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"===": [{ substr: [{ var: "event.witness.publicValues" }, 256, 2] }, "01"],
|
|
326
|
+
},
|
|
327
|
+
],
|
|
328
|
+
},
|
|
329
|
+
// Effect mints the loan principal/debt to the borrower (asset Mint), records the
|
|
330
|
+
// debt asset id, and activates the loan.
|
|
331
|
+
effect: {
|
|
332
|
+
merge: [
|
|
333
|
+
{ var: "state" },
|
|
334
|
+
{
|
|
335
|
+
status: "ACTIVE",
|
|
336
|
+
originatedAt: { var: "$ordinal" },
|
|
337
|
+
debtAssetId: { var: "event.debtAssetId" },
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
},
|
|
341
|
+
dependencies: [],
|
|
342
|
+
},
|
|
343
|
+
// Borrower repays — debt is burned, collateral released back to the borrower.
|
|
344
|
+
{
|
|
345
|
+
from: "ACTIVE",
|
|
346
|
+
to: "REPAID",
|
|
347
|
+
eventName: "repay",
|
|
348
|
+
guard: { in: [{ var: "state.borrower" }, { map: [{ var: "proofs" }, { var: "address" }] }] },
|
|
349
|
+
// Release the escrowed collateral back to the borrower. The loan fiber HOLDS the collateral
|
|
350
|
+
// (locked as AssetHolder.Fiber), so it emits the reserved `_transferAsset` directive from inside
|
|
351
|
+
// the effect — the engine extracts `_`-prefixed keys (it is NOT merged into state). A transition-
|
|
352
|
+
// level `emits` block is silently dropped by toProtoDefinition, which would strand the collateral.
|
|
353
|
+
effect: {
|
|
354
|
+
merge: [
|
|
355
|
+
{ var: "state" },
|
|
356
|
+
{
|
|
357
|
+
status: "REPAID",
|
|
358
|
+
repaidAt: { var: "$ordinal" },
|
|
359
|
+
_transferAsset: [
|
|
360
|
+
{ assetId: { var: "state.collateralAssetId" }, recipient: { var: "state.borrower" } },
|
|
361
|
+
],
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
},
|
|
365
|
+
dependencies: [],
|
|
366
|
+
},
|
|
367
|
+
// Loan goes past due → defaulted.
|
|
368
|
+
{
|
|
369
|
+
from: "ACTIVE",
|
|
370
|
+
to: "DEFAULTED",
|
|
371
|
+
eventName: "default_loan",
|
|
372
|
+
guard: {
|
|
373
|
+
and: [
|
|
374
|
+
{ var: "state.dueOrdinal" },
|
|
375
|
+
{ ">=": [{ var: "$ordinal" }, { var: "state.dueOrdinal" }] },
|
|
376
|
+
],
|
|
377
|
+
},
|
|
378
|
+
effect: {
|
|
379
|
+
merge: [
|
|
380
|
+
{ var: "state" },
|
|
381
|
+
{ status: "DEFAULTED", defaultedAt: { var: "$ordinal" } },
|
|
382
|
+
],
|
|
383
|
+
},
|
|
384
|
+
dependencies: [],
|
|
385
|
+
},
|
|
386
|
+
// Lender liquidates a defaulted loan — collateral transferred to the lender.
|
|
387
|
+
{
|
|
388
|
+
from: "DEFAULTED",
|
|
389
|
+
to: "LIQUIDATED",
|
|
390
|
+
eventName: "liquidate",
|
|
391
|
+
guard: { in: [{ var: "state.lender" }, { map: [{ var: "proofs" }, { var: "address" }] }] },
|
|
392
|
+
// Transfer the escrowed collateral to the lender via the reserved `_transferAsset` directive
|
|
393
|
+
// inside the effect (the loan fiber holds it). A transition-level `emits` block is dropped by the engine.
|
|
394
|
+
effect: {
|
|
395
|
+
merge: [
|
|
396
|
+
{ var: "state" },
|
|
397
|
+
{
|
|
398
|
+
status: "LIQUIDATED",
|
|
399
|
+
liquidatedAt: { var: "$ordinal" },
|
|
400
|
+
_transferAsset: [
|
|
401
|
+
{ assetId: { var: "state.collateralAssetId" }, recipient: { var: "state.lender" } },
|
|
402
|
+
],
|
|
403
|
+
},
|
|
404
|
+
],
|
|
405
|
+
},
|
|
406
|
+
dependencies: [],
|
|
407
|
+
},
|
|
408
|
+
],
|
|
409
|
+
});
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
8
8
|
* import {
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* Type,
|
|
10
|
+
* State,
|
|
11
11
|
* Market,
|
|
12
12
|
* getMarketDefinition,
|
|
13
13
|
* MARKETS_DEFINITIONS
|
|
@@ -19,8 +19,12 @@
|
|
|
19
19
|
*
|
|
20
20
|
* @packageDocumentation
|
|
21
21
|
*/
|
|
22
|
-
// Re-export generated protobuf types (source of truth)
|
|
23
|
-
|
|
22
|
+
// Re-export generated protobuf types (source of truth).
|
|
23
|
+
// The nested lifecycle/kind enums dropped their app prefix in the proto; under
|
|
24
|
+
// this app-scoped entrypoint they are unambiguously Type / State.
|
|
25
|
+
export { Type, State, Commitment, Resolution, Market, CreateMarketRequest, CommitToMarketRequest, SubmitResolutionRequest, CancelMarketRequest, MarketDefinition, typeFromJSON, typeToJSON, stateFromJSON, stateToJSON, } from "../../generated/ottochain/apps/markets/v1/market.js";
|
|
26
|
+
// Deprecated app-prefixed aliases (renamed to Type / State); kept for compat.
|
|
27
|
+
export { Type as MarketType, State as MarketState, typeFromJSON as marketTypeFromJSON, typeToJSON as marketTypeToJSON, stateFromJSON as marketStateFromJSON, stateToJSON as marketStateToJSON, } from "../../generated/ottochain/apps/markets/v1/market.js";
|
|
24
28
|
// ---------------------------------------------------------------------------
|
|
25
29
|
// State Machine Definitions (generated from JSON at build time)
|
|
26
30
|
// ---------------------------------------------------------------------------
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { defineFiberApp } from "../../../schema/fiber-app.js";
|
|
2
|
+
import { signerIsParty, signerIsNotParty } from "../../../schema/guards.js";
|
|
2
3
|
/**
|
|
3
4
|
* Auction market supporting English, Dutch, and sealed-bid variants.
|
|
4
5
|
*/
|
|
@@ -70,32 +71,56 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
70
71
|
PROPOSED: {
|
|
71
72
|
id: "PROPOSED",
|
|
72
73
|
isFinal: false,
|
|
73
|
-
metadata: {
|
|
74
|
+
metadata: {
|
|
75
|
+
label: "Proposed",
|
|
76
|
+
description: "Auction created but not yet open",
|
|
77
|
+
category: "initial",
|
|
78
|
+
},
|
|
74
79
|
},
|
|
75
80
|
OPEN: {
|
|
76
81
|
id: "OPEN",
|
|
77
82
|
isFinal: false,
|
|
78
|
-
metadata: {
|
|
83
|
+
metadata: {
|
|
84
|
+
label: "Open",
|
|
85
|
+
description: "Accepting bids",
|
|
86
|
+
category: "active",
|
|
87
|
+
},
|
|
79
88
|
},
|
|
80
89
|
CLOSING: {
|
|
81
90
|
id: "CLOSING",
|
|
82
91
|
isFinal: false,
|
|
83
|
-
metadata: {
|
|
92
|
+
metadata: {
|
|
93
|
+
label: "Closing",
|
|
94
|
+
description: "Bid period ended, determining winner",
|
|
95
|
+
category: "pending",
|
|
96
|
+
},
|
|
84
97
|
},
|
|
85
98
|
SETTLED: {
|
|
86
99
|
id: "SETTLED",
|
|
87
100
|
isFinal: true,
|
|
88
|
-
metadata: {
|
|
101
|
+
metadata: {
|
|
102
|
+
label: "Settled",
|
|
103
|
+
description: "Winner determined, transfer complete",
|
|
104
|
+
category: "terminal",
|
|
105
|
+
},
|
|
89
106
|
},
|
|
90
107
|
NO_SALE: {
|
|
91
108
|
id: "NO_SALE",
|
|
92
109
|
isFinal: true,
|
|
93
|
-
metadata: {
|
|
110
|
+
metadata: {
|
|
111
|
+
label: "No sale",
|
|
112
|
+
description: "Reserve not met or no valid bids",
|
|
113
|
+
category: "terminal",
|
|
114
|
+
},
|
|
94
115
|
},
|
|
95
116
|
CANCELLED: {
|
|
96
117
|
id: "CANCELLED",
|
|
97
118
|
isFinal: true,
|
|
98
|
-
metadata: {
|
|
119
|
+
metadata: {
|
|
120
|
+
label: "Cancelled",
|
|
121
|
+
description: "Auction cancelled by seller",
|
|
122
|
+
category: "terminal",
|
|
123
|
+
},
|
|
99
124
|
},
|
|
100
125
|
},
|
|
101
126
|
initialState: "PROPOSED",
|
|
@@ -104,13 +129,13 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
104
129
|
from: "PROPOSED",
|
|
105
130
|
to: "OPEN",
|
|
106
131
|
eventName: "open",
|
|
107
|
-
guard:
|
|
132
|
+
guard: signerIsParty("state.seller"),
|
|
108
133
|
effect: {
|
|
109
134
|
merge: [
|
|
110
135
|
{ var: "state" },
|
|
111
136
|
{
|
|
112
137
|
status: "OPEN",
|
|
113
|
-
openedAt: { var: "$
|
|
138
|
+
openedAt: { var: "$ordinal" },
|
|
114
139
|
bids: [],
|
|
115
140
|
highBid: null,
|
|
116
141
|
highBidder: null,
|
|
@@ -123,11 +148,11 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
123
148
|
from: "PROPOSED",
|
|
124
149
|
to: "CANCELLED",
|
|
125
150
|
eventName: "cancel",
|
|
126
|
-
guard:
|
|
151
|
+
guard: signerIsParty("state.seller"),
|
|
127
152
|
effect: {
|
|
128
153
|
merge: [
|
|
129
154
|
{ var: "state" },
|
|
130
|
-
{ status: "CANCELLED", cancelledAt: { var: "$
|
|
155
|
+
{ status: "CANCELLED", cancelledAt: { var: "$ordinal" } },
|
|
131
156
|
],
|
|
132
157
|
},
|
|
133
158
|
dependencies: [],
|
|
@@ -138,7 +163,7 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
138
163
|
eventName: "bid",
|
|
139
164
|
guard: {
|
|
140
165
|
and: [
|
|
141
|
-
|
|
166
|
+
signerIsNotParty("state.seller"),
|
|
142
167
|
{ ">=": [{ var: "event.amount" }, { var: "state.minBid" }] },
|
|
143
168
|
{
|
|
144
169
|
or: [
|
|
@@ -159,7 +184,7 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
159
184
|
{
|
|
160
185
|
or: [
|
|
161
186
|
{ "!": [{ var: "state.deadline" }] },
|
|
162
|
-
{ "<=": [{ var: "$
|
|
187
|
+
{ "<=": [{ var: "$ordinal" }, { var: "state.deadline" }] },
|
|
163
188
|
],
|
|
164
189
|
},
|
|
165
190
|
],
|
|
@@ -175,14 +200,14 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
175
200
|
{
|
|
176
201
|
bidder: { var: "event.agent" },
|
|
177
202
|
amount: { var: "event.amount" },
|
|
178
|
-
bidAt: { var: "$
|
|
203
|
+
bidAt: { var: "$ordinal" },
|
|
179
204
|
},
|
|
180
205
|
],
|
|
181
206
|
],
|
|
182
207
|
},
|
|
183
208
|
highBid: { var: "event.amount" },
|
|
184
209
|
highBidder: { var: "event.agent" },
|
|
185
|
-
lastBidAt: { var: "$
|
|
210
|
+
lastBidAt: { var: "$ordinal" },
|
|
186
211
|
},
|
|
187
212
|
],
|
|
188
213
|
},
|
|
@@ -194,11 +219,11 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
194
219
|
eventName: "close",
|
|
195
220
|
guard: {
|
|
196
221
|
or: [
|
|
197
|
-
|
|
222
|
+
signerIsParty("state.seller"),
|
|
198
223
|
{
|
|
199
224
|
and: [
|
|
200
225
|
{ var: "state.deadline" },
|
|
201
|
-
{ ">=": [{ var: "$
|
|
226
|
+
{ ">=": [{ var: "$ordinal" }, { var: "state.deadline" }] },
|
|
202
227
|
],
|
|
203
228
|
},
|
|
204
229
|
],
|
|
@@ -206,7 +231,7 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
206
231
|
effect: {
|
|
207
232
|
merge: [
|
|
208
233
|
{ var: "state" },
|
|
209
|
-
{ status: "CLOSING", closedAt: { var: "$
|
|
234
|
+
{ status: "CLOSING", closedAt: { var: "$ordinal" } },
|
|
210
235
|
],
|
|
211
236
|
},
|
|
212
237
|
dependencies: [],
|
|
@@ -233,7 +258,7 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
233
258
|
{ var: "state" },
|
|
234
259
|
{
|
|
235
260
|
status: "SETTLED",
|
|
236
|
-
settledAt: { var: "$
|
|
261
|
+
settledAt: { var: "$ordinal" },
|
|
237
262
|
winner: { var: "state.highBidder" },
|
|
238
263
|
finalPrice: { var: "state.highBid" },
|
|
239
264
|
},
|
|
@@ -263,7 +288,7 @@ export const marketAuctionDef = defineFiberApp({
|
|
|
263
288
|
{ var: "state" },
|
|
264
289
|
{
|
|
265
290
|
status: "NO_SALE",
|
|
266
|
-
closedAt: { var: "$
|
|
291
|
+
closedAt: { var: "$ordinal" },
|
|
267
292
|
reason: {
|
|
268
293
|
if: [
|
|
269
294
|
{ "!": [{ var: "state.highBidder" }] },
|