Skip to main content

Full Pallet API Reference - v8.0 to v8.1.2

Every structural API change between Polymesh chain v8.0.2 and v8.1.2: each call, event, error, storage item and runtime API that was added, renamed or had its behaviour change. It complements the narrative pages in the v8.0 → v8.1.2 changelog.

Scope:

  • No pallets were added or removed, and no constants changed.
  • transaction_version is unchanged at 8. Existing signing code needs no update.
  • Nothing was removed. The only rename is one Settlement error, which retains its index. One Sto error is added in v8.1.2, at the end of its variant list.
  • pallet-precompiles is not a runtime pallet — it plugs into pallet_revive::Config::Precompiles, takes no pallet index and adds nothing to metadata. The precompile interfaces are not part of this reference.

Summary​

PalletCallsEventsErrorsStorage
Asset5 added3 added4 added2 added
Nft3 added3 added3 added3 added
Portfolio——1 added3 added
Settlement——1 renamed—
Sto——1 added—

Five calls change behaviour or cost without changing their signature: MultiSig::create_multisig, Portfolio::quit_portfolio_custody, ExternalAgents::create_group/set_group_permissions, Sto::invest and Portfolio::move_portfolio_funds. See Behaviour changes without a signature change.

Storage versions: pallet-nft 7 → 8, pallet-portfolio 4 → 5. Both are migrated automatically — see Other Runtime Changes.

The AssetHolder type​

Several new calls take an AssetHolder, an enum introduced in v8.0 and used more widely here:

enum AssetHolder {
Portfolio(PortfolioId),
Account(AccountId32),
}

Freezing and controller transfers act on a holder in either form. Because the two forms live in different pallets' storage, an account's frozen state is in Asset and a portfolio's is in Portfolio.


Asset​

Calls​

IndexCallArguments
38set_frozen_tokensasset_id: AssetId, asset_holder: AssetHolder, amount: Balance
39set_holder_frozenasset_holder: AssetHolder, asset_id: AssetId, freeze: bool
40controller_transfer_toasset_id: AssetId, value: Balance, source: AssetHolder, destination: AssetHolder
41freeze_partial_tokensasset_id: AssetId, asset_holder: AssetHolder, amount: Balance
42unfreeze_partial_tokensasset_id: AssetId, asset_holder: AssetHolder, amount: Balance

All five require the caller to be an external agent of the asset with the relevant permission.

set_frozen_tokens, freeze_partial_tokens and unfreeze_partial_tokens apply to fungible assets only, and fail with UnexpectedNonFungibleToken otherwise. set_holder_frozen applies to NFT collections as well, and pallet-nft enforces it on transfer.

set_frozen_tokens sets the frozen balance absolutely; freeze_partial_tokens and unfreeze_partial_tokens adjust it relatively. See Asset Freezing.

Note the argument order differs between set_holder_frozen (holder first) and the other four (asset id first).

Events​

EventFields
FrozenBalanceSetcaller_did: IdentityId, asset_holder: AssetHolder, asset_id: AssetId, frozen_balance: Balance
SetAccountFreezecaller_did: IdentityId, holder: AssetHolder, asset_id: AssetId, freeze: bool
ControllerTransferTocaller_did: IdentityId, asset_id: AssetId, source: AssetHolder, destination: AssetHolder, amount: Balance

FrozenBalanceSet always carries the resulting absolute frozen balance, whichever call produced it.

Errors​

ErrorRaised when
InvalidTransferSenderIsFrozenThe sending holder is frozen for this asset
ReceiverAffirmationRequiredThe destination requires receiver affirmation, so a controller transfer cannot deliver into it
InsufficientFrozenBalanceunfreeze_partial_tokens was asked to release more than is frozen
FreezePartialTokenMustNotExceedHoldersBalancefreeze_partial_tokens would freeze more than the holder holds

InsufficientBalance is unchanged but now accounts for frozen tokens: a holder's available balance is balance − locked − frozen.

Storage​

ItemShape
FrozenBalance(AccountId32, AssetId) → Balance
FrozenAccounts(AccountId32, AssetId) → bool

These cover account holders. Portfolio holders are stored in Portfolio.


Nft​

Calls​

IndexCallArguments
5approveasset_id: AssetId, nft_id: NFTId, spender: Option<AccountId>
6set_approval_for_allasset_id: AssetId, operator: AccountId, approved: bool
7controller_transfer_tonfts: NFTs, source: AssetHolder, destination: AssetHolder

approve with spender: None clears the approval. Only the account key holding the NFT, or an approved collection operator, may call it.

controller_transfer_to requires the caller to be an external agent of the collection. Unlike Asset::controller_transfer_to, it emits no dedicated event: like Nft::controller_transfer it reports through the existing NFTHoldingsUpdated, whose HoldingsUpdateReason is ControllerTransfer and whose source and destination holders are both carried in the event.

Events​

EventFields
NFTApprovalowner: AccountId32, spender: Option<AccountId32>, asset_id: AssetId, nft_id: NFTId
NFTApprovalForAllowner: AccountId32, operator: AccountId32, asset_id: AssetId, approved: bool
NFTApprovalSpentowner: AccountId32, spender: AccountId32, asset_id: AssetId, nft_id: NFTId

In all three, owner is the account key holding the NFT, not necessarily the caller — an operator may set or spend an approval on the holder's behalf, and the event still reports the holder.

No event is emitted when a per-token approval is implicitly cleared by a transfer.

Errors​

ErrorRaised when
NFTApprovalNotAuthorizedThe caller neither holds the NFT nor operates the collection for its holder
InsufficientNFTApprovalA spender attempted a transfer without an approval for that NFT
ReceiverAffirmationRequiredThe destination requires receiver affirmation, so a controller transfer cannot deliver into it

Storage​

ItemShape
NFTAccountCount(AccountId32, AssetId) → NFTCount
TokenApproval(AssetId, NFTId) → Option<AccountId32>
OperatorApproval(AccountId32 owner, AccountId32 operator, AssetId) → bool

Storage version 7 → 8; NFTAccountCount is backfilled by migration.


Portfolio​

Errors​

ErrorRaised when
PortfolioIsFrozenThe portfolio is frozen for the asset being moved

As of v8.1.2 both this error and the pre-existing InsufficientPortfolioBalance are raised from ensure_sufficient_balance, rather than only from the multi-asset move path. InsufficientPortfolioBalance now measures balance − locked − frozen, so a partially frozen portfolio hits it where it previously did not.

ensure_sufficient_balance is not specific to portfolio moves. It backs three calls, and all three now refuse a frozen portfolio and measure its balance net of frozen tokens:

CallWhat it checks
Portfolio::move_portfolio_fundsThe sending portfolio can release each amount moved
Sto::create_fundraiserThe offering portfolio can lock the full amount offered across tiers
CapitalDistribution::distributeThe source portfolio can lock the full distribution amount

Storage​

ItemShape
PortfolioNFTCount(PortfolioId, AssetId) → NFTCount
PortfolioFrozenAssets(PortfolioId, AssetId) → Balance
FrozenPortfolios(PortfolioId, AssetId) → bool

PortfolioFrozenAssets and FrozenPortfolios are the portfolio counterparts of Asset::FrozenBalance and Asset::FrozenAccounts.

Storage version 4 → 5; PortfolioNFTCount is backfilled by migration.


Settlement​

Errors​

ChangeDetail
RenamedAllowancesNotSupportedForNFTs → DeprecatedAllowancesNotSupportedForNFTs

The variant was renamed rather than deleted so that the indices of the errors after it are unchanged. It is no longer raised: NFT spender transfers now fail with Nft::InsufficientNFTApproval. Decoders keyed on error index are unaffected; decoders keyed on name need updating.

Behaviour changes​

transfer_funds — two changes, neither altering the call signature:

  1. With from = Some(holder) and a caller other than the holder, non-fungible funds are now accepted, consuming an NFT approval. Previously this combination was rejected.
  2. A redundant custody check was removed: an instruction where the caller is the receiver but does not have custody of the receiving portfolio is now allowed.

Sto​

Errors​

ErrorRaised when
InstructionNotSettledinvest created an instruction that did not reach InstructionStatus::Success within the call

Added in v8.1.2 at the end of the variant list, so the indices of existing Sto errors are unchanged. The cause is a mandatory mediator on either asset in the instruction — the offering asset, or the raising asset when the investment is funded on chain — since the instruction cannot settle without that mediator's separate affirmation. See What changed in v8.1.2.


Behaviour changes without a signature change​

These calls keep their index, arguments and encoding. Clients need no regeneration for them, but their outcome or cost differs.

CallChange in v8.1.2
MultiSig::create_multisigCustom permissions are validated against the standard length and complexity limits. Weight includes that validation when permissions are supplied.
Portfolio::quit_portfolio_custodyRuns the secondary-key portfolio permission check in addition to the custodian check.
ExternalAgents::create_group, set_group_permissionsA nested Except extrinsic restriction is refused with Identity::ExceptNotAllowedForExtrinsics. The outer form was already refused with ExternalAgents::ExceptPermissionsNotAllowed.
Sto::investVerifies its instruction settled; see above.
Portfolio::move_portfolio_fundsEnforces the frozen balance, not only a whole-portfolio freeze.
Nft::redeem_nftNo behavioural change: number_of_keys is still validated and Nft::NumberOfKeysIsLessThanExpected is still raised. The count is now read from the collection's key set rather than from the drained metadata, and the call is re-benchmarked accordingly.

No error variant, event or storage item was removed in v8.1.2.


Runtime APIs​

APIVersionChange
NFTApi3 → 4Added token_approval(asset_id, nft_id) → Option<AccountId> and operator_approval(owner, operator, asset_id) → bool

Existing NFTApi methods are unchanged, and version 3 clients continue to work.

NFTApi::transfer_report and AssetApi::transfer_report keep their signatures but return more errors as of v8.1.2: both now evaluate the holder freeze and measure the available balance net of frozen tokens. A caller that treated an empty error list as "this transfer will succeed" gets a more accurate answer; no decoding change is required. See What changed in v8.1.2.

No custom JSON-RPC methods were added, removed or changed.