Skip to main content

RuleBuilder

The RuleBuilder provides a fluent API for constructing individual rules within a policy.

RuleBuilder uses the builder pattern to create rules step-by-step with method chaining. This provides a more intuitive and type-safe way to construct rules compared to manually creating rule objects. The builder ensures that rules are constructed correctly and validates certain constraints at build time.

Examples

// Basic permit rule
const rule = new RuleBuilder()
.permit('USE')
.withDescription('Allow general usage')
.build();

// Time-limited reproduction with payment
const reproductionRule = new RuleBuilder()
.permit('REPRODUCE')
.withDescription('Allow reproduction for one year with payment')
.withConstraint({
type: 'TIME_PERIOD',
value: {
start: Math.floor(Date.now() / 1000),
end: Math.floor(Date.now() / 1000) + 31536000 // One year
}
})
.withDuty({
type: 'PAYMENT',
value: {
amount: '100.00',
currency: 'USD',
recipient: '0xCreatorAddress'
}
})
.build();

// Prohibition rule
const prohibitRule = new RuleBuilder()
.prohibit('COMMERCIALIZE')
.withDescription('No commercial use allowed')
.build();

// Complex rule with multiple constraints and duties
const complexRule = new RuleBuilder()
.permit('MODIFY')
.withDescription('Token holders can modify with attribution')
.withConstraint({
type: 'TOKEN_GATED',
value: {
chainId: 1,
contractAddress: '0xNFTContract',
minBalance: 1
}
})
.withConstraint({
type: 'USAGE_COUNT',
value: 10
})
.withDuty({
type: 'ATTRIBUTION',
value: 'Based on original work by Artist Name'
})
.withDuty({
type: 'SHARE_ALIKE',
value: 'ipfs://QmOriginalPolicy...'
})
.build();

Definition

class RuleBuilder {
constructor();
permit(action: string): this;
prohibit(action: string): this;
withDescription(description: string): this;
withConstraint(constraint: Constraint): this;
withDuty(duty: Duty): this;
withPaymentSplit(options: PaymentSplitOptions): this;
withPaymentSplitPercentage(total: string | number, currency: string, splits: Record): this;
}

Constructor

Methods

permit

Sets the action and a 'permit' effect for the rule.

This method creates a permission rule that allows the specified action. Cannot be used together with prohibit() on the same builder instance.

permit(action: string): this

Parameters:

  • action (string) - The action to permit. Use values from Action or custom URIs.

Returns: this

This RuleBuilder instance for method chaining

Examples

// Using standard action
builder.permit('USE');
builder.permit('TRANSFER');

// Using custom action URI
builder.permit('https://example.com/actions/download');

prohibit

Sets the action and a 'prohibit' effect for the rule.

This method creates a prohibition rule that forbids the specified action. Prohibition rules cannot have duties attached to them. Cannot be used together with permit() on the same builder instance.

prohibit(action: string): this

Parameters:

  • action (string) - The action to prohibit. Use values from Action or custom URIs.

Returns: this

This RuleBuilder instance for method chaining

Examples

// Prohibit commercial use
builder.prohibit('COMMERCIALIZE');

// Prohibit custom action
builder.prohibit('https://example.com/actions/resell');

withDescription

Adds a human-readable description to the rule.

Descriptions help explain the intent and purpose of a rule. They are particularly useful for complex rules with multiple constraints or duties, or when the rule logic needs clarification.

withDescription(description: string): this

Parameters:

  • description (string) - A clear, concise description of the rule's purpose

Returns: this

This RuleBuilder instance for method chaining

Examples

builder
.permit('REPRODUCE')
.withDescription('Allow reproduction for educational purposes only');

builder
.prohibit('TRANSFER')
.withDescription('Asset cannot be transferred or sold to third parties');

withConstraint

Adds a constraint to the rule.

Constraints define conditions that must be met for the rule to apply. Multiple constraints can be added, and ALL must be satisfied (AND logic). Constraints can be standard types from the vocabulary or custom URIs.

withConstraint(constraint: Constraint): this

Parameters:

  • constraint (Constraint) - The constraint object with type and value

Returns: this

This RuleBuilder instance for method chaining

Examples

// Add time period constraint
builder.withConstraint({
type: 'TIME_PERIOD',
value: {
start: 1704067200, // Jan 1, 2024
end: 1735689599 // Dec 31, 2024
}
});

// Add token gate constraint
builder.withConstraint({
type: 'TOKEN_GATED',
value: {
chainId: 1,
contractAddress: '0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D',
minBalance: 1
}
});

// Add multiple constraints
builder
.withConstraint({ type: 'USAGE_COUNT', value: 100 })
.withConstraint({ type: 'SPATIAL', value: 'US' });

withDuty

Adds a duty to the rule. Only applicable to 'permit' rules.

Duties are obligations that must be fulfilled to exercise a permission. Multiple duties can be added, and ALL must be fulfilled. Attempting to add duties to a 'prohibit' rule will throw an error.

withDuty(duty: Duty): this

Parameters:

  • duty (Duty) - The duty object with type and value

Returns: this

This RuleBuilder instance for method chaining

Throws:

  • If attempting to add a duty to a 'prohibit' rule

Examples

// Add payment duty
builder.withDuty({
type: 'PAYMENT',
value: {
amount: '50.00',
currency: 'USD',
recipient: '0xCreatorWallet'
}
});

// Add attribution duty
builder.withDuty({
type: 'ATTRIBUTION',
value: 'Original artwork by Jane Doe'
});

// Add multiple duties
builder
.permit('MODIFY')
.withDuty({
type: 'ATTRIBUTION',
value: 'Based on work by Original Creator'
})
.withDuty({
type: 'SHARE_ALIKE',
value: 'ipfs://QmOriginalPolicyHash'
});

// Error example - cannot add duty to prohibit rule
try {
builder
.prohibit('USE')
.withDuty({ type: 'PAYMENT', value: {...} }); // Throws error!
} catch (error) {
console.error(error.message); // "Duties can only be added to 'permit' rules."
}

withPaymentSplit

Adds multiple PAYMENT duties representing a split payment.

This is a convenience method that generates multiple payment duties from a split configuration. Each recipient becomes a separate duty, maintaining semantic correctness where each duty is an independent obligation.

withPaymentSplit(options: PaymentSplitOptions): this

Parameters:

  • options (PaymentSplitOptions) - The payment split configuration

Returns: this

This RuleBuilder instance for method chaining

Throws:

  • If attempting to add to a 'prohibit' rule
  • If splits don't sum to total

Examples

// Split $100 among three recipients
builder.withPaymentSplit({
total: '100',
currency: 'USDC',
splits: [
{ recipient: 'worker', amount: '70' },
{ recipient: 'platform', amount: '20' },
{ recipient: 'creator', amount: '10' }
]
});

// This generates three separate PAYMENT duties:
// 1. { type: 'PAYMENT', value: { amount: '70', currency: 'USDC', recipient: 'worker' }}
// 2. { type: 'PAYMENT', value: { amount: '20', currency: 'USDC', recipient: 'platform' }}
// 3. { type: 'PAYMENT', value: { amount: '10', currency: 'USDC', recipient: 'creator' }}

withPaymentSplitPercentage

Adds payment duties based on percentage splits.

withPaymentSplitPercentage(total: string | number, currency: string, splits: Record): this

Parameters:

  • total (string | number) - The total payment amount
  • currency (string) - The payment currency
  • splits (Record) - Object mapping recipients to percentages (must sum to 100)

Returns: this

This RuleBuilder instance for method chaining

Examples

builder.withPaymentSplitPercentage('1000', 'USDC', {
'treasury': 50,
'developer': 30,
'designer': 20
});

See Also

Since

Version 1.0.0