Restrictions
Restrictions define per-asset transfer policies for asset destinations and burn permissions. AMP2 uses restrictions as the primary compliance control for issuer-managed transfers.
Restrictions are per asset transfer policies that control where assets can move and whether they can be burned. They are the primary mechanism for regulatory compliance in AMP2.
How restrictions work
Restrictions are defined by the issuer and enforced by the HSM at PSET cosigning time. When a transfer PSET is submitted for cosigning, the HSM checks the source wallet's restriction group for the asset being transferred. If the transfer violates the policy, the HSM refuses to cosign and the transaction cannot be broadcast.
This enforcement is cryptographic, not advisory: there is no way to bypass restrictions without the HSM's signature, and the HSM only signs compliant transactions.
Restriction group fields
| Field | Type | Description |
|---|---|---|
wids | array of WIDs | Wallets this restriction group applies to |
toWhitelist | array of WIDs | Allowed destination wallets for transfers |
useToWhitelist | boolean | If true, only toWhitelist destinations are allowed |
canBurn | boolean | If true, wallets in this group can burn the asset |
Enforcement rules
When a wallet in a restriction group attempts an operation:
| Condition | Check | Result if violated |
|---|---|---|
useToWhitelist: true | Destination WID must be in toWhitelist | Cosign refused |
canBurn: false | Transaction must not include burn outputs | Cosign refused |
| Wallet locked | Wallet must not be in locked state | Cosign refused |
| Asset locked | Asset must not be in locked state | Cosign refused |
If no restriction group is assigned to a wallet for a given asset, transfers of that asset from that wallet are unrestricted.
Single wallet restriction
Apply a restriction to one wallet for one asset using the SDK:
import { AmpActions } from '@blockstream/amp-registry';
const response = await broadcastRequest<
typeof AmpActions.editAssetWalletRestrictions
>(
{
action: 'edit',
resource: '/amp/assets/{aid}/wallets/{wid}/restrictions',
details: {
can_burn: false,
whitelist: ['allowed_wid_1', 'allowed_wid_2'],
wid: 'target_wid',
},
},
blockstream,
);This means: when wid holds this asset, it can only send to allowed_wid_1 or allowed_wid_2, and it cannot burn.
Bulk restrictions
Apply the same policy to multiple wallets at once:
const response = await broadcastRequest<
typeof AmpActions.editAssetWalletRestrictionsList
>(
{
action: 'edit',
resource: '/amp/assets/{aid}/restrictions',
details: {
can_burn: false,
use_to_whitelist: true,
to_whitelist: ['treasury_wid', 'approved_wid_1', 'approved_wid_2'],
wids: ['investor_wid_1', 'investor_wid_2', 'investor_wid_3'],
},
},
blockstream,
);All three investor wallets share the same restriction group. They can send the asset only to the treasury or the two approved wallets.
Querying restrictions
| Action | Resource | Description |
|---|---|---|
get | /amp/assets/{aid}/restrictions | List all restriction groups for an asset (v1) |
get | /amp/assets/v2/{aid}/restrictions | List restrictions with expanded group details (v2) |
get | /amp/assets/{aid}/wallets/{wid}/restrictions | Get restriction for a specific wallet |
Modifying restrictions
Restrictions are managed through edit and delete operations:
| Action | Resource | Description |
|---|---|---|
edit | /amp/assets/{aid}/wallets/{wid}/restrictions | Set restriction for a single wallet |
edit | /amp/assets/{aid}/restrictions | Set restriction for multiple wallets |
delete | /amp/assets/{aid}/wallets/{wid}/restrictions | Delete wallet restriction |
delete | /amp/assets/{aid}/restrictions/group/{gid} | Delete restriction group |
To change a wallet's restriction policy, delete the existing restriction and create a new one. There is no in place update operation.
For the full SDK reference, see the JS SDK restriction docs.
Interaction with locks
Restrictions and locks are independent but complementary:
| State | Effect |
|---|---|
| Asset locked | All operations on this asset are blocked for all wallets |
| Wallet locked | All transfers from this wallet are blocked for all assets |
| UTXO locked | The specific output cannot be spent |
| Restriction violation | The specific transfer is refused, other operations may still work |
Locks are broader than restrictions. A locked asset or wallet blocks everything regardless of restriction policies.
Difference from AMP0 categories
| Aspect | AMP0 Categories | AMP2 Restriction Groups |
|---|---|---|
| Scope | Global (across all assets) | Per asset |
| Model | Group investors, then link to assets | Define policy per asset per wallet |
| Granularity | Category level | Wallet level within a group |
| Enforcement | Application level | HSM level (cryptographic) |
| Burn control | Not available | Per group canBurn flag |
Design guidance
- Keep groups small and explicit. A restriction group should represent a clear compliance boundary (e.g., "verified EU investors for asset X").
- Audit restriction changes. Log every create/delete in your issuer systems with operator, timestamp, and reason.
- Test in testnet first. Restriction enforcement is strict: a misconfigured whitelist will block legitimate transfers.
- Include the treasury wallet in whitelists. Investors typically need to be able to send assets back to the issuer.
Related pages
- Managing Restrictions: SDK code examples
- PSET Lifecycle: where the HSM cosigns and enforces policy
- Lock and Unlock: broader freeze capabilities
PSET lifecycle
Every mutating AMP2 operation follows the same PSET pattern. The page explains the transaction flow for issuer and venue integrations.
Key management
AMP2 requires RSA and ECDSA P-256 key pairs for issuer encryption and request signing. The page explains key generation, format requirements, validation, and rotation.