Restriction management
Restrictions control asset destinations and burn permissions. The page explains restriction concepts, queries, updates, enforcement, and operational guidance.
Restrictions control where an asset can be sent and whether it can be burned. They are the primary compliance tool in AMP2.
For a hard block that prevents a specific wallet from touching an asset at all, see the Blacklist page. Restrictions and the blacklist solve different problems and can be used together — see Restrictions vs blacklist below.
Restriction concepts
| Field | Meaning |
|---|---|
wids | Wallets this restriction group applies to |
toWhitelist | Allowed destination wallets for transfers |
useToWhitelist | If true, only whitelist destinations allowed |
canBurn | If true, wallets in this group can burn the asset |
Restrictions are enforced by the HSM at PSET cosigning time. If a transfer or burn violates the active policy, AMP2 refuses to cosign.
Create a single wallet restriction
Apply a restriction to one wallet for one asset:
import {
EditAssetWalletRestrictionRequestSchema,
type AmpActions,
} from '@blockstream/amp-registry';
const restrictionResult = await broadcastRequest<
typeof AmpActions.editAssetWalletRestrictions
>({
action: 'edit',
resource: `/amp/assets/${assetId}/wallets/${walletId}/restrictions`,
details: {
can_burn: false,
whitelist: [treasuryWid, approvedInvestorWid],
},
}, broadcaster);
if (restrictionResult.status !== 'success') {
throw new Error(`Failed to set restriction: ${restrictionResult.message}`);
}This means: when walletId holds this asset, it can only send to treasuryWid or approvedInvestorWid. It cannot burn.
Create bulk restrictions
Apply the same policy to multiple wallets:
import type { AmpActions } from '@blockstream/amp-registry';
const bulkRestrictionResult = await broadcastRequest<
typeof AmpActions.editAssetWalletRestrictionsList
>({
action: 'edit',
resource: `/amp/assets/${assetId}/restrictions`,
details: {
can_burn: false,
use_to_whitelist: true,
to_whitelist: [treasuryWid, approvedWid1, approvedWid2],
wids: [investorWid1, investorWid2, investorWid3],
},
}, broadcaster);All three investor wallets now share the same restriction group with the same whitelist and burn permissions.
Query restrictions
V1 format
const restrictions = await broadcastRequest<
typeof AmpActions.getAssetRestrictions
>({
action: 'get',
resource: `/amp/assets/${assetId}/restrictions`,
}, broadcaster);V2 format (expanded group details)
const restrictionsV2 = await broadcastRequest<
typeof AmpActions.getAssetRestrictionsV2
>({
action: 'get',
resource: `/amp/assets/v2/${assetId}/restrictions`,
}, broadcaster);
if (restrictionsV2.status !== 'success') {
throw new Error('Failed to get asset restrictions');
}The V2 response includes expanded group membership details.
Per wallet restriction
const walletRestriction = await broadcastRequest<
typeof AmpActions.getAssetWalletRestrictions
>({
action: 'get',
resource: `/amp/assets/${assetId}/wallets/${walletId}/restrictions`,
}, broadcaster);Delete restrictions
Delete a wallet's restriction
await broadcastRequest<
typeof AmpActions.deleteAssetWalletRestrictions
>({
action: 'delete',
resource: `/amp/assets/${assetId}/wallets/${walletId}/restrictions`,
}, broadcaster);Delete an entire restriction group
await broadcastRequest<
typeof AmpActions.deleteAssetWalletRestrictionByGroup
>({
action: 'delete',
resource: `/amp/assets/${assetId}/restrictions/group/${groupId}`,
}, broadcaster);Updating restrictions
There is no separate update operation. You update a restriction by sending it again to the same resource. What happens next depends on the group type.
Single group
Re-send the restriction to the per-wallet resource. The existing restriction is replaced atomically in one request — no delete step is needed.
- The restriction is issued a new
group_idon every update. Do not cache group ids for single restrictions. - If the wallet currently belongs to a multiple group, the request is rejected
with
409. Remove it from that group first.
Multiple group
Re-send the restriction to the asset-level resource with the existing
group_id. The group keeps its identity, and can_burn, use_to_whitelist
and to_whitelist are updated in place. Omit group_id and you create a new
group instead.
wids replaces the group membership; it does not add to it. Any wallet in
the group but missing from wids is removed and becomes unrestricted — not
blocked. Always send the complete membership list.
If any submitted wallet already belongs to a different group for this asset, the
request is rejected with 409 listing those wallets, and nothing is changed.
Moving a wallet to a different group
A wallet cannot be added to a group while it still belongs to another group for
the same asset — the request is rejected with 409. Regrouping therefore always
takes two steps: delete the wallet's current restriction, then add it to the
target group. This applies to every change of group, including single → multiple
and multiple → single.
Enforcement and transfer relationship
When an issuer calls the send endpoint:
- AMP2 constructs the PSET with the requested recipients.
- The HSM checks the source wallet's restriction group for this asset.
- If
useToWhitelististrue, every recipient must be in thetoWhitelist. - If the transaction burns tokens,
canBurnmust betruefor the source wallet. - If any check fails, the cosign request is refused.
Restrictions vs blacklist
Restrictions and the blacklist are separate mechanisms. Use restrictions to shape where an asset may flow; use the blacklist to stop a wallet from handling the asset at all.
| Restrictions (whitelist / burn) | Blacklist | |
|---|---|---|
| Granularity | A restriction group over one or more wallets | A single (asset, wallet) pair |
| Effect | Limits allowed transfer destinations and burn permission | Blocks the wallet from moving the asset entirely |
| Direction | Applied to the source wallet's outgoing transfers | Applies whether the wallet is the sender or the recipient |
| Manage via | /amp/assets/{aid}/wallets/{wid}/restrictions | /amp/assets/{aid}/wallet/{wid}/blacklist |
A wallet can be subject to both at once. If a wallet is blacklisted for an asset, the transfer is rejected regardless of any whitelist that would otherwise allow it.
Operational guidance
- Always include the treasury wallet in whitelists: investors typically need to be able to return assets to the issuer.
- Don't delete to change policy: re-send the restriction to the same resource instead. Deleting first leaves the wallet unrestricted until the new policy lands.
- Log all restriction changes: record operator, timestamp, reason, and the old/new policy in your issuer systems.
- Test on testnet: restriction enforcement is strict. A misconfigured whitelist will block legitimate transfers with no override.
- Clear both sides when unblocking: a blacklist blocks sender and recipient independently. If both ends of a transfer are blacklisted, remove both records before retrying.
Next steps
- Blacklist: hard block a wallet from an asset
- Restrictions (Concepts): detailed restriction model
- Sending Assets: how restrictions interact with transfers
- Lock and Unlock: broader freeze capabilities
Sending assets
Asset send operations move tokens from one wallet to one or more recipient wallets. The page explains request setup, PSET handling, restrictions, fees, and verification.
Blacklist
The blacklist lets an issuer block specific wallets from transacting a given asset. A blacklist record is scoped to a single (asset, wallet) pair and is enforced on every transfer involving that wallet for that asset.