@parity/product-sdk-contracts
Typed contract interactions on Polkadot Asset Hub.
Drives queries and transactions against deployed PolkaVM/Solidity contracts
via pallet-revive. ABIs are consumed from a Contract Description Metadata
(CDM) manifest or directly from cargo-pvm-contract build artefacts. The
Solidity ABI codec is delegated to viem; transactions and dry-runs go
through PAPI typed APIs (Revive.call / ReviveApi.call).
npm install @parity/product-sdk-contractsExports
Classes
| Name | Summary |
|---|---|
ContractDryRunFailedError | A pre-flight ReviveApi.call dry-run reported failure. Thrown from the .tx() |
ContractError | Base class for all contract errors. Use instanceof ContractError to catch any contract-related error. |
ContractLiveAddressResolutionError | Live CDM registry address resolution failed. |
ContractManager | Manages typed contract interactions backed by a cdm.json manifest. |
ContractNotFoundError | A contract was not found in the cdm.json manifest. |
ContractRevertedError | A contract call returned with the REVERT flag set on a dispatched-OK call. |
ContractSignerMissingError | No signer was available for a transaction call. |
Functions
| Name | Summary |
|---|---|
createContract() | Create a contract handle from a raw H160 address and ABI — no cdm.json needed. |
createContractFromClient() | Create a contract handle from a raw PolkadotClient, descriptor, address, and ABI. |
createContractRuntime() | Wrap a typed PAPI API as a ContractRuntime. Intended for tests and |
createContractRuntimeFromClient() | Build a ContractRuntime from a raw PolkadotClient plus its descriptor. |
ensureContractAccountMapped() | Ensure the SS58 account is mapped to its derived H160 on pallet-revive. |
withLiveContractAddresses() | Return a cloned manifest whose installed contract addresses have been |
Interfaces
| Name | Summary |
|---|---|
AbiEntry | One function, constructor, or event in a contract’s ABI. |
AbiParam | An ABI parameter or return value, with support for nested tuple and struct types. |
CdmJson | A project’s cdm.json manifest. |
CdmJsonContract | A deployed contract’s on-chain address, ABI, and optional metadata CID. |
ContractDef | Per-contract definition shape — generated into .cdm/contracts.d.ts via module augmentation. |
ContractDefaults | Mutable defaults shared across all contract handles from a manager. |
ContractOptions | Options for createContract and base for ContractManagerOptions. |
ContractRevertInfo | Tagged-enum value surfaced on QueryResult.value when a contract reverts |
ContractRuntime | Runtime handle that drives queries and transactions against a |
ContractRuntimeOptions | Options for createContractRuntime / createContractRuntimeFromClient. |
Contracts | Augmentable interface extended by codegen with per-contract method types. |
DecodedContractRevert | viem-decoded standard or ABI-defined contract error. |
LiveContractResolutionOptions | Options for resolving installed CDM contract addresses from the live CDM registry. |
PrepareOptions | Options for .prepare() — subset of TxOptions. |
QueryOptions | Options for query calls — passed as the last argument after positional args. |
ReviveDryRunCallOptions | Per-call options accepted by ReviveDryRunCall. |
ReviveDryRunResult | Dry-run result returned by ReviveApi.call. Mirrors the shape exposed by |
ReviveTypedApi | Structural shape consumed by ContractManager / createContract. |
TxOptions | Options for transaction calls — passed as the last argument after positional args. |
Type Aliases
| Name | Summary |
|---|---|
CdmJsonDependencyVersion | — |
Contract | A typed contract handle where each ABI method exposes .query() and .tx(). |
ContractDryRunAt | Block reference used to target ReviveApi.call dry-runs. Matches PAPI’s |
ContractManagerOptions | Options for ContractManager construction. |
QueryResult | Result from a read-only contract query. |
ReviveDryRunCall | Signature of a ReviveApi.call dry-run, used by the wrapped contract layer |
Re-exports
Convenience re-exports from leaf packages. Click through for the canonical documentation.
| Name | Kind | Source package |
|---|---|---|
BatchableCall | type | @parity/product-sdk-tx |
TxResult | interface | @parity/product-sdk-tx |
Classes
class ContractDryRunFailedError
A pre-flight ReviveApi.call dry-run reported failure. Thrown from the .tx()
path before the extrinsic is built — prevents callers from paying gas on a
transaction the chain already told us would revert.
dispatchError carries the chain’s encoded error (typically ModuleError,
ContractReverted, OutOfGas, or AccountNotMapped — see the Revive
pallet error variants).
Extends: ContractError
Constructors
constructor
new ContractDryRunFailedError(methodName: string, dispatchError: unknown): ContractDryRunFailedErrorProperties
dispatchError
unknownmethodName
stringclass ContractError
Base class for all contract errors. Use instanceof ContractError to catch any contract-related error.
Extends: Error
Constructors
constructor
new ContractError(message: string, options?: ErrorOptions): ContractErrorclass ContractLiveAddressResolutionError
Live CDM registry address resolution failed.
Extends: ContractError
Constructors
constructor
new ContractLiveAddressResolutionError(message: string, options?: { cause?: unknown; detail?: unknown; library?: string }): ContractLiveAddressResolutionErrorProperties
detail
unknownlibrary
string | undefinedclass ContractManager
Manages typed contract interactions backed by a cdm.json manifest.
Pass a signerManager (e.g. a SignerManager from @parity/product-sdk-signer)
so the currently logged-in account is used automatically — no manual
signer/origin wiring needed.
Examples
import { createChainClient } from "@parity/product-sdk-chain-client";
import { paseo_asset_hub } from "@parity/product-sdk-descriptors/paseo-asset-hub";
import { ContractManager, createContractRuntime } from "@parity/product-sdk-contracts";
import cdmJson from "./cdm.json";
const client = await createChainClient({
chains: { assetHub: paseo_asset_hub },
});
const runtime = createContractRuntime(client.assetHub);
const manager = new ContractManager(cdmJson, runtime, {
signerManager,
});
const counter = manager.getContract("@example/counter");
const { value } = await counter.getCount.query();
await counter.increment.tx();Constructors
constructor
new ContractManager(cdmJson: CdmJson, runtime: ContractRuntime, options?: ContractOptions): ContractManagerMethods
getAddress
Get the on-chain address of an installed contract.
getAddress(library: string): HexStringgetContract
Get a typed contract handle.
Each method on the returned object has .query() for read-only calls
and .tx() for signed transactions. When codegen augments
Contracts, passing a known library name returns a fully-typed
handle. Without codegen the generic overload still works — methods are
accessible but untyped.
Overload 1
getContract(library: K): Contract<Contracts[K]>Get a typed contract handle.
Each method on the returned object has .query() for read-only calls
and .tx() for signed transactions. When codegen augments
Contracts, passing a known library name returns a fully-typed
handle. Without codegen the generic overload still works — methods are
accessible but untyped.
Overload 2
getContract(library: string): Contract<ContractDef>Get a typed contract handle.
Each method on the returned object has .query() for read-only calls
and .tx() for signed transactions. When codegen augments
Contracts, passing a known library name returns a fully-typed
handle. Without codegen the generic overload still works — methods are
accessible but untyped.
getRuntime
Get the underlying ContractRuntime backing this manager.
Useful when a consumer needs to call helpers that take a runtime
directly — most commonly ensureContractAccountMapped at app
boot. Avoids the alternative of building a second runtime against the
same client and descriptor.
getRuntime(): ContractRuntimesetDefaults
Update the default origin, signer, or signerManager used by all contract handles.
setDefaults(defaults: ContractDefaults): voidfromClient
Create a ContractManager from a raw PolkadotClient.
Convenience factory: builds a ContractRuntime internally from the
client’s typed API. Requires that the chain’s typed API exposes the
Revive pallet and ReviveApi runtime API (Asset Hub Paseo /
Polkadot / Kusama).
fromClient(cdmJson: CdmJson, client: PolkadotClient, descriptor: TDescriptor, options?: ContractOptions & ContractRuntimeOptions): ContractManagerParameters
cdmJson: The CDM manifest.client: APolkadotClientfor the chain where contracts are deployed.descriptor: The chain descriptor used to derive the typed API.options: Optional configuration (signerManager, defaults).
fromLive
Create a manager after strictly resolving installed contract addresses from the live CDM registry. ABIs still come from the installed manifest.
fromLive(cdmJson: CdmJson, runtime: ContractRuntime, options?: ContractOptions & LiveContractResolutionOptions): Promise<ContractManager>fromLiveClient
Convenience factory for fromLive when the caller has a raw
PolkadotClient and descriptor.
fromLiveClient(cdmJson: CdmJson, client: PolkadotClient, descriptor: TDescriptor, options?: ContractOptions & ContractRuntimeOptions & LiveContractResolutionOptions): Promise<ContractManager>class ContractNotFoundError
A contract was not found in the cdm.json manifest.
Extends: ContractError
Constructors
constructor
new ContractNotFoundError(library: string): ContractNotFoundErrorProperties
library
stringclass ContractRevertedError
A contract call returned with the REVERT flag set on a dispatched-OK call.
Extends: ContractError
Constructors
constructor
new ContractRevertedError(methodName: string, data: HexString, info?: { decoded?: DecodedContractRevert; reason?: string }): ContractRevertedErrorProperties
data
HexStringdecoded
DecodedContractRevertmethodName
stringreason
stringclass ContractSignerMissingError
No signer was available for a transaction call.
Extends: ContractError
Constructors
constructor
new ContractSignerMissingError(): ContractSignerMissingErrorFunctions
createContract()
Create a contract handle from a raw H160 address and ABI — no cdm.json needed.
createContract(runtime: ContractRuntime, address: HexString, abi: AbiEntry[], options?: ContractOptions): Contract<ContractDef>Examples
import { createContractRuntime, createContract } from "@parity/product-sdk-contracts";
const runtime = createContractRuntime(client.assetHub);
const counter = createContract(runtime, "0xC472...", abi, { signerManager });
await counter.getCount.query();
await counter.increment.tx();createContractFromClient()
Create a contract handle from a raw PolkadotClient, descriptor, address, and ABI.
Convenience wrapper that builds the ContractRuntime from the client’s
typed API. The chain must expose Revive + ReviveApi.
createContractFromClient(client: PolkadotClient, descriptor: TDescriptor, address: HexString, abi: AbiEntry[], options?: ContractOptions & ContractRuntimeOptions): Contract<ContractDef>Examples
const counter = createContractFromClient(client, paseo_asset_hub, "0xC472...", abi);
const { value } = await counter.getCount.query();createContractRuntime()
Wrap a typed PAPI API as a ContractRuntime. Intended for tests and
advanced setups where the caller already holds a typed API. Routes the
dry-run through the typed (compatibility-token-checked) ReviveApi.call
— fine for mocks but susceptible to Incompatible runtime entry errors
on a live chain whose descriptor lags. Prefer
createContractRuntimeFromClient for production use.
createContractRuntime(api: ReviveTypedApi, options?: ContractRuntimeOptions): ContractRuntimecreateContractRuntimeFromClient()
Build a ContractRuntime from a raw PolkadotClient plus its descriptor.
The typed API powers tx.Revive.call, tx.Revive.map_account, and
query.Revive.OriginalAccount (extrinsics + storage are tolerant of
descriptor drift). The runtime-API dry-run, which is not tolerant of
descriptor drift on PAPI’s compat-token path, is routed through
client.getUnsafeApi() — bypassing the compat check while preserving
argument and return shapes.
Use this on every production code path that calls a contract’s .tx() or
.query() against a live chain.
createContractRuntimeFromClient(client: PolkadotClient, descriptor: TDescriptor, options?: ContractRuntimeOptions): ContractRuntimeExamples
import { paseo_asset_hub } from "@parity/product-sdk-descriptors/paseo-asset-hub";
import { createContractRuntimeFromClient } from "@parity/product-sdk-contracts";
const runtime = createContractRuntimeFromClient(rawClient, paseo_asset_hub);ensureContractAccountMapped()
Ensure the SS58 account is mapped to its derived H160 on pallet-revive.
pallet-revive requires every signing account to have a registered
OriginalAccount mapping before the runtime accepts its Revive.call
extrinsics. The mapping is one-time and cheap. This helper:
- Reads
Revive.OriginalAccountfor the H160 derived fromaddress. - Returns
nullif already mapped (idempotent fast-path). - Otherwise submits
Revive.map_account()and waits for inclusion.
Call this once per signing account at app startup — after that, every
subsequent contract.<method>.tx({ signer }) against the same chain will
succeed without further mapping work.
ensureContractAccountMapped(runtime: ContractRuntime, address: SS58String, signer: PolkadotSigner, options?: { onStatus?: (s: string) => void; timeoutMs?: number }): Promise<TxResult | null>Parameters
runtime: The contract runtime (typicallycreateContractRuntime(...)).address: The SS58 address of the account to map.signer: A signer matchingaddress.options: Optional timeout / status callback (forwarded to the underlying tx).
Returns
The TxResult from the mapping extrinsic, or null if already mapped.
Examples
import { createContractRuntime, ensureContractAccountMapped } from "@parity/product-sdk-contracts";
const runtime = createContractRuntime(client.getTypedApi(paseo_asset_hub));
await ensureContractAccountMapped(runtime, signerManager.getState().selectedAccount!.address, signer);
// now safe to call contract.<method>.tx({ signer })withLiveContractAddresses()
Return a cloned manifest whose installed contract addresses have been replaced by live addresses from the CDM registry.
This is intentionally strict: if a requested library cannot be resolved
from the registry, the promise rejects. Use new ContractManager(...) or
ContractManager.fromClient(...) directly for snapshot-only behavior.
withLiveContractAddresses(cdmJson: CdmJson, runtime: ContractRuntime, options?: LiveContractResolutionOptions): Promise<CdmJson>Interfaces
interface AbiEntry
One function, constructor, or event in a contract’s ABI.
Properties
inputs
AbiParam[]name
stringoutputs
AbiParam[]stateMutability
stringtype
stringinterface AbiParam
An ABI parameter or return value, with support for nested tuple and struct types.
Properties
components
AbiParam[]name
stringtype
stringinterface CdmJson
A project’s cdm.json manifest.
Properties
contracts
Record<string, CdmJsonContract>dependencies
Record<string, CdmJsonDependencyVersion>registry
HexStringinterface CdmJsonContract
A deployed contract’s on-chain address, ABI, and optional metadata CID.
metadataCid is optional because real-world cdm.json files (e.g.
paritytech/playground-cli/cdm.json) don’t always include it — only
version, address, and abi are load-bearing for getContract().
Properties
abi
AbiEntry[]address
HexStringmetadataCid
stringversion
numberinterface ContractDef
Per-contract definition shape — generated into .cdm/contracts.d.ts via module augmentation.
Properties
methods
Record<string, { args: any[]; response: any }>interface ContractDefaults
Mutable defaults shared across all contract handles from a manager.
Properties
origin
SS58Stringsigner
PolkadotSignersignerManager
SignerManagerinterface ContractOptions
Options for createContract and base for ContractManagerOptions.
Signer resolution order (highest wins):
- Explicit override in call options
signerManager(current logged-in account)- Static
defaultSigner/defaultOrigin
Properties
defaultOrigin
SS58StringStatic fallback caller address for queries.
defaultSigner
PolkadotSignerStatic fallback signer for transactions.
signerManager
SignerManagerSigner manager from @parity/product-sdk-signer. When provided, the
currently selected account is used as the default signer and origin
for all contract interactions. Resolved at call time so account
switches are reflected immediately.
interface ContractRevertInfo
Tagged-enum value surfaced on QueryResult.value when a contract reverts
via the REVERT flag. The discriminant is intentionally distinct from
pallet-revive’s bare { type: "ContractReverted" } dispatch-error variant,
which is the other path that can populate QueryResult.value on failure.
Properties
data
HexStringdecoded
DecodedContractRevertreason
stringtype
"ContractRevertedWithPayload"interface ContractRuntime
Runtime handle that drives queries and transactions against a pallet-revive-capable chain.
Examples
import { createChainClient } from "@parity/product-sdk-chain-client";
import { paseo_asset_hub } from "@parity/product-sdk-descriptors/paseo-asset-hub";
import { createContractRuntimeFromClient } from "@parity/product-sdk-contracts";
const client = await createChainClient({
chains: { assetHub: paseo_asset_hub },
});
const runtime = createContractRuntimeFromClient(client.raw.assetHub, paseo_asset_hub);Properties
api
ReviveTypedApidryRunCall
ReviveDryRunCallDry-run entry point. Production factories route this through the
unsafe API to avoid compatibility-token failures when the descriptor
trails a runtime upgrade. The createContractRuntime test factory
delegates to api.apis.ReviveApi.call.
The runtime default at (set via ContractRuntimeOptions.at on
the factory) is applied when the caller does not pass an explicit
options.at. .query() per-call overrides flow through this argument.
interface ContractRuntimeOptions
Options for createContractRuntime / createContractRuntimeFromClient.
Properties
at
ContractDryRunAtBlock to target for ReviveApi.call dry-runs. Defaults to "best"
so contract .query() reads observe the same state as transactions
resolved at best-block (the product-sdk .tx() default). Set to
"finalized" to read the canonical, lagged state, or to a specific
block hash to pin reads to a historical block. Can be overridden per
call via QueryOptions.at.
interface Contracts
Augmentable interface extended by codegen with per-contract method types.
After running cdm install, a generated .d.ts file augments this
interface so that ContractManager.getContract() returns fully-typed
contract handles.
interface DecodedContractRevert
viem-decoded standard or ABI-defined contract error.
Properties
args
readonly unknown[] | undefinederrorName
stringinterface LiveContractResolutionOptions
Options for resolving installed CDM contract addresses from the live CDM registry.
Properties
libraries
readonly string[]Subset of installed libraries to resolve. Defaults to every contract in the manifest.
registryAddress
HexStringCDM registry contract address. Defaults to cdm.json.registry.
registryOrigin
SS58StringOrigin used for CDM registry dry-run queries. Defaults to defaultOrigin in manager helpers.
interface PrepareOptions
Options for .prepare() — subset of TxOptions.
Signer and submission lifecycle options (signer, waitFor, timeoutMs,
mortalityPeriod, onStatus) are intentionally absent — those belong to
the batch submission, not the individual prepared call.
Properties
at
ContractDryRunAtOverride the block targeted by the sizing dry-run. See
TxOptions.at.
gasLimit
Weightorigin
SS58StringstorageDepositLimit
bigintvalue
bigintinterface QueryOptions
Options for query calls — passed as the last argument after positional args.
Properties
at
ContractDryRunAtOverride the block targeted by this dry-run. Accepts "best",
"finalized", or a block hash. Defaults to the runtime’s configured
at (see createContractRuntimeFromClient({ at })), which is "best"
unless overridden — chosen so .query() observes the same state as
.tx() resolved at best-block.
origin
SS58Stringvalue
bigintinterface ReviveDryRunCallOptions
Per-call options accepted by ReviveDryRunCall.
Note on the trailing options arg: pallet-revive’s Rust runtime API
ReviveApi::call only takes the 6 positional args (origin, dest, value,
gas_limit, storage_deposit_limit, input_data). This 7th options object
is injected by PAPI on every api.apis.X.Y runtime-API call via its
WithCallOptions type wrapper (see
polkadot-api/packages/client/src/viewFns.ts:9-11 upstream — defined
as WithCallOptions$2 in the bundled .d.ts due to TS bundler suffixing).
It never reaches the Rust side — PAPI’s viewFns.ts:38-41 consumes it in
JS, reads options.at, resolves it to a concrete block hash via the
chain-head’s runtime context, and uses that hash on the JSON-RPC
state_call invocation. The 6-arg payload sent over the wire is
unchanged.
Properties
at
ContractDryRunAtinterface ReviveDryRunResult
Dry-run result returned by ReviveApi.call. Mirrors the shape exposed by
descriptors (paseo-asset-hub, polkadot-asset-hub, kusama-asset-hub).
data is a raw Uint8Array because PAPI ≥2.0 dropped the Binary class
wrapper for Vec<u8> codecs.
Properties
gas_consumed
bigintmax_storage_deposit
{ type: "Refund" | "Charge"; value: bigint }result
{ success: true; value: { data: Uint8Array; flags: number } } | { success: false; value: unknown }success: true carries { flags, data }; success: false carries the
dispatch error as the chain encoded it.
storage_deposit
{ type: "Refund" | "Charge"; value: bigint }weight_consumed
Weightweight_required
Weightinterface ReviveTypedApi
Structural shape consumed by ContractManager / createContract.
Properties
apis
{ ReviveApi: { call: unknown } }query
{ Revive: { OriginalAccount: { getValue: unknown } } }tx
{ Revive: { call: ReviveCallTx; map_account: unknown } }interface TxOptions
Options for transaction calls — passed as the last argument after positional args.
Extends: SubmitOptions
Properties
at
ContractDryRunAtOverride the block targeted by the sizing dry-run that .tx() runs
before submission. Accepts "best", "finalized", or a block hash.
Defaults to the runtime’s configured at (see
createContractRuntimeFromClient({ at })), which is "best" unless
overridden. No-op when both gasLimit and storageDepositLimit are
passed — the dry-run is skipped entirely in that case.
gasLimit
Weightorigin
SS58Stringsigner
PolkadotSignerstorageDepositLimit
bigintvalue
bigintType Aliases
type CdmJsonDependencyVersion
type CdmJsonDependencyVersion = number | stringtype Contract
A typed contract handle where each ABI method exposes .query() and .tx().
Both accept the method’s positional arguments followed by an optional options object as the last argument.
type Contract = { [K in keyof C["methods"]]: { prepare: (...args: [...C["methods"][K]["args"], unknown]) => Promise<BatchableCall>; query: (...args: [...C["methods"][K]["args"], unknown]) => Promise<QueryResult<C["methods"][K]["response"]>>; tx: (...args: [...C["methods"][K]["args"], unknown]) => Promise<TxResult> } }type ContractDryRunAt
Block reference used to target ReviveApi.call dry-runs. Matches PAPI’s
runtime-call at option: "best", "finalized", or a block hash.
type ContractDryRunAt = "best" | "finalized" | HexStringtype ContractManagerOptions
Options for ContractManager construction.
type ContractManagerOptions = ContractOptionstype QueryResult
Result from a read-only contract query.
On success, value is the decoded response and gasRequired is the
Weight consumed by ReviveApi.call’s dry-run — consumable directly by
Revive.call’s weight_limit parameter.
On failure, value carries the raw dispatch-error payload the runtime
returned (typically a tagged enum like { type: "Module", value: ... },
{ type: "ContractReverted" }, or { type: "AccountNotMapped" } — see the
Revive pallet error variants). Surfacing it lets callers narrow on shape
to diagnose silent failures instead of seeing undefined and being unable
to tell whether the contract reverted, gas estimation failed, or the
dry-run never ran. gasRequired is still populated when the runtime
reported a weight even though the call ultimately failed (e.g. a revert
after partial execution); it’s optional because some failure modes don’t
carry one.
type QueryResult = { gasRequired: Weight; success: true; value: T } | { gasRequired?: Weight; success: false; value: unknown }type ReviveDryRunCall
Signature of a ReviveApi.call dry-run, used by the wrapped contract layer
to estimate weight + storage deposit and surface revert / OOG /
AccountNotMapped failures before a tx is signed.
Identical to ReviveTypedApi.apis.ReviveApi.call, but extracted so the
runtime can route this single hot call through PAPI’s unsafe API
(skipping compatibility-token checks) on production runtimes whose
descriptors lag a chain upgrade — every other surface still uses the
compat-checked typed API.
type ReviveDryRunCall = (origin: SS58String, dest: HexString, value: bigint, gas_limit: Weight | undefined, storage_deposit_limit: bigint | undefined, input_data: Uint8Array, options?: ReviveDryRunCallOptions) => Promise<ReviveDryRunResult>