Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
226 commits
Select commit Hold shift + click to select a range
9de6dac
feat(platform)!: dpns contract v3 checks name registration with schem…
QuantumExplorer Oct 8, 2026
08a5679
fix(platform): a pre-upgrade preorder meets only a one-block minimum age
QuantumExplorer Oct 8, 2026
7fa7b0a
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer Oct 8, 2026
521761b
test(sdk): pin the dpns preorder hash of a mixed-case parent domain name
QuantumExplorer Oct 8, 2026
bdc9d9e
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer Oct 8, 2026
d3518c7
chore(contract): shorten the dpns v3 schema descriptions
QuantumExplorer Oct 9, 2026
d93f498
feat(platform)!: dpns v3 preorders are unique per owner and hash the …
QuantumExplorer Oct 9, 2026
e6c1911
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer Oct 9, 2026
b66668f
fix(sdk): hash DPNS preorders against the contract the network stores
QuantumExplorer Oct 9, 2026
fbd02c9
fix(sdk): take the DPNS contract only from a response proved at the p…
QuantumExplorer Oct 9, 2026
b720af0
fix(drive): seed the block cache with the contract a rebuild stores
QuantumExplorer Oct 9, 2026
51403d3
fix(sdk): skip a DPNS contract response when the SDK version moved me…
QuantumExplorer Oct 9, 2026
4905cf3
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer Oct 9, 2026
1f1a8b0
feat(contract): write the DPNS v3 byte arrays with the type shorthands
QuantumExplorer Oct 9, 2026
45309b9
fix(platform): DPNS v3 review fixes
QuantumExplorer Oct 9, 2026
a9b1ee5
refactor(dpp): read a reference's findBy hash key through one accessor
QuantumExplorer Oct 9, 2026
0e3ae00
test(sdk): give the records.identity refusal spec two distinct identi…
QuantumExplorer Oct 9, 2026
c2d30d9
docs(book): the findBy function exception for $ownerId; DPNS preorder…
QuantumExplorer Oct 9, 2026
b43fcec
test(drive): run the protocol 13 halves of three tests on DPNS v2
QuantumExplorer Oct 9, 2026
c158a7d
fix(sdk): parse a proof the SDK's version can not read under the vers…
QuantumExplorer Oct 9, 2026
3961808
Merge branch 'v5.0-dev' into claude/wizardly-driscoll-44c981
QuantumExplorer Oct 9, 2026
521bfa2
test(sdk): cover the protocol version fallback through the quorum key…
QuantumExplorer Oct 10, 2026
193c42f
test(sdk): fetch a missing quorum key and read the proof again throug…
QuantumExplorer Oct 10, 2026
35696a2
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer Oct 11, 2026
4be5d8c
Merge remote-tracking branch 'origin/v5.0-dev' into claude/wizardly-d…
QuantumExplorer Oct 11, 2026
759d679
feat(platform)!: dpns v3 preorders hash the owner and the name, witho…
QuantumExplorer Oct 11, 2026
aaa0bb7
fix(sdk): dpns registration decodes under the contract it built again…
QuantumExplorer Oct 11, 2026
b1ae90f
fix(wasm-sdk): the trusted context forwards a registered contract to …
QuantumExplorer Oct 11, 2026
ec975f7
Merge branch 'v5.0-dev' into claude/wizardly-driscoll-44c981
QuantumExplorer Oct 12, 2026
8a35b1a
Merge branch 'v5.0-dev' into claude/wizardly-driscoll-44c981
QuantumExplorer Oct 12, 2026
a7e6bf7
Merge v5.1-dev (with v5.0-dev) into the DPNS v3 branch
QuantumExplorer Oct 13, 2026
1cfe150
feat(platform)!: move DPNS v3 to protocol version 15 and choose the f…
QuantumExplorer Oct 13, 2026
4146766
fix(drive-abci): keep DPNS v3 for its rebuild on an upgrade that skip…
QuantumExplorer Oct 13, 2026
388dd5f
Merge v5.1-dev into the DPNS v3 branch
QuantumExplorer Oct 20, 2026
e46c134
feat(platform)!: hold a DPNS name to the preorders a reveal reads, wi…
QuantumExplorer Oct 21, 2026
b9eecc3
fix(sdk): delete a pending DPNS preorder that expires before its reve…
QuantumExplorer Oct 21, 2026
0541601
test(drive-abci): run the contest-fund upgrade test at the version it…
QuantumExplorer Oct 21, 2026
823e3af
test(drive-abci): re-pin the nullifier batch guard roots for the DPNS…
QuantumExplorer Oct 21, 2026
7a92326
fix(sdk): leave the DPNS records.identity rule to DPP in js-dash-sdk
QuantumExplorer Oct 21, 2026
97c7e85
test(sdk): cover the public DPNS registration up to its pending-preor…
QuantumExplorer Oct 21, 2026
b3db3ce
fix(sdk): js-dash-sdk stops on an expiring pending DPNS preorder inst…
QuantumExplorer Oct 21, 2026
5e53930
test(sdk): judge a pending DPNS preorder at the time its response rep…
QuantumExplorer Oct 21, 2026
082c561
feat(platform)!: tradeable tokens (PV15)
QuantumExplorer Oct 21, 2026
e3aceb1
feat(platform)!: token marketplace escrow trees and token market cont…
QuantumExplorer Oct 21, 2026
b7bd591
feat(platform)!: token marketplace listings (PV15)
QuantumExplorer Oct 21, 2026
10c1397
fix(drive-abci): refuse a tradeable non-transferable token in check_tx
QuantumExplorer Oct 21, 2026
07215d4
Merge branch 'claude/token-market-trade-mode' into claude/token-marke…
QuantumExplorer Oct 21, 2026
2ed1dad
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 21, 2026
e31796b
refactor(drive-abci): check listings' state-free rules in check_tx
QuantumExplorer Oct 21, 2026
9c128e6
fix(swift-sdk): keep a Tradeable token tradeable when a contract is p…
QuantumExplorer Oct 21, 2026
5072cc3
Merge branch 'claude/token-market-trade-mode' into claude/token-marke…
QuantumExplorer Oct 21, 2026
3df38e3
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 21, 2026
c7f7fb9
fix(platform): token market review round 1
QuantumExplorer Oct 21, 2026
853b4a6
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 21, 2026
3b12a5b
fix(drive): pass the listing escrow its batch's earlier operations
QuantumExplorer Oct 21, 2026
d85d2c2
fix(platform): token market review round 2
QuantumExplorer Oct 22, 2026
57d0050
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
47b4e5c
fix(platform): token listings review round 1
QuantumExplorer Oct 22, 2026
94ef903
fix(drive): keep the escrow's Tokens layer estimate whichever operati…
QuantumExplorer Oct 22, 2026
2248eec
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
cd848aa
fix(drive): keep the escrows' root estimate whichever balance operati…
QuantumExplorer Oct 22, 2026
e6620ea
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
cfe9af5
fix(platform): token market review round 4
QuantumExplorer Oct 22, 2026
a682542
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
ce96fcb
fix(drive): prove a listing's placement after it is partly filled
QuantumExplorer Oct 22, 2026
90918f4
fix(drive): merge two estimates of one layer at one depth by their cost
QuantumExplorer Oct 22, 2026
f4a0e71
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
abbd7e8
fix(drive): price equal-depth layer descriptions with GroveDB's estim…
QuantumExplorer Oct 22, 2026
d4ab767
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
3bcc656
fix(platform): a listing signs the decimals its price is at
QuantumExplorer Oct 22, 2026
bcacf6b
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 22, 2026
c5e631e
Merge branch 'claude/token-market-trade-mode' into claude/token-marke…
QuantumExplorer Oct 22, 2026
85d7fc9
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
3f92254
chore(token-market-contract): version 5.0.0-rc.7 like the rest of the…
QuantumExplorer Oct 22, 2026
95fcf70
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
6be9098
test(drive-abci): re-pin shielded fee estimates for protocol 15 batch…
QuantumExplorer Oct 22, 2026
c39d28c
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
39c9b05
fix(drive): skip pricing identical layer descriptions; depth proof te…
QuantumExplorer Oct 22, 2026
494cea1
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 22, 2026
cd0380f
fix(drive): refuse a listing placement carrying group information in …
QuantumExplorer Oct 22, 2026
6bb00b0
fix(drive): a marketplace proof binds the token id to its contract an…
QuantumExplorer Oct 22, 2026
3127618
fix(platform): listing review round 4
QuantumExplorer Oct 22, 2026
f94a22e
test(platform): pin listing width bounds and the revision byte a fill…
QuantumExplorer Oct 23, 2026
88599ae
test(drive-abci): the revision-byte test uses a token that keeps no t…
QuantumExplorer Oct 23, 2026
1cc8a23
fix(platform): listing review round 5
QuantumExplorer Oct 23, 2026
2060a1b
fix(drive): a listing pays for the hash that derives its id
QuantumExplorer Oct 23, 2026
7c5b4c8
Merge branch 'v5.1-dev' into claude/token-market-escrow-contract
QuantumExplorer Oct 23, 2026
4767255
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 23, 2026
860dac3
Merge branch 'v5.1-dev' into claude/token-market-escrow-contract
QuantumExplorer Oct 23, 2026
945b9ef
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 23, 2026
ce1baf5
feat(platform)!: orders keep no $createdAtBlockHeight and no expiresAt
QuantumExplorer Oct 23, 2026
ad0d84f
fix(drive): price layer descriptions only when their depths tie; the …
QuantumExplorer Oct 23, 2026
c896407
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 23, 2026
10f4c70
feat(platform)!: listings carry no expiry
QuantumExplorer Oct 23, 2026
5fe8a03
docs(platform): a fill's absolute escrow write depends on the one-tra…
QuantumExplorer Oct 23, 2026
26c35af
fix(drive): order reads add their cost with checked fee arithmetic
QuantumExplorer Oct 23, 2026
6cb5ac7
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 25, 2026
b97c646
chore: token-market-contract follows the 5.0.0-rc.8 release bump
QuantumExplorer Oct 25, 2026
2483383
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 25, 2026
1f9875c
docs(platform-version): renumber the token listings note after the merge
QuantumExplorer Oct 25, 2026
5f93697
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 25, 2026
22fc30a
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 25, 2026
d99411d
docs(platform-version): renumber the Token listings note after the merge
QuantumExplorer Oct 25, 2026
436c30c
docs(platform-version): the token market contract's table entry cites…
QuantumExplorer Oct 25, 2026
8e37f1b
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 25, 2026
c15044a
fix(dpp): orders of tokens with 39 or more decimals are priced, not r…
QuantumExplorer Oct 25, 2026
2eb9666
fix(drive): layer descriptions that tie on depth and price are ordere…
QuantumExplorer Oct 25, 2026
be63e4c
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 25, 2026
848d3bc
docs(platform-version): note 9 records how orders of tokens with 39 o…
QuantumExplorer Oct 25, 2026
a5f9498
docs(platform-version): the DPNS note no longer says the data trigger…
QuantumExplorer Oct 26, 2026
6d05060
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 26, 2026
affc1e2
fix(drive): keeping the deeper layer description compares every kind …
QuantumExplorer Oct 26, 2026
c589b9a
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 26, 2026
9685732
fix(drive): EstimatedLevel is imported by the tests that use it
QuantumExplorer Oct 26, 2026
73f1da2
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 26, 2026
459a584
fix(sdk): the trusted provider serves no token market contract before…
QuantumExplorer Oct 26, 2026
7b69cae
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 26, 2026
d00de30
docs(platform-version): name every slot PLATFORM_V15 changes for the …
QuantumExplorer Oct 26, 2026
74e517b
fix(drive): merge a shared layer's descriptions into one covering bot…
QuantumExplorer Oct 26, 2026
18e9f38
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 26, 2026
5a98f00
fix(sdk): the trusted provider's token market gate uses the canonical id
QuantumExplorer Oct 26, 2026
01a6340
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 26, 2026
b4e1c6f
feat(platform)!: token market orders no longer record a minimum fill
QuantumExplorer Oct 27, 2026
6b2b8fd
feat(platform)!: generatedFrom sys.tokens.decimals generates a token'…
QuantumExplorer Oct 27, 2026
d29e489
Merge branch 'claude/generated-from-token-decimals' into claude/token…
QuantumExplorer Oct 27, 2026
f2821cf
feat(platform)!: token market orders generate their decimals from the…
QuantumExplorer Oct 27, 2026
6f00eff
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 27, 2026
21fa8b1
docs(platform-version): the listings note is note 10 of protocol vers…
QuantumExplorer Oct 27, 2026
22a4162
feat(platform)!: a listing takes its token's minimum fill and decimals
QuantumExplorer Oct 27, 2026
aaba891
docs(platform-version): indent note 10's continuation under its two-d…
QuantumExplorer Oct 27, 2026
59fba48
test(drive-abci): re-pin the shielded characterization roots
QuantumExplorer Oct 27, 2026
ebc2b5c
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 27, 2026
65e4ddc
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 28, 2026
eb5ddbe
test(dpp): the system contract size cap test covers the token market …
QuantumExplorer Oct 28, 2026
978a91a
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 28, 2026
3f80b80
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 28, 2026
3751e86
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 28, 2026
fcc1363
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 30, 2026
d3f4093
style(platform-version): format the drive version 10 table
QuantumExplorer Oct 30, 2026
28f34c2
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Oct 30, 2026
a38389e
Merge remote-tracking branch 'origin/claude/token-market-escrow-contr…
QuantumExplorer Oct 30, 2026
1589b40
docs(platform-version): renumber the token listings note to 14
QuantumExplorer Oct 30, 2026
50331e9
fix(drive)!: estimate a batch's fee the same whatever its operations'…
QuantumExplorer Oct 30, 2026
749ac6e
Merge claude/order-independent-batch-estimates (#5688) into claude/to…
QuantumExplorer Oct 30, 2026
ff62705
Merge claude/token-market-escrow-contract into claude/token-market-li…
QuantumExplorer Oct 30, 2026
a8ae269
docs(platform-version): renumber the token listings note to 15
QuantumExplorer Oct 30, 2026
2177f07
fix(drive): pick a layer's description once the whole batch is described
QuantumExplorer Oct 30, 2026
19ae32d
test(drive): pin apply_drive_operations 1 at protocol version 14
QuantumExplorer Oct 30, 2026
1469762
Merge claude/order-independent-batch-estimates (#5688) into claude/to…
QuantumExplorer Oct 30, 2026
8e24d95
test(drive-abci): describe the estimate pin's generation as it now picks
QuantumExplorer Oct 30, 2026
26ebfe2
Merge claude/order-independent-batch-estimates (#5688) into claude/to…
QuantumExplorer Oct 30, 2026
47ea2a8
Merge claude/token-market-escrow-contract into claude/token-market-li…
QuantumExplorer Oct 30, 2026
2600480
fix(kotlin-example-app): store an unknown token trade mode as NotTrad…
QuantumExplorer Oct 30, 2026
1edb1c0
fix(drive): refuse an estimated operation that leaves no layer map
QuantumExplorer Oct 30, 2026
9a16908
Merge remote-tracking branch 'origin/claude/order-independent-batch-e…
QuantumExplorer Oct 30, 2026
13936e9
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 30, 2026
d4cc944
docs(book): rewrap the batch estimate paragraph
QuantumExplorer Oct 30, 2026
9350332
Merge branch 'claude/order-independent-batch-estimates' into claude/t…
QuantumExplorer Oct 30, 2026
1959990
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 30, 2026
c04c172
Merge remote-tracking branch 'origin/v5.1-dev' into claude/order-inde…
QuantumExplorer Oct 30, 2026
5f5198f
Merge #5688 (v5.1-dev with decision proposals) into claude/token-mark…
QuantumExplorer Oct 30, 2026
9a25d69
Merge claude/token-market-escrow-contract (decision proposals) into c…
QuantumExplorer Oct 30, 2026
8d31dbf
docs(platform-version): point the DPNS bindings note at note 15
QuantumExplorer Oct 31, 2026
096a2cf
test(drive-abci): pin protocol 15 fees with both new genesis contracts
QuantumExplorer Oct 31, 2026
26337eb
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 31, 2026
0c68958
Merge origin/v5.1-dev (private document types) into claude/order-inde…
QuantumExplorer Oct 31, 2026
22de2dc
Merge #5688 (v5.1-dev with private document types) into claude/token-…
QuantumExplorer Oct 31, 2026
7fb2733
Merge claude/token-market-escrow-contract (private document types) in…
QuantumExplorer Oct 31, 2026
eb27187
fix(drive)!: keep every layer description an estimate's writes give, …
QuantumExplorer Oct 31, 2026
db23b91
Merge claude/order-independent-batch-estimates (EstimatedLayers) into…
QuantumExplorer Oct 31, 2026
ea186c5
docs(drive): describe the estimate parameters as EstimatedLayers
QuantumExplorer Oct 31, 2026
ce348ac
Merge branch 'claude/order-independent-batch-estimates' into claude/t…
QuantumExplorer Oct 31, 2026
e0a4d59
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 31, 2026
c9db39e
docs(drive): name EstimatedLayers in the estimate tests' comments
QuantumExplorer Oct 31, 2026
53096e3
Merge branch 'claude/order-independent-batch-estimates' into claude/t…
QuantumExplorer Oct 31, 2026
c8e90d4
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 31, 2026
eff7694
fix(drive): describe a layer holding subtrees with subtrees in a v15 …
QuantumExplorer Oct 31, 2026
fa9e3b4
Merge branch 'claude/order-independent-batch-estimates' into claude/t…
QuantumExplorer Oct 31, 2026
b92488f
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Oct 31, 2026
ff93005
Merge origin/v5.1-dev (private document stores, repeated schema keys)…
QuantumExplorer Nov 1, 2026
eba2c98
Merge claude/order-independent-batch-estimates (private document stor…
QuantumExplorer Nov 1, 2026
0461f55
Merge branch 'claude/token-market-escrow-contract' into claude/token-…
QuantumExplorer Nov 1, 2026
0c29aa0
fix(drive)!: resolve a batch's estimate from what its writes describe…
QuantumExplorer Nov 1, 2026
e40c37a
refactor(drive): build an estimate with (!apply).then(EstimatedLayers…
QuantumExplorer Nov 1, 2026
e3071db
Merge claude/order-independent-batch-estimates (review 2: resolved es…
QuantumExplorer Nov 1, 2026
535060d
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 1, 2026
707af07
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 1, 2026
7750299
test(drive-abci): pin the rule-free restore fee with the token market…
QuantumExplorer Nov 2, 2026
edc26f4
fix(dpp): read a generated property's token id without decoding a tex…
QuantumExplorer Nov 2, 2026
1b0a79a
refactor(platform-value): bound identifier decoding where the convers…
QuantumExplorer Nov 2, 2026
7e691b5
Merge origin/v5.1-dev (decision proposals, private document types and…
QuantumExplorer Nov 2, 2026
5e4b49b
fix(platform)!: bill the token id hash of a generated decimals and re…
QuantumExplorer Nov 2, 2026
353b550
fix(dpp): read a generated property's token id without decoding a tex…
QuantumExplorer Nov 2, 2026
98c308a
refactor(platform-value): bound identifier decoding where the convers…
QuantumExplorer Nov 2, 2026
24b5783
Merge claude/generated-from-token-decimals (review fixes) into claude…
QuantumExplorer Nov 2, 2026
b9f04dd
docs(platform): end the generatedFrom bullet of CONTRACT_VERSIONS_V7 …
QuantumExplorer Nov 2, 2026
a8ec055
fix(dpp): admit token decimals under an integer maximum past i64 and …
QuantumExplorer Nov 2, 2026
255f108
fix(dpp): leave a rule reading a state-generated property unjudged on…
QuantumExplorer Nov 2, 2026
52fe4e7
Merge claude/generated-from-token-decimals (client pre-check skip, i1…
QuantumExplorer Nov 2, 2026
1f285ea
fix(dpp): pass a client document leaving out required state-generated…
QuantumExplorer Nov 2, 2026
a39f474
Merge claude/generated-from-token-decimals (client schema stand-in fo…
QuantumExplorer Nov 2, 2026
4a60b32
test(token-market-contract): accept an order leaving out the decimals…
QuantumExplorer Nov 2, 2026
4452182
Merge origin/v5.1-dev (verified HTTP context provider, dash-sdk-cxx, …
QuantumExplorer Nov 2, 2026
b122f23
fix(dpp)!: refuse token decimals inside an object declaring const or …
QuantumExplorer Nov 3, 2026
4818cb8
Merge claude/generated-from-token-decimals (token decimals refused in…
QuantumExplorer Nov 3, 2026
b6ca1e5
fix(sdk): serve no token market contract before protocol 15 from the …
QuantumExplorer Nov 3, 2026
1a1347c
fix(dpp): read the keywords beside a $ref when admitting token decima…
QuantumExplorer Nov 3, 2026
c776544
Merge claude/generated-from-token-decimals (keywords beside a $ref in…
QuantumExplorer Nov 3, 2026
deb2477
fix(dpp)!: declare token decimals and the objects holding them in pla…
QuantumExplorer Nov 3, 2026
8845695
Merge claude/generated-from-token-decimals (token decimals declared i…
QuantumExplorer Nov 3, 2026
653ff71
test(dpp): refuse token decimals declared with a $ref beside a type n…
QuantumExplorer Nov 3, 2026
586c870
Merge claude/generated-from-token-decimals (type beside a $ref regres…
QuantumExplorer Nov 3, 2026
25fa783
Merge origin/v5.1-dev (#5604 squash, #5476, #5712, #5726) into claude…
QuantumExplorer Nov 3, 2026
4c77f75
test(drive): resolve a layer kept deeper with the nodes of the descri…
QuantumExplorer Nov 3, 2026
53e231c
test(drive-abci): refuse a signed replace or delete of a stored token…
QuantumExplorer Nov 3, 2026
9931a98
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 3, 2026
536dd06
Merge claude/token-market-escrow-contract (#5526 final head) into cla…
QuantumExplorer Nov 3, 2026
b415c94
Merge origin/v5.1-dev (#5526 squash) into claude/token-market-listings
QuantumExplorer Nov 3, 2026
14e47d7
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 4, 2026
1b4cce0
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 4, 2026
0ca14b6
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 4, 2026
8991caf
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 4, 2026
1e76fd9
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 5, 2026
4af1b0f
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 6, 2026
f06ad6b
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 6, 2026
04a4b57
Merge remote-tracking branch 'origin/v5.1-dev' into claude/token-mark…
QuantumExplorer Nov 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 107 additions & 9 deletions book/src/data-model/token-marketplace.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ price and each purchase mints new tokens and pays the contract owner.

## Making a token tradeable

A token opts in through its `marketplaceRules`:
A token opts in through its `marketplaceRules`, with its minimum fill:

```json
"marketplaceRules": {
"$formatVersion": "0",
"tradeMode": "Tradeable",
"tradeMode": { "Tradeable": { "minFill": 1000 } },
"tradeModeChangeRules": {
"$formatVersion": "0",
"authorizedToMakeChange": { "$type": "contractOwner" },
Expand All @@ -28,6 +28,16 @@ A token opts in through its `marketplaceRules`:
}
```

`minFill` is the smallest amount, in base units, a fill of one of the token's orders takes,
unless it takes everything the order has left, and the least a fill leaves open: no order is
ever left holding less than a trade. An order of less is refused when it is placed
(`InvalidTokenOrderFillRangeError`, 10463, the minimum and the amount). It is the token's, not the
order's: every fill reads it as the token has it when the fill executes, so raising or lowering it
(a `MarketplaceTradeMode` configuration update, under `tradeModeChangeRules`) applies to the open
orders too. An order already holding less than a raised minimum is still filled, whole. It is from
1 to `i64::MAX` (`InvalidTokenOrderFillRangeError` on contract create or update, or on the
configuration update).

| `tradeMode` | Meaning |
|---|---|
| `NotTradeable` (the default) | Holders cannot list the token or make offers for it on Platform |
Expand Down Expand Up @@ -65,13 +75,19 @@ offer), each with three indexes:

Each side sums what it holds in escrow, so the sums cannot overflow: the tokens listed never exceed
the token's supply, and the credits offered never exceed the credits on Platform. Every integer of
an order is a signed 8-byte value, so a partial fill rewrites an order without changing its stored
size.

An order's price is in credits per whole token, and each order records the token's decimals when
it was placed (`decimals`). Every fill prices the order at that scale, so a later change to the
token's decimals (a `Conventions` update) changes neither what an open listing costs nor what an
open offer pays. The `book` and `depth` indexes keep each scale apart (`tokenId`, then `decimals`,
an order is a signed 8-byte value, so a partial fill rewrites them without changing their size. The
document's `$revision` is a variable-length integer, 7 bits to a byte: a fill that takes an order's
revision past one of those widths (from 127 to 128, then from 16,383 to 16,384, and so on) adds a
byte, and no other fill adds storage.

An order's price is in credits per whole token, so the token's decimals set what it is worth. The
signer names no decimals: each order records the token's decimals as the token has them when the
order is placed (`decimals`, declared `generatedFrom` `sys.tokens.decimals` of `tokenId`, so it
is generated when the order is created and kept after). Every fill prices the order at that
scale, so a later change to the token's decimals (a `Conventions` update) changes neither what an
open listing costs nor what an open offer pays. Whoever controls the token's conventions can
change its decimals while a signed order waits to execute, and the order is then placed at the new
scale: a listing asks, and an offer escrows, its price per whole token of the new decimals. The `book` and `depth` indexes keep each scale apart (`tokenId`, then `decimals`,
then `price`), so a book query and a depth sum name the token's decimals and never mix prices of
different scales. After a token changes its decimals, the orders placed before the change stay
under the old decimals until they close; a client showing them alongside the new ones queries both
Expand All @@ -90,3 +106,85 @@ What an order holds is kept outside the contract:
- The credits of an offer sit in `[PreFundedSpecializedBalances, PREFUNDED_BALANCES_FOR_TOKEN_ORDERS]`,
a SumTree keyed by order id, which the credit conservation check already counts.


## Listings

Three token transitions of a batch work with listings. Each is refused before protocol version
15, unpaid, by the batch's `is_allowed` gate (`StateTransitionNotActiveError` 10603, as
`TokenPlaceAsk`, `TokenFillAsk` or `TokenCancelOrder`).

| Transition | Fields | Effect |
|---|---|---|
| `TokenPlaceAsk` | `amount`, `price` | Moves `amount` base units from the seller's balance into escrow and records an `ask` |
| `TokenFillAsk` | `orderId`, `minAmount`, `maxAmount`, `maxTotalPrice` | Moves part or all of the listing from escrow to the buyer, and its cost from the buyer's credits to the seller's |
| `TokenCancelOrder` | `orderId`, `side` | Returns what an order holds to its owner and deletes the order |

A listing's id follows from the token, the seller and the transition's identity contract nonce
(`TokenOrderSide::order_id`), so a client knows it before the listing is placed.

### Price and partial fills

`price` is in credits per whole token, 10 to the power of the token's decimals base units. The
listing records those decimals when it is placed and every fill prices it at them, so a later
change to the token's decimals does not change what the rest of the listing costs. A fill
takes as much as it may: everything open, up to `maxAmount`. A listing never keeps less than the
token's `minFill` open, so a fill that would leave less takes less, leaving exactly `minFill`; a
fill that does not take everything open takes at least `minFill`. The fill is refused when the
amount it would take is under `minAmount`, or when it costs more than `maxTotalPrice`.

Each fill pays the change in the listing's running total rounded up, so splitting a purchase
never changes what it costs in all:

```text
2 decimals, 333 credits per token (3.33 per base unit), a listing of 3 base units
one fill of 3: 10 credits
three fills of 1: 4 + 3 + 3 = 10 credits
```

The rounding favours the seller and is never more than one credit per fill.

### Rules

| Rule | Refused with |
|---|---|
| `amount` and `price` from 1 to `i64::MAX` | `InvalidTokenAmountError` (10458), `InvalidTokenOrderPriceError` (10462) |
| A fill's `minAmount` from 1 to `maxAmount`, `maxAmount` up to `i64::MAX` | `InvalidTokenOrderFillRangeError` (10463) |
| The contract defines the token | `ContractHasNoTokensError`, `InvalidTokenPositionError` |
| The token is tradeable (to place or fill) | `TokenNotTradeableError` (40750) |
| `amount` at least the token's `minFill`, and what the order is worth at the token's decimals at most `i64::MAX` credits | `InvalidTokenOrderFillRangeError` (10463), `InvalidTokenOrderValueError` (10465) |
| The order is open, for this token | `TokenOrderNotFoundError` (40751) |
| The fill range meets the listing | `TokenOrderFillAmountError` (40753) |
| The fill costs at most `maxTotalPrice` | `TokenOrderPriceLimitError` (40754) |
| Only the order's owner cancels it | `TokenOrderNotOwnedError` (40755) |
| A seller does not fill their own listing | `TokenOrderSelfFillError` (40756) |
| The seller holds `amount` | `IdentityDoesNotHaveEnoughTokenBalanceError` |
| The token is not paused (to place or fill) | `TokenIsPausedError` |
| The seller's account is not frozen (to place or fill), nor the buyer's unless the token allows transfers to frozen balances | `IdentityTokenAccountFrozenError` |

The rules on a transition's own fields (the first two rows) are checked before anything is read and
refused unpaid. The state rules are paid: a refused transition bumps the signer's nonce and charges
the work that ran. The rules that read nothing beyond the contract (a tradeable token, its minimum
fill and what the listing is worth at its decimals) run with the batch's advanced structure, so
check_tx refuses them too. A
cancel has no rule beyond ownership, so an order can always be withdrawn, also when the token is paused, no longer tradeable or the owner's account is frozen. The buyer's credits are
checked with the batch's fees, which count a fill's cost like a direct purchase.

### Storage and proofs

The seller pays the storage of the `ask` and gets it back when the listing closes, by a fill that
takes everything left or by a cancel. A partial fill rewrites the `ask` without changing its size,
so the buyer pays no storage for it beyond their own token balance, except when a fill widens the
listing's `$revision` by a byte (first at revision 128, then at 16,384 and at every further 7
bits): that fill's buyer pays for the byte. The `ask` stays the seller's, so those bytes are
refunded to the seller when the listing closes. Selling a listing charges the seller nothing.

The proof a node returns for each transition:

| Transition | Proves |
|---|---|
| `TokenPlaceAsk` | The `ask` document, holding the listing's terms |
| `TokenFillAsk` | The buyer's token balance |
| `TokenCancelOrder` | That the order's document is gone |

Offers (`bid`) and their fills come with the next transitions of the marketplace. Until then no
offer can exist, and a `TokenCancelOrder` for one finds none.
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ object TokenMaterializer {

// Marketplace rules.
val marketplace = dict.obj("marketplaceRules")
val tradeMode = marketplace?.str("tradeMode") ?: "NotTradeable"
val tradeMode = marketplace?.tradeMode("tradeMode") ?: "NotTradeable"
val tradeModeChange = marketplace?.rule("tradeModeChangeRules")

// History-keeping: nested object or a single boolean for all.
Expand Down Expand Up @@ -208,6 +208,23 @@ object TokenMaterializer {
private fun JsonObject.rule(key: String): ChangeControlRules? =
(this[key] as? JsonObject)?.let(ChangeControlRules::parse)

/** The `TokenTradeMode` variants rs-dpp writes. */
private val TRADE_MODES = setOf("NotTradeable", "Tradeable")

/**
* rs-dpp writes `TokenTradeMode` externally tagged: `NotTradeable` as a
* bare string, and `Tradeable` (protocol version 15) as an object holding
* its fields, `{"Tradeable":{"minFill":1000}}`. The variant name, the
* string or the object's single key, is the mode the column keeps;
* `minFill` is not persisted. Any other name is refused (`null`, which
* the caller stores as `NotTradeable`), so a malformed or newer mode is
* never shown as tradeable. Port of `parseTokenTradeMode` in
* `DataContractParser.swift`, whose `TokenTradeMode(rawValue:)` refuses
* it the same way.
*/
private fun JsonObject.tradeMode(key: String): String? =
(str(key) ?: obj(key)?.keys?.singleOrNull())?.takeIf { it in TRADE_MODES }

/**
* u64-safe supply extraction β€” port of `extractTokenSupply`
* (numbers or strings; decimal string out).
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package org.dashfoundation.example.services.tokens

import org.dashfoundation.dashsdk.persistence.entities.DataContractEntity
import org.dashfoundation.dashsdk.persistence.entities.TokenEntity
import org.junit.Assert.assertEquals
import org.junit.Test

/**
* [TokenMaterializer] coverage for `marketplaceRules.tradeMode`. rs-dpp
* writes `TokenTradeMode` externally tagged: `NotTradeable` as a bare
* string, `Tradeable` (protocol version 15) as an object holding its
* `minFill` (a JSON number, or a decimal string above 2^53 - 1). The
* variant name lands in [TokenEntity.tradeMode]; `minFill` is not kept. Any
* other name is stored as `NotTradeable`.
* Mirrors `DataContractParserTradeModeTests.swift`.
*/
class TokenMaterializerTradeModeTest {

private val contractId = ByteArray(32) { 0xAB.toByte() }

/** [tradeMode] is the raw JSON value of `marketplaceRules.tradeMode`. */
private fun parseSingleToken(tradeMode: String): TokenEntity {
val json = """{"tokens":{"0":{"baseSupply":0,"marketplaceRules":""" +
"""{"${'$'}formatVersion":"0","tradeMode":$tradeMode}}}}"""
val contract = DataContractEntity(
id = contractId,
name = "Fixture",
serializedContract = json.encodeToByteArray(),
networkRaw = 0,
)
val tokens = TokenMaterializer.parse(contract)
assertEquals(1, tokens.size)
return tokens.single()
}

@Test
fun `tradeable object form is stored as Tradeable`() {
val token = parseSingleToken("""{"Tradeable":{"minFill":1000}}""")

assertEquals("Tradeable", token.tradeMode)
}

@Test
fun `tradeable with a string minFill is stored as Tradeable`() {
val token = parseSingleToken("""{"Tradeable":{"minFill":"9223372036854775807"}}""")

assertEquals("Tradeable", token.tradeMode)
}

@Test
fun `bare NotTradeable string stays NotTradeable`() {
val token = parseSingleToken("\"NotTradeable\"")

assertEquals("NotTradeable", token.tradeMode)
}

@Test
fun `an unknown bare mode is stored as NotTradeable`() {
val token = parseSingleToken("\"Auctioned\"")

assertEquals("NotTradeable", token.tradeMode)
}

@Test
fun `an unknown tagged mode is stored as NotTradeable`() {
val token = parseSingleToken("""{"Auctioned":{"minFill":1}}""")

assertEquals("NotTradeable", token.tradeMode)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ data class TokenEntity(
val mintingAllowChoosingDestination: Boolean = true,
/** JSON `TokenDistributionChangeRules` (UI-only). */
val distributionChangeRules: String? = null,
/** `TokenTradeMode.rawValue` ("NotTradeable"). */
/**
* `TokenTradeMode.rawValue`: "NotTradeable" or "Tradeable" (protocol
* version 15). Contract JSON carries `Tradeable` as an object holding its
* `minFill` (`{"Tradeable":{"minFill":1000}}`); only the variant name is
* kept, `minFill` is not persisted.
*/
val tradeMode: String = "NotTradeable",
val tradeModeChangeRules: String? = null,
val mainControlGroupPosition: Int? = null,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::balances::credits::TokenAmount;
use crate::consensus::basic::data_contract::{
NonTransferableTokenShieldedPoolError, NonTransferableTokenTradeableError,
TokenShieldedPoolIncompatibleRulesError,
};
use crate::consensus::basic::state_transition::StateTransitionNotActiveError;
use crate::consensus::basic::token::InvalidTokenOrderFillRangeError;
use crate::consensus::basic::unsupported_version_error::UnsupportedVersionError;
use crate::data_contract::associated_token::token_configuration::accessors::v0::TokenConfigurationV0Getters;
use crate::data_contract::associated_token::token_configuration::accessors::v1::TokenConfigurationV1Getters;
Expand Down Expand Up @@ -82,6 +84,12 @@ impl TokenConfiguration {
.is_tradeable()
}

/// The smallest fill of the token's orders (`marketplaceRules.tradeMode` `Tradeable`'s
/// `minFill`), `None` when the token is not tradeable.
pub fn min_fill(&self) -> Option<TokenAmount> {
self.as_cow_v0().marketplace_rules.trade_mode().min_fill()
}

/// Checks the configuration's format version against the bounds the platform version
/// admits (`dpp.contract_versions.token_versions.token_configuration_format`).
///
Expand Down Expand Up @@ -159,7 +167,8 @@ impl TokenConfiguration {
/// version 15 (`TOKEN_MARKETPLACE_INITIAL_PROTOCOL_VERSION`): below it the mode is refused as
/// not active, the refusal software that predates the marketplace gives by failing to decode
/// it. A tradeable token must also be transferable, since filling a listing or an offer moves
/// the token from one identity to another. Checked on contract create and update.
/// the token from one identity to another, and its minimum fill is from 1 to `i64::MAX`
/// (`InvalidTokenOrderFillRangeError`). Checked on contract create and update.
pub fn validate_marketplace_rules(
&self,
token_contract_position: TokenContractPosition,
Expand Down Expand Up @@ -200,6 +209,16 @@ impl TokenConfiguration {
NonTransferableTokenTradeableError::new(token_contract_position).into(),
);
}
// An order stores its amounts as signed 8-byte values, so no order is larger than
// `i64::MAX`, and a minimum fill of 0 would let a fill take nothing
let largest_order = i64::MAX as TokenAmount;
if let Some(min_fill) = trade_mode.min_fill() {
if min_fill == 0 || min_fill > largest_order {
return SimpleConsensusValidationResult::new_with_error(
InvalidTokenOrderFillRangeError::new(min_fill, largest_order).into(),
);
}
}
SimpleConsensusValidationResult::new()
}

Expand Down Expand Up @@ -1221,7 +1240,7 @@ mod marketplace_rules_tests {
let mut configuration = TokenConfigurationV0::default_most_restrictive();
configuration
.marketplace_rules
.set_trade_mode(TokenTradeMode::Tradeable);
.set_trade_mode(TokenTradeMode::Tradeable { min_fill: 1 });
TokenConfiguration::V0(configuration)
}

Expand Down Expand Up @@ -1290,7 +1309,7 @@ mod marketplace_rules_tests {
configuration.set_transferable(false);

let proposed = configuration.validate_trade_mode(
&TokenTradeMode::Tradeable,
&TokenTradeMode::Tradeable { min_fill: 1 },
0,
PlatformVersion::latest(),
);
Expand All @@ -1302,12 +1321,44 @@ mod marketplace_rules_tests {
));

configuration.apply_token_configuration_item(
TokenConfigurationChangeItem::MarketplaceTradeMode(TokenTradeMode::Tradeable),
TokenConfigurationChangeItem::MarketplaceTradeMode(TokenTradeMode::Tradeable {
min_fill: 1,
}),
);
let applied = configuration.validate_marketplace_rules(0, PlatformVersion::latest());
assert_eq!(applied.errors, proposed.errors);
}

/// A tradeable token's minimum fill is from 1 to the largest order, `i64::MAX`.
#[test]
fn should_refuse_a_minimum_fill_of_0_or_above_the_largest_order() {
let largest_order = i64::MAX as TokenAmount;
for (min_fill, valid) in [
(0, false),
(1, true),
(largest_order, true),
(largest_order + 1, false),
] {
let result = tradeable().validate_trade_mode(
&TokenTradeMode::Tradeable { min_fill },
0,
PlatformVersion::latest(),
);
if valid {
assert!(result.is_valid(), "{min_fill}");
} else {
assert!(
matches!(
result.errors.as_slice(),
[ConsensusError::BasicError(BasicError::InvalidTokenOrderFillRangeError(error))]
if error.min() == min_fill && error.max() == largest_order
),
"{min_fill}: {result:?}"
);
}
}
}

/// Proposing the mode every token may have is never refused.
#[test]
fn should_accept_proposing_not_tradeable_for_a_non_transferable_token() {
Expand Down
Loading
Loading