> ## Documentation Index
> Fetch the complete documentation index at: https://www.dynamic.xyz/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Manage declarative rules

> Read, add, update, remove, and replace wallet- and signer-layer declarative rules from JavaScript or React.

> [!NOTE]
>
> Declarative rules are in **early access** and are not enabled by default. [Talk to us](https://www.dynamic.xyz/talk-to-us) if you'd like to participate.

These helpers write [declarative rules](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/declarative-rules.md) to the wallet layer and to the caller's own signer layer. They run with the signed-in end user's session (the wallet owner, or a business-account owner or admin), not an API token. For the legacy `PolicyRules` helpers, see [Manage Policies](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/manage-policies.md).

## Before you start

* Create and initialize a Dynamic client (see [Creating a Dynamic Client](https://www.dynamic.xyz/docs/javascript/reference/client/create-dynamic-client.md), [Initializing the Dynamic Client](https://www.dynamic.xyz/docs/javascript/reference/client/initialize-dynamic-client.md)).
* Use `@dynamic-labs-sdk/client` and `@dynamic-labs-sdk/react-hooks` 1.42.0 or later. The helpers are exported from `@dynamic-labs-sdk/client/waas`, and the hooks from `@dynamic-labs-sdk/react-hooks`.
* `walletAccount` below is the WaaS wallet account, for example one returned by `getWalletAccounts()`.
* 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 is refused with `rule_syntax_disabled`.

The examples use this rule from [Rule examples](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/rule-examples.md):

```javascript theme={"system"}
import {
  WaasPolicyAction,
  WaasPolicyDeclarativeRuleInputPhaseEnum,
} from '@dynamic-labs/sdk-api-core';

const rule = {
  ruleId: '00000000-0000-4000-8000-000000000004',
  name: 'Blocked address',
  phase: WaasPolicyDeclarativeRuleInputPhaseEnum.Transaction,
  then: WaasPolicyAction.Deny,
  when: {
    exists: {
      in: 'counterparties',
      where: { field: 'address', op: 'in', value: ['0x0000000000000000000000000000000000000bad'] },
    },
  },
};
```

## Read rules

`getWalletPolicyLayer` and `getSignerPolicyLayer` return the layer. `readPolicyLayerRules` returns its entries, and `isDeclarativePolicyRule` tells declarative rules apart from legacy ones.

**JavaScript**

```javascript theme={"system"}
import {
  getWalletPolicyLayer,
  isDeclarativePolicyRule,
  readPolicyLayerRules,
} from '@dynamic-labs-sdk/client/waas';

const layer = await getWalletPolicyLayer({ walletAccount });
const rules = readPolicyLayerRules(layer).filter(isDeclarativePolicyRule);
```

**React**

```tsx theme={"system"}
import { isDeclarativePolicyRule, readPolicyLayerRules } from '@dynamic-labs-sdk/client/waas';
import { useGetWalletPolicyLayer } from '@dynamic-labs-sdk/react-hooks';

const { data: layer } = useGetWalletPolicyLayer({ walletAccount });
const rules = layer ? readPolicyLayerRules(layer).filter(isDeclarativePolicyRule) : [];
```

For the caller's own signer layer, use `getSignerPolicyLayer({ walletAccount })` or `useGetSignerPolicyLayer({ walletAccount })`.

## Add or update a rule

An upsert creates the rule, or updates it when its `ruleId` already exists on the layer. Leave `ruleId` out to create a rule, and the returned layer contains the generated id.

**JavaScript**

```javascript theme={"system"}
import { upsertWalletPolicyRule } from '@dynamic-labs-sdk/client/waas';

const layer = await upsertWalletPolicyRule({ walletAccount, rule });
```

**React**

```tsx theme={"system"}
import { useUpsertWalletPolicyRule } from '@dynamic-labs-sdk/react-hooks';

const { mutate: upsertRule, isPending } = useUpsertWalletPolicyRule();

<button onClick={() => upsertRule({ walletAccount, rule })} disabled={isPending}>
  Save rule
</button>;
```

For the caller's own signer layer, use `upsertSignerPolicyRule({ walletAccount, rule })` or `useUpsertSignerPolicyRule`.

## Remove a rule

**JavaScript**

```javascript theme={"system"}
import { removeWalletPolicyRule } from '@dynamic-labs-sdk/client/waas';

const layer = await removeWalletPolicyRule({
  walletAccount,
  ruleId: '00000000-0000-4000-8000-000000000004',
});
```

**React**

```tsx theme={"system"}
import { useRemoveWalletPolicyRule } from '@dynamic-labs-sdk/react-hooks';

const { mutate: removeRule } = useRemoveWalletPolicyRule();

<button onClick={() => removeRule({ walletAccount, ruleId: '00000000-0000-4000-8000-000000000004' })}>
  Remove rule
</button>;
```

For the caller's own signer layer, use `removeSignerPolicyRule({ walletAccount, ruleId })` or `useRemoveSignerPolicyRule`.

## Replace the 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. Use `scope: { walletId }` for the wallet layer, where `walletId` is the wallet's `verifiedCredentialId`, or `scope: { shareSetId }` for the caller's own signer layer. Only environment admins and business-account admins can replace a layer.

**JavaScript**

```javascript theme={"system"}
import { replacePolicyLayerRules } from '@dynamic-labs-sdk/client/waas';

const layer = await replacePolicyLayerRules({
  scope: { walletId: walletAccount.verifiedCredentialId },
  rules: [rule],
});
```

**React**

```tsx theme={"system"}
import { useReplacePolicyLayerRules } from '@dynamic-labs-sdk/react-hooks';

const { mutate: replaceRules } = useReplacePolicyLayerRules();

<button
  onClick={() =>
    replaceRules({ scope: { walletId: walletAccount.verifiedCredentialId }, rules: [rule] })
  }
>
  Save rules
</button>;
```

## Errors

The write helpers throw an `APIError` when the request is refused. Its `code` tells you why, for example `rule_syntax_disabled` when declarative rules are not enabled for the environment, or `composition_layer_edit_mixed_rule_syntax` when the write would mix legacy and declarative rules.

## Next steps

> **[Rule examples](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/rule-examples.md)**
>
> Ready-made declarative rules.

> **[Manage Policies](https://www.dynamic.xyz/docs/embedded-wallets/mpc/policies/manage-policies.md)**
>
> The legacy `PolicyRules` helpers.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.