Skip to main content
Declarative rules are in early access and are not enabled by default. Talk to us if you’d like to participate.
Declarative rules describe what a request must look like and what happens when it does, so one rule can combine chain, token, amount, destination, and recent spending, or hold a transaction for approvers. This page shows the JavaScript SDK helpers for writing them on a business account.

Before you start

  • Create and initialize a Dynamic client (see Creating a Dynamic Client, Initializing the Dynamic Client).
  • Use @dynamic-labs-sdk/client 1.42.0 or later. The helpers are exported from @dynamic-labs-sdk/client/waas.
  • The helpers run with the signed-in member’s session, not an API token.
  • A layer holds legacy rules or declarative rules, never both. A write that would mix them is refused, and until declarative rules are enabled for your environment a declarative write throws an APIError with code rule_syntax_disabled.

Legacy or declarative

Use the legacy PolicyRules helpers on Policies when an address list, a per-transaction cap, or a key-export block is all you need. Use declarative rules when a rule has to combine conditions, cap spending over time, or require approval only under a specific condition. Before writing a layer, decide whether it names what is forbidden (deny style) or what is permitted (allow style with a deny fallback); see Deny style and allow style.

Which layer to use

replacePolicyLayerRules replaces any of the three, and only business-account admins and environment admins can call it. Approval rules can be written only by a business-account owner or admin, or an environment admin.

Add or update a rule

The examples use this rule from Rule examples. Leave ruleId out to create a rule, and the returned layer contains the generated id.

Read rules

Read the layer, then keep its declarative rules with readPolicyLayerRules and isDeclarativePolicyRule.
For the wallet and signer layers, use getWalletPolicyLayer({ walletAccount }) and getSignerPolicyLayer({ walletAccount, shareSetId }).

Remove a rule

For the wallet and signer layers, use removeWalletPolicyRule({ walletAccount, ruleId }) and removeSignerPolicyRule({ walletAccount, shareSetId, ruleId }).

Replace a layer’s rules

replacePolicyLayerRules sets the layer’s full rule list, so any rule you leave out is removed. Keep the ruleId of every rule you are keeping. scope is { businessAccountId } for the account layer, { walletId } for a wallet layer, or { walletId, shareSetId } for a signer layer.

Approval rules

A rule with then: REQUIRE_APPROVAL holds a matching transaction until enough members approve it. This one holds any transfer of more than 10,000 USDC on an EVM chain until two members with the built-in admin role or the custom cfo role approve it within 24 hours.
  • The member who made the request never counts toward requiredApprovals.
  • Role names are matched without regard to case, and a custom role also counts as the built-in role it inherits.
  • Dynamic does not check that a role exists. If you name a role nobody in the account holds, a matching request can never be approved.
  • The rule’s when decides when approval applies. Unlike a legacy approvalRequirements entry, a declarative requirement has no when of its own, and one that includes it is refused.
To offer real role names when you build an approver picker, list the account’s custom roles. Any member can read them. The built-in roles owner, admin, and viewer are always available and are not in the result.
A matching transaction goes through the same signing quorum flow as a legacy approval rule: the signing call rejects with SigningConsentRequiredError, other members approve the proposal, and the initiator resumes it. Follow Complete a quorum-gated signing operation.

Next steps

Rule examples

Ready-made declarative rules to copy and adjust.

Quorum policies

Approve and resume a quorum-gated signing request.
Last modified on October 23, 2026