address-list
On-chain address list where membership = owning x1 of token ID 1. Manager can add/remove addresses.
Address List
Instruction text for agents that use the Address List skill, loaded by bb dev skills address-list and the MCP get_skill_instructions tool.
Try it
Paste this into Claude Code, Codex, or Cursor with the BitBadges MCP server wired. The agent loads the skill, builds, verifies, and hands back a link to review and sign.
Load the address-list skill and build me one: on-chain address list where membership = owning x1 of token ID 1. Manager can add/remove addresses. Use the session tools, run validate, review, and simulate in parallel, fix anything critical, then call get_review_url and give me the link.From a shell, bb dev skills address-list prints the same instructions.
Summary
Required standards: ["Address List"]
- validTokenIds: must be exactly [{ "start": "1", "end": "1" }]
- Two collection approvals required with exact approvalIds (frontend depends on these):
- "manager-add": fromListId "Mint", toListId "All", initiatedByListId = creator. Mints token to add address.
- "manager-remove": fromListId "!Mint", toListId burn address (bb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs7gvmv), initiatedByListId = creator. Burns token to remove address.
- Both approvals must have overridesFromOutgoingApprovals: true
- No peer-to-peer transfer approval, only manager can modify the list
- Standard is "Address List" (not "Non-Transferable")
- Use per-field tools (set_standards, add_approval, set_permissions, set_invariants)
Instructions
Address List Configuration
An address list collection represents membership as token ownership: owning x1 of token ID 1 = being on the list. The manager controls membership by minting (adding) and burning (removing) tokens.
Preferred path: presets (two short tool calls)
Both approvals are fully canonical, the only param that varies is the manager/creator address. Use the presets:
add_preset_approval({ presetId: "address-list.manager-add", params: { creatorAddress: "bb1..." } })
add_preset_approval({ presetId: "address-list.manager-remove", params: { creatorAddress: "bb1..." } })list_presets({skill: "address-list"}) enumerates them. For non-canonical variants (e.g. a committee instead of a single manager) fall back to raw add_approval.
Critical: Exact Approval IDs Required
The frontend identifies address list approvals by their exact approvalIds. Using different IDs will break the UI.
- Approval 1: approvalId must be "manager-add"
- Approval 2: approvalId must be "manager-remove"
Required Structure
- Standards: ["Address List"] (not "Non-Transferable")
- validTokenIds: [{ "start": "1", "end": "1" }]
- Burn address: bb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs7gvmv (ETH null address in bb1 format)
Manager-Add Approval (mint to add)
{
"fromListId": "Mint",
"toListId": "All",
"initiatedByListId": "bb1creator...",
"transferTimes": [{ "start": "1", "end": "18446744073709551615" }],
"tokenIds": [{ "start": "1", "end": "1" }],
"ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }],
"uri": "ipfs://METADATA_APPROVAL_manager-add",
"customData": "",
"approvalId": "manager-add",
"approvalCriteria": {
"overridesFromOutgoingApprovals": true
},
"version": "0"
}Manager-Remove Approval (forceful burn to remove)
fromListId must be "!Mint" (All except Mint). Using "All" is rejected by the chain with "Mint address cannot be included in address list with other addresses", the Mint slot can only appear in a list by itself.
{
"fromListId": "!Mint",
"toListId": "bb1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqs7gvmv",
"initiatedByListId": "bb1creator...",
"transferTimes": [{ "start": "1", "end": "18446744073709551615" }],
"tokenIds": [{ "start": "1", "end": "1" }],
"ownershipTimes": [{ "start": "1", "end": "18446744073709551615" }],
"uri": "ipfs://METADATA_APPROVAL_manager-remove",
"customData": "",
"approvalId": "manager-remove",
"approvalCriteria": {
"overridesFromOutgoingApprovals": true
},
"version": "0"
}Invariants
Do not set noForcefulPostMintTransfers: true on address-list collections. That invariant would block manager-remove from burning tokens (since its overridesFromOutgoingApprovals: true is only chain-allowed when fromListId is exactly "Mint"). The manager must be able to forcibly burn a list member's token, so leave that invariant off. Other default invariants (e.g. noCustomOwnershipTimes) are fine.
Default Balances
{
"balances": [],
"outgoingApprovals": [],
"incomingApprovals": [],
"autoApproveAllIncomingTransfers": true,
"autoApproveSelfInitiatedOutgoingTransfers": true,
"autoApproveSelfInitiatedIncomingTransfers": true,
"userPermissions": {}
}Permissions
Lock approvals and token IDs:
- canUpdateCollectionApprovals: frozen
- canUpdateValidTokenIds: frozen
- canUpdateManager: frozen (typically)
Common Mistakes
- Don't use approvalId other than "manager-add" and "manager-remove", the frontend depends on these exact strings.
- Don't use standard "Non-Transferable", address lists use "Address List".
- Don't add a peer-to-peer transfer approval, only the manager should modify the list.
- Don't forget overridesFromOutgoingApprovals: true on both approvals.