What are Deals?
Deals are the foundation of the IOTA Repstation system. They represent agreements between two parties (Party A and Party B) that enable mutual rating after completion. Every rating in the system must be tied to a specific deal, ensuring accountability and preventing spam ratings.
Deal Lifecycle
Deals follow a strict three-state lifecycle:
PENDING
Deal is created by Party A but not yet accepted by Party B.
Only Party A can modify or cancel
No ratings allowed
Party B can accept to move to ACTIVE
ACTIVE
Both parties have agreed to the deal terms.
Deal is locked and cannot be modified
No ratings allowed yet
Either party can close the deal
CLOSED
Deal has been completed and closed.
Both parties can now rate each other
Deal cannot be reopened
Ratings can be updated or revoked
Deal Components
Participants
Each deal has exactly two participants:
Party A : The deal initiator (usually the service requester)
Party B : The deal acceptor (usually the service provider)
Subject Reference
Every deal includes a subject reference that identifies what the deal is about:
interface SubjectReference {
type : string ; // e.g., "NFT", "SERVICE", "ORDER"
id : string ; // e.g., "nft-123", "order-456"
}
Common Subject Types:
NFT - Non-fungible token transactions
SERVICE - Service agreements
ORDER - Purchase orders
LOAN - Lending agreements
ESCROW - Escrow services
Deal Amount
The monetary value associated with the deal, stored as a string to handle large numbers:
// Examples
amount : "1000" // 1000 units
amount : "250000" // 250k units
amount : "0" // Free service
Creating Deals
Admin-Created Deals
Applications with admin capabilities can create deals directly:
const { deal_id } = await client . openDealAdmin ({
signer: adminWallet ,
admin_cap_id: adminCapability ,
party_b: customerWallet ,
subject_ref: {
type: "ORDER" ,
id: "ORD-2024-001"
},
amount: "15000"
});
Client-Created Deals
Users with client capabilities can create deals:
const { deal_id } = await client . openDealClient ({
signer: userWallet ,
client_cap_id: userCapability ,
party_b: providerWallet ,
subject_ref: {
type: "SERVICE" ,
id: "web-design-project"
},
amount: "50000"
});
Deal Acceptance
Only Party B can accept a pending deal:
// Party B accepts the deal
await client . acceptDeal ({
signer: partyBWallet ,
deal_id: dealId
});
Once a deal is accepted, it cannot be modified. Ensure all terms are agreed upon before acceptance.
Deal Completion
Either party can close an active deal:
// Close the deal when work is completed
await client . closeDeal ({
signer: partyWallet , // Can be either party
deal_id: dealId
});
Deal States and Permissions
State Party A Can Party B Can Ratings Allowed PENDING Cancel, Close Accept ❌ ACTIVE Close Close ❌ CLOSED Rate Party B Rate Party A ✅
Best Practices
1. Clear Subject References
Use descriptive and unique subject references:
// Good
subject_ref : {
type : "NFT_MARKETPLACE_SALE" ,
id : "cryptopunk-7804-sale-2024"
}
// Avoid
subject_ref : {
type : "SALE" ,
id : "123"
}
2. Accurate Amounts
Always specify the correct deal amount:
// For a $150 service (assuming token has 2 decimals)
amount : "15000" // 150.00 in smallest units
3. Timely Deal Closure
Close deals promptly when work is completed to enable rating:
// In your application logic
async function markOrderDelivered ( orderId : string ) {
// Update your database
await db . orders . update ( orderId , { status: 'delivered' });
// Close the reputation deal
const order = await db . orders . findById ( orderId );
await reputationClient . closeDeal ({
signer: adminWallet ,
deal_id: order . reputationDealId
});
}
Error Handling
Common deal-related errors and solutions:
try {
await client . acceptDeal ({ signer , deal_id });
} catch ( error ) {
switch ( error . code ) {
case 'DEAL_NOT_FOUND' :
console . error ( 'Deal ID does not exist' );
break ;
case 'NOT_PARTY_B' :
console . error ( 'Only Party B can accept this deal' );
break ;
case 'DEAL_ALREADY_ACCEPTED' :
console . error ( 'Deal is already in ACTIVE state' );
break ;
case 'DEAL_ALREADY_CLOSED' :
console . error ( 'Deal has been closed' );
break ;
}
}
Integration Patterns
E-commerce Integration
class OrderService {
async createOrder ( buyerId : string , sellerId : string , productId : string , amount : number ) {
// Create order in your system
const order = await this . db . orders . create ({
buyerId , sellerId , productId , amount ,
status: 'pending'
});
// Create reputation deal
const dealResult = await this . reputation . openDealAdmin ({
signer: this . adminWallet ,
admin_cap_id: this . adminCap ,
party_b: buyerId ,
subject_ref: {
type: 'ECOMMERCE_ORDER' ,
id: order . id
},
amount: amount . toString ()
});
// Link deal to order
await this . db . orders . update ( order . id , {
reputationDealId: dealResult . deal_id
});
return order ;
}
}
class ServiceBooking {
async bookService ( clientId : string , providerId : string , serviceType : string , fee : number ) {
// Create booking
const booking = await this . createBooking ({
clientId , providerId , serviceType , fee
});
// Auto-accept deal for service bookings
const dealResult = await this . reputation . openDealClient ({
signer: clientId ,
client_cap_id: await this . getClientCap ( clientId ),
party_b: providerId ,
subject_ref: {
type: 'SERVICE_BOOKING' ,
id: booking . id
},
amount: fee . toString ()
});
// Auto-accept if provider is online
if ( await this . isProviderOnline ( providerId )) {
await this . reputation . acceptDeal ({
signer: providerId ,
deal_id: dealResult . deal_id
});
}
return booking ;
}
}
Next Steps
Rating System Learn how to create and manage ratings after deal completion.
Reputation Profiles Understand how ratings build into reputation profiles.
API Reference Explore the complete deal management API.
Integration Examples See real-world implementation patterns.