From 6f13f8baa554d0796ee364a8e294de5c85787692 Mon Sep 17 00:00:00 2001 From: Prashant Bajpai <34747455+prashantasdeveloper@users.noreply.github.com> Date: Thu, 27 Aug 2026 14:16:26 +0530 Subject: [PATCH 1/2] fix: resolve claim's signing Identity from the Procedure's own Context prepareClaimDividends called distribution.getParticipant() with no args, letting it default the identity to check off distribution.context - the Context the DividendDistribution entity happened to be fetched with. That Context is not necessarily this Procedure's own Context (context.clone() scoped to this call's signingAccount), so any consumer that fetches entities off a shared Context while overriding signingAccount per call (e.g. the REST API) had claim() silently check participation for whatever Identity that shared Context's signingAddress last pointed to, instead of the Identity actually signing the claim - failing with 'The signing Identity is not included in this Distribution' even for a genuine participant. Resolve the signing Identity from the Procedure's own Context explicitly and pass it into getParticipant() so the correct Identity is always the one checked. --- src/api/procedures/claimDividends.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/api/procedures/claimDividends.ts b/src/api/procedures/claimDividends.ts index 1ebb2a4909..7eeccb3020 100644 --- a/src/api/procedures/claimDividends.ts +++ b/src/api/procedures/claimDividends.ts @@ -31,7 +31,18 @@ export async function prepareClaimDividends( assertDistributionOpen(paymentDate, expiryDate); - const participant = await distribution.getParticipant(); + // `distribution` was fetched through (and carries) whatever Context it happened to be + // constructed with, which is *not* necessarily this Procedure's own Context (`context` above, + // scoped to this call's `signingAccount`). Since `getParticipant` defaults its `identity` by + // reading the *signing* Identity off whichever Context it's given, calling it with no args here + // would resolve against `distribution`'s Context instead of this one, silently checking the + // wrong Identity's participation (and balance) whenever the two differ - e.g. any multi-account + // consumer, such as the REST API, that fetches entities off a shared Context while overriding + // `signingAccount` per call. Resolve the signing Identity from this Procedure's Context + // explicitly and pass it through so the correct Identity is always the one checked. + const signingIdentity = await context.getSigningIdentity(); + + const participant = await distribution.getParticipant({ identity: signingIdentity }); if (!participant) { throw new PolymeshError({ From 56c8e3731c6f51298ff18eb4dab308d04f20e243 Mon Sep 17 00:00:00 2001 From: Prashant Bajpai <34747455+prashantasdeveloper@users.noreply.github.com> Date: Thu, 27 Aug 2026 14:48:34 +0530 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=F0=9F=93=9D=20document=20the=20cla?= =?UTF-8?q?im=20dividends=20Context=20fix=20in=20the=20v31=20changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- changelogs/v31.0.0-next.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/changelogs/v31.0.0-next.md b/changelogs/v31.0.0-next.md index c2d24d16e8..11923f5808 100644 --- a/changelogs/v31.0.0-next.md +++ b/changelogs/v31.0.0-next.md @@ -1,6 +1,6 @@ --- title: SDK Changelog - v31.0.0 to next release -description: Pending changes since Polymesh SDK v31.0.0. Adds Ethereum wallet signing and address mapping, broadcasting a transaction without waiting for it, issuing NFTs to an Account, connecting from runtimes that disallow WASM compilation, ordering POLYX transaction history, an optional middleware API key, and staking coverage for chill, rebond, era progress, historical era data, the validator set, commission and total issuance. Fixes BigNumber checks across duplicate package copies, ignored authorization expiry options, unbounded Portfolio scans, on-chain failure reporting, staking permission checks, withdrawing unbonded POLYX where the controller is not the stash, and the units of the total staked amount. +description: Pending changes since Polymesh SDK v31.0.0. Adds Ethereum wallet signing and address mapping, broadcasting a transaction without waiting for it, issuing NFTs to an Account, connecting from runtimes that disallow WASM compilation, ordering POLYX transaction history, an optional middleware API key, and staking coverage for chill, rebond, era progress, historical era data, the validator set, commission and total issuance. Fixes BigNumber checks across duplicate package copies, ignored authorization expiry options, unbounded Portfolio scans, on-chain failure reporting, staking permission checks, withdrawing unbonded POLYX where the controller is not the stash, the units of the total staked amount, and a false "not included" rejection when claiming dividends. sidebar_label: v31.0.0 → next id: v31-0-to-next tags: @@ -383,6 +383,14 @@ All seven now return `permissions: true`: it short-circuits both checks, makes n The count now comes from the stash named in the controller's ledger. An Account that is its own controller is unaffected. +### Claiming dividends could reject a genuine participant as "not included" + +`DividendDistribution.claim()` checks a Distribution's participants by calling `getParticipant()` with no arguments, which defaults the Identity to check to whatever `Context.getSigningIdentity()` returns. `prepareClaimDividends` called it on `distribution` — the `DividendDistribution` entity — rather than on the Procedure's own `Context`. Those are not always the same object: `distribution` carries whichever `Context` it happened to be fetched with, while the Procedure runs against a fresh clone scoped to this call's `signingAccount`. + +For a consumer that fetches entities off one shared, long-lived `Context` while overriding `signingAccount` per call — the REST API is the clearest example — `claim()` checked participation against whatever Identity that shared `Context`'s signing Account last happened to be, not the Identity actually signing the claim. The result was a deterministic `'The signing Identity is not included in this Distribution'`, even for a real, funded participant. + +`prepareClaimDividends` now resolves the signing Identity from its own `Context` explicitly and passes it into `getParticipant()`, so the Identity checked always matches the one signing the call. + --- ## Other changes