You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The DKG SDK's Publishing Conviction Account (PCA) write surface — chain-adapter.ts methods, DKGAgent facade methods, daemon HTTP routes /api/pca/*, the response schemas in daemon/routes/pca.ts, and every chain-adapter integration test that exercised PCA — was wired end-to-end to the V9PublishingConvictionAccount.sol contract. The V10DKGPublishingConvictionNFT.sol contract was never reachable from the SDK. After #500 archived V9, the SDK methods became return null stubs and all /api/pca/* writes return HTTP 503 FEATURE_UNAVAILABLE_503.
This is both a hypothesis confirmation (we were testing the wrong contract) and a feature gap (SDK has no path to the live V10 PCA contract). Publishing through V10 PCA NFT does work end-to-end on-chain — KnowledgeAssetsV10.publish() directly invokes the V10 NFT — but nothing in the SDK or daemon can create, fund, or register an agent against a V10 PCA account.
Evidence
1. Pre-archive SDK call sites all resolved the V9 contract
packages/chain/src/archive/evm-adapter-v8-v9-methods.ts (verbatim source preserved from commit 4dc99e6e):
this.contracts.publishingConvictionAccount was populated from Hub.getContractAddress("PublishingConvictionAccount") — the V9 contract key. See evm-adapter.ts:705-709:
try{this.contracts.publishingConvictionAccount=awaitthis.resolveContract('PublishingConvictionAccount');}catch{// PublishingConvictionAccount not deployed — conviction account operations unavailable}
2. V9 vs V10 contract APIs are not just renamed — they are semantically different
DKGAgent.createPublishingConvictionAccount(_amount, _lockEpochs) (packages/agent/src/dkg-agent.ts:3978) carries the V9 lockEpochs parameter — V10 NFT has no per-account lock. This is the smoking gun: even the SDK facade signature was V9-shaped.
3. Daemon route handler is V9-shaped
packages/cli/src/daemon/routes/pca.ts:5-7:
// PCAs are a distinct economic primitive: they're the off-chain// expression of the on-chain `PublishingConvictionAccount` contract,// driven by an operator standing up the runbook fixtures
packages/evm-module/test/v10-e2e-conviction.test.ts Flow 3 — bypasses SDK entirely, instantiates DKGPublishingConvictionNFT directly via loadFixture. This is the only test that exercises V10 NFT, and it does so by direct contract call, not through the SDK path.
There is no test in the codebase that covers SDK → daemon → chain-adapter → V10 PCA NFT.
evm-adapter.ts:2152-2188 has three read-only V10 NFT methods (getConvictionAgentAccountId, getConvictionAccountLockDurationEpochs, getPublishingConvictionAccountOwner) — used by the publisher to decide whether to route through the PCA discount branch and what publishEpochs to use. Reads work; writes do not.
V9 deploy script 043_deploy_publishing_conviction_account.ts archived with func.skip = async () => true. V9 contract not registered in Hub on V10 deployments.
V10 NFT deploy script 053_deploy_dkg_publishing_conviction_nft.ts active. Registered in Hub as "DKGPublishingConvictionNFT".
V10 NFT is directly invoked by KnowledgeAssetsV10.publish() (lines 384, 401, 912, 928):
agentToAccountId(msg.sender) resolves the publisher's PCA
coverPublishingCost(msg.sender, baseCost, kcStartEpoch, kcEpochs) debits the account
What this means
Every commit before refactor: archive non-V10 contracts and downstream V8/V9 backward-compat code #500 that claimed to test "publishing conviction account" through the SDK was testing the V9 contract. The V10 PCA NFT contract has never been reachable from pnpm --filter @origintrail-official/dkg-chain test or the daemon HTTP API.
Publishing does work end-to-end on V10: a PCA NFT account created via direct contract call will let a registered agent publish at discount because KnowledgeAssetsV10.publish() short-circuits the SDK and calls the NFT directly. But there is no SDK / daemon helper to create the account, top it up, or register an agent.
Each resolves this.contracts.dkgPublishingConvictionNFT and calls the V10 method directly. V10ConvictionAccountInfo mirrors the NFT's getAccountInfo return tuple.
packages/agent/src/dkg-agent.ts
Replace the five null stubs with delegating thin wrappers to the new chain-adapter methods. Drop lockEpochs from createConvictionAccount. Rename addPCAAuthorizedKey → registerConvictionAgent (V9 "key" → V10 "agent" terminology shift).
packages/cli/src/daemon/routes/pca.ts
Response schema: replace V9 fields with V10 fields.
POST /api/pca body: drop lockEpochs (now a global parameter).
New routes: POST /api/pca/:id/agent (register), DELETE /api/pca/:id/agent/:address (deregister), POST /api/pca/:id/settle (settle).
Remove POST /api/pca/:id/authorize (V9 semantics) — replaced by agent registration.
packages/sdk (or wherever the public client lives)
All V10 NFT write methods exposed through chain-adapter, agent facade, and daemon HTTP API.
New integration test in packages/chain/test/conviction-account-v10.test.ts that deploys V10 NFT via fixture and exercises full lifecycle (create → topUp → registerAgent → coverPublishingCost via KAv10 publish → settle).
Daemon e2e test: POST /api/pca returns 200 with {accountId, txHash, blockNumber}.
MockChainAdapter + NoChainAdapter parity stubs.
CHANGELOG / docs note: V10.1+ replaces per-account lock + multi-key with global lock + agent reverse map; clients must update.
V10 PCA NFT lifecycle test as standalone on-chain test (not just inside KAv10 publish flow).
Summary
The DKG SDK's Publishing Conviction Account (PCA) write surface —
chain-adapter.tsmethods,DKGAgentfacade methods, daemon HTTP routes/api/pca/*, the response schemas indaemon/routes/pca.ts, and every chain-adapter integration test that exercised PCA — was wired end-to-end to the V9PublishingConvictionAccount.solcontract. The V10DKGPublishingConvictionNFT.solcontract was never reachable from the SDK. After #500 archived V9, the SDK methods becamereturn nullstubs and all/api/pca/*writes return HTTP 503FEATURE_UNAVAILABLE_503.This is both a hypothesis confirmation (we were testing the wrong contract) and a feature gap (SDK has no path to the live V10 PCA contract). Publishing through V10 PCA NFT does work end-to-end on-chain —
KnowledgeAssetsV10.publish()directly invokes the V10 NFT — but nothing in the SDK or daemon can create, fund, or register an agent against a V10 PCA account.Evidence
1. Pre-archive SDK call sites all resolved the V9 contract
packages/chain/src/archive/evm-adapter-v8-v9-methods.ts(verbatim source preserved from commit4dc99e6e):this.contracts.publishingConvictionAccountwas populated fromHub.getContractAddress("PublishingConvictionAccount")— the V9 contract key. Seeevm-adapter.ts:705-709:2. V9 vs V10 contract APIs are not just renamed — they are semantically different
PublishingConvictionAccount.solDKGPublishingConvictionNFT.solcreateAccount(uint96 amount, uint40 lockEpochs)— per-account lock durationcreateAccount(uint96 committedTRAC)— lock is global (parametersStorage.publishingConvictionEpochs())addFunds(accountId, amount)— admin-gated, raises rawbalancetopUp(accountId, amount)— populates persistenttopUpBalancebuffer separate from base commitmentaddAuthorizedKey(accountId, key)— many keys per account, manual listregisterAgent(accountId, agent)— bidirectionalagentToAccountIdreverse map, agent can only belong to one account (N28-protection)coverPublishingCost(accountId, baseCost, caller)— direct balance debit, single epochcoverPublishingCost(publishingAgent, baseCost, kcStartEpoch, kcEpochs)— window-based allowance, lazy-settlement, enforceskcEpochs ≤ lockDurationEpochssettle(accountId)lazy-sweep + active sink viaEpochStorage.addTokensToEpochRangeMAX_DISCOUNT * conviction / (conviction + C_HALF)— dynamiccommittedTRACaccount.adminfieldownerOf(accountId)getAccountInfoshape(admin, balance, initialDeposit, lockEpochs, conviction, discountBps)(owner, committedTRAC, baseEpochAllowance, createdAtEpoch, expiresAtEpoch, createdAtTimestamp, expiresAtTimestamp, discountBps, topUpBuffer, agentCount, lastSettledWindow, fullySwept)DKGAgent.createPublishingConvictionAccount(_amount, _lockEpochs)(packages/agent/src/dkg-agent.ts:3978) carries the V9lockEpochsparameter — V10 NFT has no per-account lock. This is the smoking gun: even the SDK facade signature was V9-shaped.3. Daemon route handler is V9-shaped
packages/cli/src/daemon/routes/pca.ts:5-7:serializeAccountInforeturns the V9 shape:{accountId, admin, balance, initialDeposit, lockEpochs, conviction, discountBps}. No V10 fields (committedTRAC,topUpBalance,lockDurationEpochs,expiresAtEpoch,agentCount, ...).4. Tests
packages/chain/test/archive/conviction-account.test.ts— 9 PCA tests. Archived. Used adapter methods (createConvictionAccount,addConvictionFunds,addPCAAuthorizedKey,getConvictionAccountInfo) that resolve to V9.packages/chain/test/archive/staking-conviction.test.ts— V8 stakeWithLock.packages/evm-module/test/v10-e2e-conviction.test.tsFlow 3 — bypasses SDK entirely, instantiatesDKGPublishingConvictionNFTdirectly vialoadFixture. This is the only test that exercises V10 NFT, and it does so by direct contract call, not through the SDK path.There is no test in the codebase that covers
SDK → daemon → chain-adapter → V10 PCA NFT.5. Current (post-#500) state
DKGAgentPCA write methods (createPublishingConvictionAccount,addPublishingConvictionAccountFunds,addPCAAuthorizedKey,isPCAAuthorizedKey,getPublishingConvictionAccountInfo) atdkg-agent.ts:3978-4013allreturn null.null→ HTTP 503FEATURE_UNAVAILABLE_503.evm-adapter.ts:2152-2188has three read-only V10 NFT methods (getConvictionAgentAccountId,getConvictionAccountLockDurationEpochs,getPublishingConvictionAccountOwner) — used by the publisher to decide whether to route through the PCA discount branch and whatpublishEpochsto use. Reads work; writes do not.043_deploy_publishing_conviction_account.tsarchived withfunc.skip = async () => true. V9 contract not registered in Hub on V10 deployments.053_deploy_dkg_publishing_conviction_nft.tsactive. Registered in Hub as"DKGPublishingConvictionNFT".KnowledgeAssetsV10.publish()(lines 384, 401, 912, 928):agentToAccountId(msg.sender)resolves the publisher's PCAcoverPublishingCost(msg.sender, baseCost, kcStartEpoch, kcEpochs)debits the accountWhat this means
pnpm --filter @origintrail-official/dkg-chain testor the daemon HTTP API.KnowledgeAssetsV10.publish()short-circuits the SDK and calls the NFT directly. But there is no SDK / daemon helper to create the account, top it up, or register an agent./api/pca/*are not a regression from refactor: archive non-V10 contracts and downstream V8/V9 backward-compat code #500 — they reflect a pre-existing wiring gap that the archive merely surfaced.Proposed wiring (V10 NFT through SDK)
packages/chain/src/chain-adapter.ts(interface) +packages/chain/src/evm-adapter.ts(impl)Each resolves
this.contracts.dkgPublishingConvictionNFTand calls the V10 method directly.V10ConvictionAccountInfomirrors the NFT'sgetAccountInforeturn tuple.packages/agent/src/dkg-agent.tsReplace the five null stubs with delegating thin wrappers to the new chain-adapter methods. Drop
lockEpochsfromcreateConvictionAccount. RenameaddPCAAuthorizedKey→registerConvictionAgent(V9 "key" → V10 "agent" terminology shift).packages/cli/src/daemon/routes/pca.tsPOST /api/pcabody: droplockEpochs(now a global parameter).POST /api/pca/:id/agent(register),DELETE /api/pca/:id/agent/:address(deregister),POST /api/pca/:id/settle(settle).POST /api/pca/:id/authorize(V9 semantics) — replaced by agent registration.packages/sdk(or wherever the public client lives)Update
ApiClient/dkg.client.apirequest/response shapes. Add migration note.Acceptance
packages/chain/test/conviction-account-v10.test.tsthat deploys V10 NFT via fixture and exercises full lifecycle (create → topUp → registerAgent → coverPublishingCost via KAv10 publish → settle).POST /api/pcareturns 200 with{accountId, txHash, blockNumber}.MockChainAdapter+NoChainAdapterparity stubs.Out of scope
References
packages/evm-module/contracts/DKGPublishingConvictionNFT.solpackages/evm-module/contracts/archive/PublishingConvictionAccount.solpackages/chain/src/archive/evm-adapter-v8-v9-methods.tsSee also