> ## 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 Policies

> Create, read, and remove wallet- and signer-layer policy rules for any embedded wallet.

<Note>
  Wallet and signer policy layers are in **early access**. [Talk to us](https://www.dynamic.xyz/talk-to-us) if you'd like to participate.
</Note>

These helpers work for any embedded wallet. A wallet's owner sets its wallet-layer rules, and a signer sets their own signer-layer rules. Business-account wallets add one more layer on top: see the [business accounts policies guide](/docs/javascript/reference/business-accounts/policies/overview) for the account-layer helpers.

## Before you start

Before this: create and initialize a Dynamic client (see [Creating a Dynamic Client](/docs/javascript/reference/client/create-dynamic-client), [Initializing the Dynamic Client](/docs/javascript/reference/client/initialize-dynamic-client)).

The policy helpers are exported from `@dynamic-labs-sdk/client/waas`, and the matching React hooks are exported from `@dynamic-labs-sdk/react-hooks`.

## PolicyRules keys

`createPolicy` and `removePolicyRules` work with a `PolicyRules` map. Each key maps to at most one underlying `WaasPolicyRule`, so calling `createPolicy` again with the same key updates that rule in place instead of duplicating it.

| Key                       | Type                                 | Description                                                                                                                     |
| ------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
| `allowAddresses`          | `string[]`                           | Only allow transactions that interact with these addresses. Combine with `maxAmountPerTransaction` to cap the same allow rule.  |
| `denyAddresses`           | `string[]`                           | Deny transactions that interact with these addresses. Independent of `allowAddresses`.                                          |
| `blockExport`             | `boolean`                            | When `true`, blocks exporting the wallet's private key.                                                                         |
| `maxAmountPerTransaction` | `{ amount: string; asset?: string }` | Cap the value of a single transaction, in the asset's smallest unit. Omit `asset` to cap the chain's native asset.              |
| `names`                   | `object`                             | Set a custom name for each rule kind. Keys are `allowAddresses`, `blockExport`, `denyAddresses`, and `maxAmountPerTransaction`. |

For the raw fields these keys produce, see [Rule fields](/docs/embedded-wallets/mpc/policies/overview#rule-fields).

## Create or update rules

`createPolicy` writes a `PolicyRules` map to a layer in one batch. The `scope` object decides which layer is updated: `{ walletId }` for the wallet layer, or `{ shareSetId }` for the caller's own signer layer.

### Wallet-Layer

Use `scope: { walletId }`, where `walletId` is the wallet's `verifiedCredentialId`. Only the wallet owner can set this layer.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    import { createPolicy } from '@dynamic-labs-sdk/client/waas';
    import { WaasChainEnum } from '@dynamic-labs/sdk-api-core';

    const walletId = walletAccount.verifiedCredentialId;

    const layer = await createPolicy({
      scope: { walletId },
      chain: WaasChainEnum.Evm,
      chainIds: [1],
      rules: {
        allowAddresses: ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'],
        maxAmountPerTransaction: { amount: '100000000000' }, // 100 USDC
      },
    });
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { useCreatePolicy } from '@dynamic-labs-sdk/react-hooks';
    import { WaasChainEnum } from '@dynamic-labs/sdk-api-core';

    const SaveWalletPolicy = ({ walletId }: { walletId: string }) => {
      const { mutate: createPolicy, isPending } = useCreatePolicy();

      return (
        <button
          onClick={() =>
            createPolicy({
              scope: { walletId },
              chain: WaasChainEnum.Evm,
              chainIds: [1],
              rules: {
                allowAddresses: ['0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48'],
                maxAmountPerTransaction: { amount: '100000000000' },
              },
            })
          }
          disabled={isPending}
        >
          Save wallet policy
        </button>
      );
    };
    ```
  </Tab>
</Tabs>

### Signer-Layer

Use `scope: { shareSetId }` to set rules for the caller's own signer. A wallet account has one own share set that signs transactions, and it can also have other active share sets, such as delegated access.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    import { createPolicy } from '@dynamic-labs-sdk/client/waas';
    import { WaasChainEnum } from '@dynamic-labs/sdk-api-core';

    const layer = await createPolicy({
      scope: { shareSetId: walletAccount.shareSetId },
      chain: WaasChainEnum.Evm,
      chainIds: [1],
      rules: { blockExport: true },
    });
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { useCreatePolicy } from '@dynamic-labs-sdk/react-hooks';
    import { WaasChainEnum } from '@dynamic-labs/sdk-api-core';

    const BlockExport = ({ shareSetId }: { shareSetId: string }) => {
      const { mutate: createPolicy, isPending } = useCreatePolicy();

      return (
        <button
          onClick={() =>
            createPolicy({
              scope: { shareSetId },
              chain: WaasChainEnum.Evm,
              chainIds: [1],
              rules: { blockExport: true },
            })
          }
          disabled={isPending}
        >
          Block key export
        </button>
      );
    };
    ```
  </Tab>
</Tabs>

<Note>
  A `shareSetId` is the current identifier for a signer. It rotates when the wallet shares are refreshed or reshared, so do not store it. Re-read `walletAccount.shareSetId` before each update.
</Note>

## Read rules

`getPolicy` fetches a layer and converts the underlying rules back into a `PolicyRules` map. Rules with fields that `PolicyRules` does not include go into `unmapped`, so they are never silently dropped.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    import { getPolicy } from '@dynamic-labs-sdk/client/waas';

    const { rules, unmapped } = await getPolicy({
      scope: { walletId },
    });

    // rules.allowAddresses, rules.maxAmountPerTransaction, etc.
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { useGetPolicy } from '@dynamic-labs-sdk/react-hooks';

    const WalletPolicy = ({ walletId }: { walletId: string }) => {
      const { data: policy, isLoading } = useGetPolicy({ scope: { walletId } });

      if (isLoading) return null;

      return <pre>{JSON.stringify(policy?.rules, null, 2)}</pre>;
    };
    ```
  </Tab>
</Tabs>

## Remove rules

`removePolicyRules` removes the rules for one or more `PolicyRules` keys in one batch. Pass the keys to remove in the `rules` array.

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={"system"}
    import { removePolicyRules } from '@dynamic-labs-sdk/client/waas';

    const layer = await removePolicyRules({
      scope: { walletId },
      chain: 'EVM',
      chainIds: [1],
      rules: ['maxAmountPerTransaction'],
    });
    ```
  </Tab>

  <Tab title="React">
    ```tsx theme={"system"}
    import { useRemovePolicyRules } from '@dynamic-labs-sdk/react-hooks';

    const RemoveCap = ({ walletId }: { walletId: string }) => {
      const { mutate: removeRules, isPending } = useRemovePolicyRules();

      return (
        <button
          onClick={() =>
            removeRules({
              scope: { walletId },
              chain: 'EVM',
              chainIds: [1],
              rules: ['maxAmountPerTransaction'],
            })
          }
          disabled={isPending}
        >
          Remove cap
        </button>
      );
    };
    ```
  </Tab>
</Tabs>

## Who can update a rule

| Caller       | Can update these layers        |
| ------------ | ------------------------------ |
| Wallet owner | Their wallet and signer layers |
| Signer       | Their own signer layer         |

Business accounts extend this: an owner or admin can also manage every wallet and signer in the account, plus an account-wide layer that applies to all of them. See [business account policies](/docs/javascript/reference/business-accounts/policies/overview).

## Next steps

<CardGroup cols={2}>
  <Card title="Policy Layers" href="/docs/embedded-wallets/mpc/policies/policy-layers">
    How environment, wallet, and signer rules combine.
  </Card>

  <Card title="Business account policies" icon="building" href="/docs/javascript/reference/business-accounts/policies/overview">
    The extra account-layer rule for business-account wallets.
  </Card>
</CardGroup>
