Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
85 changes: 85 additions & 0 deletions .cdm/cdm.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Auto-generated by cdm install -- do not edit
import type { HexString, SizedHex } from "polkadot-api";

declare module "@parity/cdm-codegen" {
interface CdmContracts {
"@w3s/playground-registry": {
methods: {
getAppCount: { args: []; response: number };
getDomainAt: { args: [index: number]; response: string };
getMetadataUri: { args: [domain: string]; response: string };
getOwner: { args: [domain: string]; response: HexString };
getVisibility: { args: [domain: string]; response: number };
getOwnerAppCount: { args: [owner: HexString]; response: number };
getOwnerDomainAt: { args: [owner: HexString, index: number]; response: string };
getSudo: { args: []; response: HexString };
isAdmin: { args: [addr: HexString]; response: boolean };
isBlacklisted: { args: [account: HexString]; response: boolean };
getPoints: { args: [account: HexString]; response: bigint };
getApps: { args: [start: number, count: number]; response: { total: number; scanned: number; entries: { index: number; domain: string; metadata_uri: string; owner: HexString; visibility: number; publisher: HexString }[] } };
getStarCount: { args: [domain: string]; response: number };
getModCount: { args: [domain: string]; response: number };
getLineageCount: { args: []; response: number };
getLineage: { args: [start: number, count: number]; response: { child: string; source: string }[] };
hasStarred: { args: [voter: HexString, domain: string]; response: boolean };
getAppData: { args: [domains: string[], voter: HexString]; response: { domain: string; metadata_uri: string; owner: HexString; visibility: number; publisher: HexString; star_count: number; mod_count: number; has_starred: boolean }[] };
getPointBreakdown: { args: [account: HexString]; response: { mod_points: bigint; star_points: bigint; total: bigint } };
isPinned: { args: [domain: string]; response: boolean };
getPinnedApps: { args: []; response: { index: number; domain: string; metadata_uri: string; owner: HexString; visibility: number; publisher: HexString }[] };
getBuilderCount: { args: []; response: number };
getBuilders: { args: [start: number, count: number]; response: { total: number; scanned: number; entries: { account: HexString; score: bigint }[] } };
pin: { args: [domain: string]; response: undefined };
unpin: { args: [domain: string]; response: undefined };
star: { args: [domain: string]; response: undefined };
publish: { args: [domain: string, metadata_uri: string, visibility: number, modded_from: string]; response: undefined };
setVisibility: { args: [domain: string, visibility: number]; response: undefined };
unpublish: { args: [domain: string]; response: undefined };
addAdmin: { args: [admin: HexString]; response: undefined };
removeAdmin: { args: [admin: HexString]; response: undefined };
adminSetDeployAwardCount: { args: [account: HexString, count: number]; response: undefined };
adminSetAppSocialCounts: { args: [domain: string, star_count: number, mod_count: number]; response: undefined };
setBlacklisted: { args: [accounts: HexString[], value: boolean]; response: undefined };
setFrozen: { args: [value: boolean]; response: undefined };
isFrozen: { args: []; response: boolean };
setVerifier: { args: [verifier: HexString]; response: undefined };
getVerifier: { args: []; response: HexString };
importApp: { args: [domain: string, owner: HexString, publisher: HexString, visibility: number, metadata_uri: string]; response: undefined };
importApps: { args: [apps: { domain: string; owner: HexString; publisher: HexString; visibility: number; metadata_uri: string }[]]; response: undefined };
importPinned: { args: [domain: string]; response: undefined };
importLineage: { args: [entries: { child: string; source: string }[]]; response: undefined };
importPoints: { args: [entries: { account: HexString; total: bigint }[]]; response: undefined };
importSocialCounts: { args: [entries: { domain: string; star_count: number; mod_count: number }[]]; response: undefined };
};
};
"@w3s/playground-identity": {
methods: {
setIdentity: { args: [root_pubkey: SizedHex<32>, signature: number[]]; response: undefined };
clearIdentity: { args: []; response: undefined };
isVerified: { args: [account: HexString]; response: boolean };
rootOf: { args: [account: HexString]; response: SizedHex<32> };
getRootAccount: { args: [account: HexString]; response: SizedHex<32> };
getRootAccounts: { args: [accounts: HexString[]]; response: SizedHex<32>[] };
adminSetIdentity: { args: [account: HexString, root_pubkey: SizedHex<32>]; response: undefined };
adminClearIdentity: { args: [account: HexString]; response: undefined };
addAdmin: { args: [admin: HexString]; response: undefined };
removeAdmin: { args: [admin: HexString]; response: undefined };
setFrozen: { args: [value: boolean]; response: undefined };
importIdentities: { args: [accounts: HexString[], roots: SizedHex<32>[]]; response: undefined };
};
};
"@w3s/playground-open-verifier": {
methods: {
isVerified: { args: [_account: HexString]; response: boolean };
rootOf: { args: [account: HexString]; response: SizedHex<32> };
getRootAccount: { args: [account: HexString]; response: SizedHex<32> };
getRootAccounts: { args: [accounts: HexString[]]; response: SizedHex<32>[] };
faucet: { args: []; response: undefined };
canClaim: { args: [account: HexString]; response: boolean };
lastClaimAt: { args: [account: HexString]; response: number };
setFrozen: { args: [value: boolean]; response: undefined };
getSudo: { args: []; response: HexString };
isFrozen: { args: []; response: boolean };
};
};
}
}
85 changes: 85 additions & 0 deletions .cdm/contracts.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Auto-generated by cdm install -- do not edit
import type { HexString, SizedHex } from "polkadot-api";

declare module "@parity/product-sdk-contracts" {
interface Contracts {
"@w3s/playground-registry": {
methods: {
getAppCount: { args: []; response: number };
getDomainAt: { args: [index: number]; response: string };
getMetadataUri: { args: [domain: string]; response: string };
getOwner: { args: [domain: string]; response: HexString };
getVisibility: { args: [domain: string]; response: number };
getOwnerAppCount: { args: [owner: HexString]; response: number };
getOwnerDomainAt: { args: [owner: HexString, index: number]; response: string };
getSudo: { args: []; response: HexString };
isAdmin: { args: [addr: HexString]; response: boolean };
isBlacklisted: { args: [account: HexString]; response: boolean };
getPoints: { args: [account: HexString]; response: bigint };
getApps: { args: [start: number, count: number]; response: { total: number; scanned: number; entries: { index: number; domain: string; metadata_uri: string; owner: HexString; visibility: number; publisher: HexString }[] } };
getStarCount: { args: [domain: string]; response: number };
getModCount: { args: [domain: string]; response: number };
getLineageCount: { args: []; response: number };
getLineage: { args: [start: number, count: number]; response: { child: string; source: string }[] };
hasStarred: { args: [voter: HexString, domain: string]; response: boolean };
getAppData: { args: [domains: string[], voter: HexString]; response: { domain: string; metadata_uri: string; owner: HexString; visibility: number; publisher: HexString; star_count: number; mod_count: number; has_starred: boolean }[] };
getPointBreakdown: { args: [account: HexString]; response: { mod_points: bigint; star_points: bigint; total: bigint } };
isPinned: { args: [domain: string]; response: boolean };
getPinnedApps: { args: []; response: { index: number; domain: string; metadata_uri: string; owner: HexString; visibility: number; publisher: HexString }[] };
getBuilderCount: { args: []; response: number };
getBuilders: { args: [start: number, count: number]; response: { total: number; scanned: number; entries: { account: HexString; score: bigint }[] } };
pin: { args: [domain: string]; response: undefined };
unpin: { args: [domain: string]; response: undefined };
star: { args: [domain: string]; response: undefined };
publish: { args: [domain: string, metadata_uri: string, visibility: number, modded_from: string]; response: undefined };
setVisibility: { args: [domain: string, visibility: number]; response: undefined };
unpublish: { args: [domain: string]; response: undefined };
addAdmin: { args: [admin: HexString]; response: undefined };
removeAdmin: { args: [admin: HexString]; response: undefined };
adminSetDeployAwardCount: { args: [account: HexString, count: number]; response: undefined };
adminSetAppSocialCounts: { args: [domain: string, star_count: number, mod_count: number]; response: undefined };
setBlacklisted: { args: [accounts: HexString[], value: boolean]; response: undefined };
setFrozen: { args: [value: boolean]; response: undefined };
isFrozen: { args: []; response: boolean };
setVerifier: { args: [verifier: HexString]; response: undefined };
getVerifier: { args: []; response: HexString };
importApp: { args: [domain: string, owner: HexString, publisher: HexString, visibility: number, metadata_uri: string]; response: undefined };
importApps: { args: [apps: { domain: string; owner: HexString; publisher: HexString; visibility: number; metadata_uri: string }[]]; response: undefined };
importPinned: { args: [domain: string]; response: undefined };
importLineage: { args: [entries: { child: string; source: string }[]]; response: undefined };
importPoints: { args: [entries: { account: HexString; total: bigint }[]]; response: undefined };
importSocialCounts: { args: [entries: { domain: string; star_count: number; mod_count: number }[]]; response: undefined };
};
};
"@w3s/playground-identity": {
methods: {
setIdentity: { args: [root_pubkey: SizedHex<32>, signature: number[]]; response: undefined };
clearIdentity: { args: []; response: undefined };
isVerified: { args: [account: HexString]; response: boolean };
rootOf: { args: [account: HexString]; response: SizedHex<32> };
getRootAccount: { args: [account: HexString]; response: SizedHex<32> };
getRootAccounts: { args: [accounts: HexString[]]; response: SizedHex<32>[] };
adminSetIdentity: { args: [account: HexString, root_pubkey: SizedHex<32>]; response: undefined };
adminClearIdentity: { args: [account: HexString]; response: undefined };
addAdmin: { args: [admin: HexString]; response: undefined };
removeAdmin: { args: [admin: HexString]; response: undefined };
setFrozen: { args: [value: boolean]; response: undefined };
importIdentities: { args: [accounts: HexString[], roots: SizedHex<32>[]]; response: undefined };
};
};
"@w3s/playground-open-verifier": {
methods: {
isVerified: { args: [_account: HexString]; response: boolean };
rootOf: { args: [account: HexString]; response: SizedHex<32> };
getRootAccount: { args: [account: HexString]; response: SizedHex<32> };
getRootAccounts: { args: [accounts: HexString[]]; response: SizedHex<32>[] };
faucet: { args: []; response: undefined };
canClaim: { args: [account: HexString]; response: boolean };
lastClaimAt: { args: [account: HexString]; response: number };
setFrozen: { args: [value: boolean]; response: undefined };
getSudo: { args: []; response: HexString };
isFrozen: { args: []; response: boolean };
};
};
}
}
22 changes: 22 additions & 0 deletions .changeset/bulletin-deploy-0200.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
"playground-cli": patch
---

Update `bulletin-deploy` to 0.20.0.

Fixes two crashes that ended a deploy after the content was already uploaded.
One of them is a crash we hit in practice: `JSON.parse` on incoming RPC data was
unguarded and threw inside the socket handler, where nothing upstream could
catch it, killing the process mid-deploy. The other is `hasIPFS()` passing when
`ipfs` is installed but was never initialised.

Also brings, from 0.19.x: the storage-deposit floor for registering a name drops
from a hardcoded 200 PAS to 5 PAS (measured cost is ~0.15), registers no longer
revert when the chain moves between dry-run and inclusion, duplicate files in a
bundle upload once instead of twice, an interrupted register no longer strands
the commitment fee, Bulletin re-authorizes on an exhausted-but-unexpired quota,
and deploying refuses to silently fall back to the public dev key when a stored
session can't be read.

Additive for us: `deploy()`'s signature is unchanged, every option we pass still
exists, and the log banners the progress bar parses are intact.
23 changes: 23 additions & 0 deletions .changeset/fix-dotns-generation-drift.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
"playground-cli": patch
---

Fix deploys failing with `Contract execution would revert during startingPrice on POP_RULES`.

The DotNS contracts ship in ABI *generations* that are redeployed behind the same
contract addresses, and roll out per environment rather than per release. Generation
`v0.5.8-rc1` removed `PopRules.startingPrice()`, so the pinned `bulletin-deploy@0.15.0`
— which only knows the older generation and calls that function unconditionally — hit a
revert on paseo-next-v2 for every deploy, dev mode included. Because the addresses never
changed, this was invisible to any version diff of `environments.json`.

Bumps `bulletin-deploy` to `0.18.4`, which probes the live generation at connect time and
supports all three.

Also fixes the domain-availability preflight, which constructed `DotNS` and connected with
only an RPC URL. Without a contract map it fell back to built-in defaults whose `POP_RULES`
has no code on this network, so 0.16+'s generation probe failed with "No contract deployed
at this address". It now resolves the env's contracts from bulletin-deploy's own
`environments.json` and passes them (plus `environmentId`) to `connect()`, matching what the
deploy path already did. The divergence guard in `config.test.ts` now asserts that contract
map exists upstream, so a catalog change fails in CI rather than mid-deploy.
20 changes: 20 additions & 0 deletions .changeset/gate-asks-wired-verifier.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"playground-cli": patch
---

Ask the personhood verifier the registry actually uses before blocking a
command.

`playground deploy`, `deploy-all`, `mod` and `decentralize` refused with
"Join the competition first" for users whose publish the chain would have
accepted. The gate read `getRootAccount` from the identity spine, but the
registry does not consult the spine — it consults whatever `set_verifier`
names, which on the current deployment is an open verifier that accepts every
account. The CLI was enforcing a stricter rule than the chain, against a
different contract.

The gate now resolves `registry.getVerifier()` and calls `isVerified` on that
address, so it is correct both today and on a competition deployment that
wires the spine, with no flag to keep in sync. It asks the verifier a
question rather than comparing its address — an address comparison would be
correct only until the next verifier implementation.
21 changes: 21 additions & 0 deletions .changeset/product-id-follows-env-tld.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
"playground-cli": minor
---

Derive the product account from an environment-scoped product id
(`playground.paseo` on paseo-next-v2) instead of a fixed `playground.dot`.

This is an identity migration, not a cosmetic change: the product id is an
input to the account derivation, so **your product account address changes**.
Apps published from the CLI before this release are owned by the old address
and will no longer show as yours; anything keyed to the old product id (cached
subtrees, the SDK allowance cache under `~/.polkadot-apps/`) is simply not
found under the new one and is re-granted at your next `playground login`.

The change is required for the CLI to work at all against a phone on a
`paseo` environment. The mobile host validates the product id against its own
TLD and drops a mismatch silently, so a `.dot` id produced no prompt, no error
and no reply — only a ~180 second timeout. It also keeps the CLI and the
playground web app on one identity: the app already ships the
environment-suffixed form, and two different ids for the same person would
split app ownership and XP across two accounts.
32 changes: 32 additions & 0 deletions .changeset/rfc0022-product-accounts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
"playground-cli": minor
---

Fix QR pairing, and sign as the RFC-0022 product account.

`playground login` has been unable to pair with current phones since
mid-August: `@novasamatech/host-papp` 0.9.0 moved the pairing envelope from
P-256/AES-GCM to X25519/ChaCha20-Poly1305, shrinking the device key from 65 to
32 bytes. The handshake codec is fixed-width, so there was no graceful
degrade — iOS reported "Something went wrong" and Android "invalid QR code".
Moving to `@parity/product-sdk-terminal@0.10.0` (host-papp 0.10.0) puts the CLI
back on the wire both shipping apps speak.

The same release changes how the product account is derived. RFC-0022 places it
at `//product//{productId}/{index}`, where the two `//product//{productId}`
junctions are HARD — and a public key cannot cross a hard junction, so the
account is now derived from a subtree key the wallet provides rather than from
the session's root key locally.

**Your product account address changes, and you must pair again.** Run
`playground logout` and then `playground login`. Apps published from the old
address stay owned by it; allowances and PGAS are re-granted at the next login.
The new derivation is what current phones and the playground web app already
use, so this brings the CLI back into agreement with them rather than away.

Deploy also stops presenting a retry as progress. The phone-approval counter
was counting signature *requests*, so a request that timed out and was re-sent
appeared as the next step — and contradicted the "Phone approvals expected"
plan, which counts operations. A deploy could print "step 2: Link content"
while the plan said step 2 was the registry publish. Repeats are now labelled
as retries, with the remedy worth checking when no prompt appeared at all.
Loading
Loading