# [31.0.0](https://github.com/PolymeshAssociation/polymesh-sdk/compare/v30.2.0...v31.0.0) (2026-08-14)


* fix!: 🐛 require expiresAt on off-chain settlement and STO receipts ([1473bc3](https://github.com/PolymeshAssociation/polymesh-sdk/commit/1473bc3749248826a69330d9fc1dbaf67202c736))


### Bug Fixes

* 🐛 authorise ballot voting as a holder action ([aa36fc0](https://github.com/PolymeshAssociation/polymesh-sdk/commit/aa36fc0a3177e2926397a01d2cc601b283a83518)), closes [#1643](https://github.com/PolymeshAssociation/polymesh-sdk/issues/1643)
* 🐛 base transferFunds authorization on signing key, add NFT checks ([64adfd9](https://github.com/PolymeshAssociation/polymesh-sdk/commit/64adfd91710c0843e87bf902c3c73bdcda68d5d1))
* 🐛 check agent permissions for the accept-side transaction ([394fb58](https://github.com/PolymeshAssociation/polymesh-sdk/commit/394fb588fb1d71ff1c4f5290572d470361ae9e08))
* 🐛 compare NFT ownership by address for MultiSig Account holders in transferFunds ([816a5f7](https://github.com/PolymeshAssociation/polymesh-sdk/commit/816a5f799d9e6fb15e4e62b84410a5dfad019a9d))
* 🐛 correct protocol fee mapping against v8 runtime ([69ec025](https://github.com/PolymeshAssociation/polymesh-sdk/commit/69ec025da27bc62d5ffb7476487b26296390ff49))
* 🐛 correct transaction tags against chain v8 metadata ([e77224d](https://github.com/PolymeshAssociation/polymesh-sdk/commit/e77224dce8ab3bb3a4c2edd19d8ac2a43b10d204))
* 🐛 declare the transaction revokeIdentityToCreatePortfolios submits ([debc1d0](https://github.com/PolymeshAssociation/polymesh-sdk/commit/debc1d065da6a8e6a36f102e0ac5b26c020ab9ed))
* 🐛 declare the transactions procedures actually submit ([672fcfd](https://github.com/PolymeshAssociation/polymesh-sdk/commit/672fcfd3d1a7c3f4b4fb8756d65c789f6ad3a2f3))
* 🐛 distinguish immediate execution from a pending instruction ([9c40cf9](https://github.com/PolymeshAssociation/polymesh-sdk/commit/9c40cf91ca1772812a03a0aa3fb530294b82298d))
* 🐛 drop permission declarations the chain never checks ([ec0ddbb](https://github.com/PolymeshAssociation/polymesh-sdk/commit/ec0ddbbb395d0393119bf99b29079cafa8650fe2))
* 🐛 drop remaining permission declarations the chain never checks ([fdb8f75](https://github.com/PolymeshAssociation/polymesh-sdk/commit/fdb8f75f968f607fd8c9b9654bd59c75564ada65))
* 🐛 make generate:consts idempotent ([1c9b080](https://github.com/PolymeshAssociation/polymesh-sdk/commit/1c9b08096a2aba5c8ea98cbc561c4230245c7058))
* 🐛 only require the DID Registrar role to issue a CDD claim ([78abd14](https://github.com/PolymeshAssociation/polymesh-sdk/commit/78abd14d912d85e61bdcaeda6fe5a0ed668d5f0c))
* 🐛 protocol fees no longer silently reported as zero ([e30e51d](https://github.com/PolymeshAssociation/polymesh-sdk/commit/e30e51dcd3703258060ad2a22f4bd34ad13b397f))
* 🐛 report transfer failures instead of throwing ([50fb337](https://github.com/PolymeshAssociation/polymesh-sdk/commit/50fb337d25beee873d779484b6fb25ec67aa37c4))
* 🐛 return null from getNextCheckpoint after every Schedule is removed ([75d0b0e](https://github.com/PolymeshAssociation/polymesh-sdk/commit/75d0b0ed22f7819905b0804d25b65357d7d9488e))
* 🐛 staking.getPayee returns null for an Account with no payee ([4a8effc](https://github.com/PolymeshAssociation/polymesh-sdk/commit/4a8effcabb8140fa01d812c11c5ab693778735be))


### Features

* 🎸 add Checkpoint.Schedules.getNextCheckpoint getter ([31db08c](https://github.com/PolymeshAssociation/polymesh-sdk/commit/31db08ccc433dde93355f5f90f0d2c7e36766259))
* 🎸 add CorporateActionBase.getDocuments getter ([edef2cb](https://github.com/PolymeshAssociation/polymesh-sdk/commit/edef2cb4567aa85f0b100d80cf38b6464e8e07e8))
* 🎸 align TransferError with the chain's transfer errors ([52f1364](https://github.com/PolymeshAssociation/polymesh-sdk/commit/52f13642eeec5397818afe09e1734be70ba2075a))
* 🎸 allow transferFunds between asset holders on different DIDs ([458bfd5](https://github.com/PolymeshAssociation/polymesh-sdk/commit/458bfd5d28d156e1633ffd5970df41afd1d9374e))
* 🎸 Drop v7 support ([4292be3](https://github.com/PolymeshAssociation/polymesh-sdk/commit/4292be303bb5bd161b83ce92ed9ea7b1993e82e7))
* 🎸 make nft.createNftCollection grantable to External Agents ([32753ef](https://github.com/PolymeshAssociation/polymesh-sdk/commit/32753ef90ff9e1bc010e344e66155fd89a44ffe7))
* 🎸 rebuild transaction groups from the chain's permission model ([b6cb8e5](https://github.com/PolymeshAssociation/polymesh-sdk/commit/b6cb8e5ee0b13903cf8f0e92050272800a260372))
* 🎸 remove CDD transfer errors that cannot occur on v8 ([10114e3](https://github.com/PolymeshAssociation/polymesh-sdk/commit/10114e300392e9bb9f05406ce0f85bdcdda7774d))
* 🎸 remove types and a procedure for extrinsics that no longer exist ([2fb7fec](https://github.com/PolymeshAssociation/polymesh-sdk/commit/2fb7fecbcc64eff17682a8e9c0c15732d433255c))


### BREAKING CHANGES

* `expiresAt` is now required on
`Instruction.generateOffChainAffirmationReceipt` and
`Offering.generateOffChainFundingReceipt`, and on
`OffChainAffirmationReceipt` and `OffChainFundingReceipt`.
* 🧨 `Assets.transferFunds` return type changed from
`void` to `Instruction | undefined`. It resolves to the pending
`Instruction` when a cross-DID transfer is left awaiting the
receiver's affirmation, and `undefined` when the transfer settles
immediately (same-DID, or the receiver auto-affirmed).
* 🧨 The following exported types are removed, along with the
`modifyCorporateActionsAgent` procedure:

- `ScopeClaimProof` and `AddInvestorUniquenessClaimParams` — described
  `identity.add_investor_uniqueness_claim`, which does not exist on chain v8
- `ModifyPrimaryIssuanceAgentParams` — the Primary Issuance Agent concept was
  superseded by External Agents
- `ModifyCorporateActionsAgentParams` — its procedure's only caller,
  `CorporateActions.setAgent`, was removed in v22.0.0 in favour of
  `Permissions.inviteAgent`, but the procedure was left behind

None had any reference in the SDK and no procedure accepted or returned them.
There is no replacement because there is no longer an operation to describe.

`testUtils` Asset entity mocks no longer default a `primaryIssuanceAgents`
field, which `AssetDetails` has not had since v22.0.0.
* 🧨 - Removed the `TransferStatus` enum and its sole
producer `u8ToTransferStatus`. `TransferError` — the enum actually
populated, by `Settlements.canTransfer` — keeps its role, and its members'
doc comments no longer refer to `TransferStatus` equivalents.
- Removed `TransferError.InvalidReceiverPortfolio`. Its sole producer was
the `granularCanTransferResultToTransferBreakdown` cascade deleted with v7
support, and it cannot be re-mapped: the `portfolio` pallet has a single
`PortfolioDoesNotExist` variant, already mapped to `InvalidSenderPortfolio`.
- Added `TransferError.InvalidReceiverIdentity` for a receiving Identity
that is not active. Both transfer-validation paths report this condition
(`nft.InvalidNFTTransferInvalidReceiverDID` and
`asset.InvalidTransferInvalidReceiverDID`) and neither was mapped, so it
previously surfaced as a raw chain error name.
- Removed the `transfersCanTransfer` mock option in `testUtils`, typed
against a return type `canTransfer` no longer has.
- See [`changelogs/v30.2.0-next.md`](changelogs/v30.2.0-next.md) for full
migration guidance.
* 🧨 - Removed `TransferError.InvalidReceiverCdd`,
`TransferError.InvalidSenderCdd` and `TransferError.ScopeClaimMissing`.
The first two cannot be produced because transfers are no longer CDD
gated; `ScopeClaimMissing` relates to Investor Uniqueness, removed from
the chain some time ago.
- See [`changelogs/v30.2.0-next.md`](changelogs/v30.2.0-next.md) for full
migration guidance.
* 🧨 - Removed `TxGroup.RelayerManagement` and
`RELAYER_MANAGEMENT_TX_TAGS`. Every call in the `relayer` pallet is
`ensure_signed` only, so the group never gated anything and no replacement
grant is needed.
- `TxGroup.MultiSigManagement` / `MULTISIG_MANAGEMENT_TX_TAGS` reduced to
`multiSig.CreateMultisig`, the only permission-checked call in the pallet.
The rest are executed under the MultiSig's own origin via a proposal, are
`ensure_signed` only, or are primary-key only. What a MultiSig may do via
proposal is constrained by the permissions held by the **MultiSig Account
itself**, not by its signers'.
- Added `TxGroup.InstructionMediation` / `INSTRUCTION_MEDIATION_TX_TAGS`
(`AffirmInstructionAsMediator`, `RejectInstructionAsMediator`,
`LockInstruction`, `UnlockInstruction`). These are **newly grantable, not
relocated** — no group previously covered them, so existing
`SettlementManagement` grantees do not already have them.
- Added `TxGroup.DidRegistration` / `DID_REGISTRATION_TX_TAGS`
(`identity.RegisterDid`); `TxGroup.CddRegistration` is deprecated but
retained.
- Removed tags for extrinsics no longer on chain:
`settlement.AddInstructionWithMemo`, `settlement.AddAndAffirmInstructionWithMemo`,
`portfolio.MovePortfolioFundsV2`.
- Added tags for permission-checked v8 extrinsics no group previously
covered, across `SettlementManagement`, `PortfolioManagement`,
`StoManagement` and `CorporateActionsManagement`.
- Consumers building permission UIs from `TX_GROUP_TO_TAGS_MAP`,
`AGENT_TX_GROUP_VALUES` or the individual `*_TX_TAGS` constants should
re-check their output.
- See [`changelogs/v30.2.0-next.md`](changelogs/v30.2.0-next.md) for full
migration guidance.
* 🧨 - SDK now only supports **chain v8** — connecting to a v7 chain throws on
initialization (`SUPPORTED_SPEC_VERSION_RANGE` narrowed to `'8.0'`).
- Removed: `ChildIdentity` entity and all child-identity APIs (`Identities.createChild`/
`createChildren`/`getChildIdentity`, `Identity.*` equivalents), `Claims.getCddClaims`,
`Identity.hasValidCdd`, `RoleType.CddProvider`/`isCddProviderRole`/`CddProviderRole`,
`AccountManagement.subsidizeAccount`, `consumeAddRelayerPayingKeyAuthorization`/
`AuthorizationType.AddRelayerPayingKey`, `Instruction.withdraw`/`withdrawAsMediator`/
`InstructionAffirmationOperation.Withdraw`/`WithdrawAsMediator`, `Nft.controllerTransfer`'s
`destinationPortfolio` param, `AcceptPrimaryKeyRotationParams.cddAuth`,
`SetStakingControllerParams`/`BondPolyxParams.controller`.
- Renamed: `Identity.isCddProvider()` → `Identity.isDidRegistrar()`.
- Deprecated: `Identities.registerIdentity` (`createCdd`/`expiry` are now no-ops) —
use `registerDid`/`selfRegisterDid`.
- Error message changes (update any string-matching code):
`'Beneficiary/Subsidizer Account does not have a valid CDD Claim'` →
`'...does not have an associated Identity'`;
`'Issuing Identity does not have a valid CDD claim'` → `'Issuing Identity does not exist'`;
`'Issuer must be a CDD provider'` → `'Issuer must be a DID Registrar'`;
`'MultiSig signers must be accounts as of v7'` → `'MultiSig signers must be accounts'`.
- See [`changelogs/v30.2.0-next.md`](changelogs/v30.2.0-next.md) for full migration guidance.
