Skip to main content
Version: v30.0.x

SDK Changelog - v29.0.1 to v30.0.0

This guide describes changes between v29.0.1 and v30.0.0 of @polymeshassociation/polymesh-sdk, including breaking changes, new features, deprecations, and migration steps. If you're upgrading from v29, start with the Quick Migration Checklist below.


Overview

v30.0.0 is a major release that adds Polymesh chain v8 support while maintaining compatibility with chain v7. The SDK automatically detects the connected chain version at runtime and branches behavior accordingly.

Key themes in this release:

  • Dual chain support (v7 and v8) — connect to either chain without changing SDK initialization code
  • Account-level asset holdings — accounts can hold fungible assets and NFTs directly, not only through portfolios
  • Subsidy workflow overhaul — v8 introduces approve → accept → revoke subsidy flow
  • Granular agent permission groupsTxGroup enum expanded from 10 coarse groups to 22 fine-grained groups
  • Dependency upgrades — Polkadot.js 16.x, polymesh-types 7.x, signing manager 4.x
  • Improved transaction lifecycle — new InBlock and Future transaction statuses

In this guide

Upgrading? Start with Prerequisites and Quick Migration Checklist.

Need to know what broke? See Breaking Changes.

Looking for new capabilities? Check New Features.

Want to understand behavior changes? See Modified Behavior.

Curious about removed APIs? Visit Deprecated APIs.


Prerequisites

Before upgrading, ensure your environment meets these requirements.

Supported chain versions

ChainSpec version thresholdSDK support
v7specVersion < 8_000_000Full support (existing behavior largely preserved)
v8specVersion >= 8_000_000Full support (new features and changed workflows)

The SDK validates the connected chain against 7.0 || 7.1 || 7.2 || 7.3 || 8.0.

Middleware / SubQuery

If you use Middleware V2 (GraphQL), upgrade to ≥ v19.6.0-alpha.2. The SDK enforces this minimum version and will warn if your middleware is outdated.

Middleware schema changes include:

  • Asset transaction history now includes fromAccount and toAccount fields
  • Claims expiry queries are fixed to correctly include non-expired claims

Dependency upgrades

Update these packages alongside the SDK:

Packagev29.0.1v30.0.0
@polkadot/api11.2.116.5.2
@polkadot/util / util-crypto12.6.213.5.9
@polymeshassociation/polymesh-types^6.2.0^7.4.0
@polymeshassociation/local-signing-manager^3.0.1^4.1.1
@polymeshassociation/signing-manager-types^3.0.0^3.7.1

WebSocket library change

The SDK no longer depends on the websocket npm package. It uses:

  • Browser: native WebSocket API
  • Node.js: ws package

If your application bundled websocket only because the SDK required it, you can remove that dependency.

Node.js

Node.js ≥ 20.0.0 is required (unchanged from v29).


Quick migration checklist

Use this checklist when upgrading from v29.0.1.

  1. Upgrade SDK and companion packages (Polkadot 16.x, polymesh-types 7.x, signing manager 4.x)
  2. Upgrade Middleware V2 to ≥ v19.6.0-alpha.2 if used
  3. Replace v8 subsidy flow: subsidizeAccountapproveSubsidy + acceptSubsidy (see Subsidy workflow)
  4. Rename settlement/instruction params: portfoliosholders, portfolioassetHolder, destinationPortfoliodestination (see Settlement and instruction parameter renames)
  5. Update InstructionAffirmation.identity.party and handle Account type (see InstructionAffirmation type change)
  6. Update stored TxGroup enum values to new granular group names (see Agent permission groups)
  7. Handle new transaction statuses: InBlock and Future (see Transaction status improvements)
  8. Use document IDs from documents.get() for selective removal via documents.remove() (see Document management)
  9. Enable balance stats (StatType.Balance / StatType.ScopedBalance) when using percentage transfer restrictions (see Transfer restrictions and asset statistics)
  10. Pass expiresAt to generateOffChainAffirmationReceipt on chain v8 (see Receiver affirmation)
  11. Guard deprecated APIs with context.isV7 checks or catch ErrorCode.NotSupported (see Deprecated APIs)
  12. For MultiSig direct execution (non-proposal), pass asProposal: false to fee estimation methods (see MultiSig asProposal parameter)

Breaking changes

1. Agent permission groups (TxGroup enum)

The TxGroup enum has been restructured from 10 coarse groups to 22 granular groups. Transaction tag membership is now defined in src/types/txGroupConstants.ts instead of inline enum documentation.

Removed / renamed groups:

v29 TxGroupv30 replacement
DistributionCapitalDistribution + SettlementManagement
ComplianceRequirementsManagementComplianceManagement

New groups include: AssetDocumentManagement, AssetMetadataManagement, AssetRegistration, AuthorizationManagement, CapitalDistribution, CddRegistration, CheckpointManagement, ComplianceManagement, CorporateActionManagement, IdentityManagement, OfferingManagement, PortfolioManagement, SettlementManagement, StakingManagement, TickerManagement, TokenManagement, and others.

Migration example:

// Before (v29)
permissions: {
transactions: [
TxGroup.Distribution,
TxGroup.ComplianceRequirementsManagement,
];
}

// After (v30)
permissions: {
transactions: [TxGroup.CapitalDistribution, TxGroup.ComplianceManagement];
}

Review the full list of groups and their transaction tags in the SDK documentation or src/types/txGroupConstants.ts.


2. Settlement and instruction parameter renames

Several procedure parameter types have been renamed to support account-level asset holders.

Parameterv29 namev30 nameType change
Affirm instructionportfoliosholdersPortfolioLike[]AssetHolderLike[]
Withdraw instructionportfoliosholdersPortfolioLike[]AssetHolderLike[]
Reject instructionportfolioassetHolderPortfolioLikeAssetHolderLike
Controller transferdestinationPortfoliodestinationPortfolioLikeAssetHolderLike
NFT controller transferdestinationPortfoliodestinationPortfolioLikeAssetHolderLike

Migration example:

// Before (v29)
await instruction.affirm({ portfolios: [portfolio] });
await instruction.reject({ portfolio: myPortfolio });
await asset.controllerTransfer({ destinationPortfolio: targetPortfolio });

// After (v30)
await instruction.affirm({ holders: [portfolio] }); // portfolio or account
await instruction.reject({ assetHolder: myAccount });
await asset.controllerTransfer({ destination: targetAccount });

3. InstructionAffirmation type change

The affirming party is no longer always an Identity. It can now be an Account or Identity.

// Before (v29)
interface InstructionAffirmation {
identity: Identity;
status: AffirmationStatus;
}

// After (v30)
interface InstructionAffirmation {
party: Account | Identity;
status: AffirmationStatus;
}

Migration: Update any code that reads .identity on affirmation results to use .party and handle both Account and Identity types.


4. Instruction leg types

FungibleLeg and NftLeg from/to fields now use AssetHolder instead of DefaultPortfolio | NumberedPortfolio. Accounts are valid leg endpoints on chain v8.


5. TransferBreakdown.general type widening

// Before (v29)
general: TransferError[];

// After (v30)
general: (TransferError | string)[];

Chain v8 can return custom error strings not mapped to SDK TransferError enum values. Update type guards accordingly.


6. Document get() return type

// Before (v29)
documents.get(): Promise<ResultSet<AssetDocument>>

// After (v30)
documents.get(): Promise<ResultSet<AssetDocumentWithId>>

AssetDocumentWithId includes an on-chain id: BigNumber field required by the new documents.remove() method.


7. Subsidy workflow (chain v8)

On chain v8, the old authorization-based subsidy flow is deprecated.

// Before (v7 / v29)
await accountManagement.subsidizeAccount({ beneficiary, allowance });
// Beneficiary accepts via authorization

// After (v8 / v30)
await accountManagement.approveSubsidy({ beneficiary, allowance });
await accountManagement.acceptSubsidy({ subsidizer }); // called by beneficiary
// Either party can revoke before acceptance:
await accountManagement.revokeSubsidy({ beneficiary });

subsidizeAccount still works on chain v7 but is deprecated on v8.


8. MultiSig modification permissions

On v29, only the MultiSig admin identity could call modifyMultiSig. On v30, any signer on the MultiSig can modify it.


9. RoleType.CddProvider deprecated

Use RoleType.DidRegistrar instead. CDD provider role is discontinued on chain v8.


10. ModifyInstructionAffirmationParams attribute rename

Internal affirmation modification params have been renamed (affects advanced integrators building custom affirmation flows).


New features

This release introduces significant new capabilities, particularly for chain v8 support. While many features are chain-version-specific, the SDK's automatic detection means your code can remain unchanged when connecting to different chain versions.

Chain v8 dual-version support

The SDK detects chain version via Context.isV7 and Context.specVersion. These update automatically when the chain undergoes a runtime upgrade. Use this to conditionally enable v8-specific features:

const sdk = await Polymesh.connect({ nodeUrl, signingManager });
const { isV7 } = sdk.context;

if (isV7) {
// v7-specific logic
} else {
// v8-specific logic
}

A new ErrorCode.NotSupported is thrown when calling a method incompatible with the connected chain version.


Account-level asset holdings

Available on both v7 and v8. Accounts can now hold fungible assets and NFTs directly, independent of portfolios. This is a core v8 feature, with backward-compatible support on v7.

New types:

  • AssetHolderLikeAccountLike | PortfolioLike (convenience input type)
  • AssetHolderAccount | DefaultPortfolio | NumberedPortfolio (concrete entity)
  • AssetHolderId — identifier used in instruction legs

New methods:

MethodDescriptionChain
Account.getAssetBalances()Get all fungible asset balances held in an accountBoth
Account.getCollections()Get NFT collections held in an accountv8 only
Assets.transferFunds()Transfer funds between two asset holders owned by the same identityv8 only
Fungible.approveAllowance()Approve a spending allowance for another accountv8 only
Fungible.getAllowance()Query allowance between owner and spenderv8 only

Modified methods that now support account-level operations:

MethodChange
FungibleSettlements.canTransfer()from/to accept AssetHolderLike
NonFungibleSettlements.canTransfer()from/to accept AssetHolderLike
Nft.getOwner()Returns AssetHolder | null instead of Portfolio
Identity.getInstructions()Now includes instructions where identity owns accounts in legs
IssueTokensParamsNew optional account field (mutually exclusive with portfolioId)
RedeemTokensParams / RedeemNftParamsNew optional fromAccount field

Subsidy management (chain v8)

v8 only. The subsidy workflow has been completely redesigned on chain v8 with explicit approve-accept-revoke flow:

MethodDescription
AccountManagement.approveSubsidy()Subsidizer approves an allowance for a beneficiary
AccountManagement.acceptSubsidy()Beneficiary accepts a pending subsidy
AccountManagement.revokeSubsidy()Subsidizer revokes a pending subsidy
Subsidies.getPendingSubsidies()Query pending subsidies awaiting acceptance

See Subsidy workflow (chain v8) under Breaking Changes for migration details.


Identity registration (chain v8)

v8 only. New streamlined identity registration:

MethodDescription
Identities.selfRegisterDid()Register a new DID for the signing account without a CDD provider

Receiver affirmation (chain v8)

v8 only. Receiver affirmation is automatic by default on chain v8. To require explicit receiver affirmation:

await identity.setMandatoryReceiverAffirmation(AffirmationRequirement.Required);

Off-chain affirmation receipts now require an expiresAt date on chain v8:

await instruction.generateOffChainAffirmationReceipt({
expiresAt: new Date('2026-12-31'),
});

Document management

Available on both v7 and v8. Incremental document operations allow you to add or remove specific documents without replacing the entire list.

MethodDescription
Documents.add()Add documents to the asset's existing list
Documents.remove()Remove specific documents by on-chain ID
Documents.set()Replace all documents (removes all existing first)
Documents.get()Returns documents with on-chain IDs

Example — selective document removal:

const { data: docs } = await asset.documents.get();
const idsToRemove = docs
.filter((d) => d.name === 'old-doc.pdf')
.map((d) => d.id);
await asset.documents.remove({ documentIds: idsToRemove });
await asset.documents.add({ documents: [newDocument] });

NFT batch issuance

Available on both v7 and v8. Issue multiple NFTs in a single transaction:

await collection.batchIssue({
metadataList: [
[{ name: 'NFT 1', ... }],
[{ name: 'NFT 2', ... }],
],
});

NFT event parsing has been updated to handle chain v8's NFTHoldingsUpdated event (in addition to v7's NFTPortfolioUpdated).


Transfer restrictions and asset statistics

Improved control and reliability. Two new stat types support enhanced transfer restriction validation:

New stat types:

  • StatType.Balance — balance-based statistics for percentage/max-ownership restrictions
  • StatType.ScopedBalance — scoped balance statistics with claim-type scope

Enhanced setAssetStats / setTransferRestrictions behavior:

  • Reads current active stats from chain before updating (prevents accidental stat removal)
  • Only calls setActiveAssetStats if the stat set actually changed (reduces unnecessary on-chain operations)
  • Stat values are optional when enabling (defaults to 0); omit on updates to preserve current values
  • Throws NoDataChange if no changes are needed
  • Fixed duplicate detection across jurisdiction and claim-type restrictions
  • Fixed bug in fetching all transfer restriction exemptions

Important: When using percentage or max-ownership restrictions, you must enable StatType.Balance or StatType.ScopedBalance stats.


Transaction status improvements

Finer-grained visibility into transaction lifecycle. Two new TransactionStatus values provide better progress tracking:

StatusWhen emitted
InBlockExtrinsic is included in a block (before finalization)
FutureExtrinsic is scheduled for future execution (dispatch-after)

Example — monitoring transaction progress:

tx.onStatusChange((status) => {
if (status === TransactionStatus.InBlock) {
// Extrinsic in block, awaiting finalization
console.log('Transaction included in block');
}
if (status === TransactionStatus.Future) {
// Scheduled for future execution
console.log('Transaction scheduled for later');
}
});

MultiSig asProposal parameter

Fee estimation and signable payload generation now accept an asProposal parameter to distinguish between direct execution and proposal creation:

// Estimate fees for direct execution (not wrapped as MultiSig proposal)
const fees = await tx.getTotalFees(false);

// Build signable payload for direct execution
const payload = await tx.toSignablePayload(metadata, false);

preRunValidation runs before fee checks and respects the asProposal context (e.g., transferPolyx validates the acting account's balance when asProposal: true).


Corporate action validation

Improved safety. Corporate action initiation now includes SDK-side validation:

  • Duplicate withholding detection
  • Withholding limit checks

This applies to initiateCorporateAction and configureDividendDistribution procedures.


Modified behavior

This section describes changes in how existing methods behave, without breaking their signatures. Most changes are chain-specific (v8 only) or bug fixes.

Claims (chain v8)

Methodv7 behaviorv8 behavior
Claims.getCddClaims()Returns CDD claimsThrows NotSupported
Identity.hasValidCdd()Checks CDD validityReturns true if DID exists
Claims expiry queryCould miss non-expired claimsFixed: expiry IS NULL OR filterExpiry > now

Historic asset transactions

BaseHistoricAssetTransaction (returned by Fungible.getTransactionHistory() and NftCollection.getTransactionHistory()) now includes account-level transfer details:

  • fromAccount: Account | null
  • toAccount: Account | null

These fields are populated when using Middleware V2 (≥ v19.6.0-alpha.2).


Default portfolio ID assignment

Bug fix. Fixed incorrect ID assignment to the default portfolio.


Staking controller (chain v8)

The controller argument to setStakingController is ignored on chain v8 — the stash account becomes its own controller.


Invite permissions default

Bug fix. Corrected default invite permissions to use assets: key instead of tokens:.


Deprecated APIs

The following APIs are deprecated. On chain v8, calling deprecated methods throws ErrorCode.NotSupported. On chain v7, they continue to work but should not be used in new code.

Subsidy

DeprecatedReplacement
AccountManagement.subsidizeAccount()approveSubsidy() + acceptSubsidy()

Migration: See Subsidy workflow (chain v8) for details.

CDD claims

DeprecatedNotes
Claims.getCddClaims()CDD claims discontinued on v8
Identity.hasValidCdd()Behavior changed on v8 (see Modified behavior)

Child identities

DeprecatedNotes
Identities.getChildIdentity()Child identities discontinued on v8
Identities.createChild()Child identities discontinued on v8
All ChildIdentity methodsChild identities discontinued on v8

Instruction affirmation withdrawal

DeprecatedReplacement
Instruction.withdraw()Use reject() instead
Instruction.withdrawAsMediator()Use rejectAsMediator() instead
InstructionAffirmationOperation.WithdrawDeprecated enum value
InstructionAffirmationOperation.WithdrawAsMediatorDeprecated enum value

Other

DeprecatedReplacement / notes
RoleType.CddProviderRoleType.DidRegistrar
AcceptPrimaryKeyRotationParams.cddAuthNo longer needed on v8
NftControllerTransferParams.destinationPortfoliodestination: AssetHolderLike
AuthorizationType.AddRelayerPayingKeyOldAddRelayerPayingKey

Bug fixes

AreaFix
Transfer restrictionsFixed setTransferRestrictions input validation
Transfer restrictionsFixed fetching all transfer restriction exemptions
ClaimsFixed claims expiry query to include non-expired claims
Default portfolioFixed incorrect ID assignment to default portfolio
Invite permissionsFixed default permissions key (tokens:assets:)
MultiSig feesFixed payer fallback when primary account has no identity
v7 typesExplicit v7 type handling in dual-version code paths

Version compatibility matrix

Quick reference for version compatibility:

SDK versionChain v7Chain v8Middleware V2Polkadot.js
v29.0.1≥ v19.3.011.2.1
v30.0.0≥ v19.6.0-alpha.216.5.2