The tagging feature allows users to organize and categorize their savings goals, bills, and insurance policies using custom string labels (tags). This enables better grouping, filtering, and analytics across all financial entities.
Tags have been added to the following structs:
-
Bill (
bill_payments/src/lib.rs)- Added
tags: Vec<String>field - Tags are preserved when bills are archived
- Tags are copied to recurring bills
- Added
-
ArchivedBill (
bill_payments/src/lib.rs)- Added
tags: Vec<String>field - Tags are preserved from the original bill
- Added
-
SavingsGoal (
savings_goals/src/lib.rs)- Added
tags: Vec<String>field
- Added
-
InsurancePolicy (
insurance/src/lib.rs)- Added
tags: Vec<String>field
- Added
Each contract provides owner-only functions to manage tags:
pub fn add_tags_to_bill(
env: Env,
caller: Address,
bill_id: u32,
tags: Vec<String>,
) -> Result<(), Error>
pub fn remove_tags_from_bill(
env: Env,
caller: Address,
bill_id: u32,
tags: Vec<String>,
) -> Result<(), Error>pub fn add_tags_to_goal(
env: Env,
caller: Address,
goal_id: u32,
tags: Vec<String>,
)
pub fn remove_tags_from_goal(
env: Env,
caller: Address,
goal_id: u32,
tags: Vec<String>,
)pub fn add_tags_to_policy(
env: Env,
caller: Address,
policy_id: u32,
tags: Vec<String>,
)
pub fn remove_tags_from_policy(
env: Env,
caller: Address,
policy_id: u32,
tags: Vec<String>,
)All contracts enforce the following validation rules:
- Tags cannot be empty (at least one tag must be provided)
- Each tag must be between 1 and 32 characters in length
- Tags are case-sensitive
- Duplicate tags are allowed
Tag operations emit events for tracking and analytics:
tags_add: Emitted when tags are added to a bill- Data:
(bill_id, owner, tags)
- Data:
tags_rem: Emitted when tags are removed from a bill- Data:
(bill_id, owner, tags)
- Data:
tags_add: Emitted when tags are added to a goal- Data:
(goal_id, owner, tags)
- Data:
tags_rem: Emitted when tags are removed from a goal- Data:
(goal_id, owner, tags)
- Data:
tags_add: Emitted when tags are added to a policy- Data:
(policy_id, owner, tags)
- Data:
tags_rem: Emitted when tags are removed from a policy- Data:
(policy_id, owner, tags)
- Data:
- Only the owner of an entity (bill, goal, or policy) can add or remove tags
- All tag operations require authentication via
caller.require_auth() - Unauthorized attempts will result in a panic or error
- Tags are stored as part of the entity struct
- Tags are included in all query results (paginated and single-entity queries)
- Tags persist across entity lifecycle (e.g., when bills are archived)
- Tags are copied to recurring bills when a bill is paid
let tags = vec![
String::from_str(&env, "utilities"),
String::from_str(&env, "monthly"),
String::from_str(&env, "high-priority")
];
client.add_tags_to_bill(&owner, &bill_id, &tags);let tags_to_remove = vec![
String::from_str(&env, "old-tag")
];
client.remove_tags_from_goal(&owner, &goal_id, &tags_to_remove);let tags = vec![
String::from_str(&env, "health"),
String::from_str(&env, "family")
];
client.add_tags_to_policy(&owner, &policy_id, &tags);Tags are automatically included in all paginated query results:
get_unpaid_billsget_all_bills_for_ownerget_archived_billsget_active_policiesget_goals
When bills are archived, their tags are preserved in the ArchivedBill struct.
When a recurring bill is paid and a new bill is created, the tags are copied to the new bill.
Error::EmptyTags(12): Returned when trying to add/remove an empty tag listError::InvalidTag(13): Returned when a tag is invalid (empty or > 32 characters)Error::Unauthorized(5): Returned when a non-owner tries to modify tagsError::BillNotFound(1): Returned when the bill doesn't exist
These contracts use panics for error handling:
- "Tags cannot be empty": When trying to add/remove an empty tag list
- "Tag must be between 1 and 32 characters": When a tag is invalid
- "Only the [entity] owner can [add/remove] tags": When unauthorized
- "[Entity] not found": When the entity doesn't exist
Potential improvements for the tagging system:
- Tag-based Filtering: Add query functions to filter entities by tags
- Tag Analytics: Aggregate statistics by tag (e.g., total amount by tag)
- Tag Suggestions: Auto-suggest tags based on entity names or patterns
- Tag Limits: Enforce maximum number of tags per entity
- Tag Normalization: Automatically normalize tags (lowercase, trim whitespace)
- Predefined Tags: Support for system-defined tag categories