Skip to content

Commit 442fa24

Browse files
pelleclaude
andcommitted
Update TypeScript types, schemas, and documentation for TAIP-17
- Add Escrow and Capture interfaces to TypeScript types - Create JSON schemas for Escrow and Capture messages - Update messages.md with Escrow and Capture documentation - Add TAIP-17 to README.md and CHANGELOG.md - Update agent.json schema to support flexible role values including EscrowAgent - Ensure all components follow existing TAP patterns 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 0f41ee2 commit 442fa24

7 files changed

Lines changed: 427 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ This changelog focuses on:
3838
### Added
3939
- JSON Schema definitions for all TAP message types in `/schemas/` directory
4040
- Developer resources page with implementation guides
41+
- TAIP-17: Composable Escrow workflow (Draft)
42+
- New `Escrow` message type for holding assets on behalf of parties
43+
- New `Capture` message type for releasing escrowed funds
44+
- Supports both cryptocurrency assets and fiat currency denominations
45+
- Enables payment guarantees and asset swap use cases
4146
- TypeScript fixes: Added `by` field to Cancel interface
4247

4348
### Removed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ The purpose of TAIPs is to provide the community with a means to propose enhance
4242
| 14 | [Payment Requests](./TAIPs/taip-14.md) |
4343
| 15 | [Agent Connection Protocol](./TAIPs/taip-15.md) |
4444
| 16 | [Invoices](./TAIPs/taip-16.md) |
45+
| 17 | [Composable Escrow](./TAIPs/taip-17.md) |
4546

4647
## Implementation Resources
4748

messages.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ permalink: /messages/
1212
- [Transaction Message](#transaction-message)
1313
- [Transfer](#transfer)
1414
- [Payment](#payment)
15+
- [Escrow](#escrow)
1516
- [Authorization Flow Messages](#authorization-flow-messages)
1617
- [Authorize](#authorize)
1718
- [Settle](#settle)
1819
- [Reject](#reject)
1920
- [Cancel](#cancel)
2021
- [Revert](#revert)
22+
- [Capture](#capture)
2123
- [Participant Management Messages](#participant-management-messages)
2224
- [UpdateAgent](#updateagent)
2325
- [UpdateParty](#updateparty)
@@ -271,6 +273,104 @@ Initiates a payment request from a merchant to a customer.
271273
}
272274
```
273275

276+
### Escrow
277+
[TAIP-17] - Draft
278+
279+
Requests an agent to hold assets in escrow on behalf of parties, enabling payment guarantees and asset swaps.
280+
281+
| Attribute | Type | Required | Status | Description |
282+
|-----------|------|----------|---------|-------------|
283+
| @context | string | Yes | Draft ([TAIP-17]) | JSON-LD context "https://tap.rsvp/schema/1.0" |
284+
| @type | string | Yes | Draft ([TAIP-17]) | JSON-LD type "https://tap.rsvp/schema/1.0#Escrow" |
285+
| asset | string | No | Draft ([TAIP-17]) | CAIP-19 identifier for the specific cryptocurrency asset. Either asset OR currency must be present |
286+
| currency | string | No | Draft ([TAIP-17]) | ISO 4217 currency code for fiat-denominated escrows. Either asset OR currency must be present |
287+
| amount | string | Yes | Draft ([TAIP-17]) | Amount to be held in escrow (decimal string) |
288+
| originator | [Party](#party) | Yes | Draft ([TAIP-17]) | Party whose assets will be placed in escrow |
289+
| beneficiary | [Party](#party) | Yes | Draft ([TAIP-17]) | Party who will receive the assets when released |
290+
| expiry | string | Yes | Draft ([TAIP-17]) | ISO 8601 timestamp after which the escrow automatically expires |
291+
| agreement | string | No | Draft ([TAIP-17]) | URL or URI referencing the terms and conditions of the escrow |
292+
| agents | array of [Agent](#agent) | Yes | Draft ([TAIP-17]) | Array of agents involved in the escrow. Exactly one agent MUST have role "EscrowAgent" |
293+
294+
#### Examples
295+
296+
##### Payment guarantee escrow
297+
```json
298+
{
299+
"id": "123e4567-e89b-12d3-a456-426614174000",
300+
"type": "https://tap.rsvp/schema/1.0#Escrow",
301+
"from": "did:web:merchant.example",
302+
"to": ["did:web:paymentprocessor.example"],
303+
"created_time": 1719226800,
304+
"expires_time": 1719313200,
305+
"body": {
306+
"@context": "https://tap.rsvp/schema/1.0",
307+
"@type": "https://tap.rsvp/schema/1.0#Escrow",
308+
"asset": "eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
309+
"amount": "100.00",
310+
"originator": {
311+
"@id": "did:eg:customer"
312+
},
313+
"beneficiary": {
314+
"@id": "did:web:merchant.example"
315+
},
316+
"expiry": "2025-06-25T00:00:00Z",
317+
"agreement": "https://merchant.example/order/12345/terms",
318+
"agents": [
319+
{
320+
"@id": "did:web:merchant.example",
321+
"for": "did:web:merchant.example"
322+
},
323+
{
324+
"@id": "did:web:paymentprocessor.example",
325+
"role": "EscrowAgent"
326+
},
327+
{
328+
"@id": "did:web:customer.wallet",
329+
"for": "did:eg:customer"
330+
}
331+
]
332+
}
333+
}
334+
```
335+
336+
##### Fiat currency escrow
337+
```json
338+
{
339+
"id": "789e0123-e89b-12d3-a456-426614174003",
340+
"type": "https://tap.rsvp/schema/1.0#Escrow",
341+
"from": "did:web:marketplace.example",
342+
"to": ["did:web:escrow.bank"],
343+
"body": {
344+
"@context": "https://tap.rsvp/schema/1.0",
345+
"@type": "https://tap.rsvp/schema/1.0#Escrow",
346+
"currency": "USD",
347+
"amount": "500.00",
348+
"originator": {
349+
"@id": "did:eg:buyer"
350+
},
351+
"beneficiary": {
352+
"@id": "did:eg:seller"
353+
},
354+
"expiry": "2025-07-01T00:00:00Z",
355+
"agreement": "https://marketplace.example/purchase/98765",
356+
"agents": [
357+
{
358+
"@id": "did:web:marketplace.example",
359+
"for": "did:eg:seller"
360+
},
361+
{
362+
"@id": "did:web:buyer.bank",
363+
"for": "did:eg:buyer"
364+
},
365+
{
366+
"@id": "did:web:escrow.bank",
367+
"role": "EscrowAgent"
368+
}
369+
]
370+
}
371+
}
372+
```
373+
274374
## Authorization Flow Messages
275375

276376
### Authorize
@@ -446,6 +546,55 @@ Requests a reversal of a settled transaction. This could be part of a dispute re
446546
}
447547
```
448548

549+
### Capture
550+
[TAIP-17] - Draft
551+
552+
Authorizes the release of escrowed funds to the beneficiary. Only agents acting for the beneficiary can send this message.
553+
554+
| Attribute | Type | Required | Status | Description |
555+
|-----------|------|----------|---------|-------------|
556+
| @context | string | Yes | Draft ([TAIP-17]) | JSON-LD context "https://tap.rsvp/schema/1.0" |
557+
| @type | string | Yes | Draft ([TAIP-17]) | JSON-LD type "https://tap.rsvp/schema/1.0#Capture" |
558+
| amount | string | No | Draft ([TAIP-17]) | Amount to capture (decimal string). If omitted, captures full escrow amount. Must be ≤ original amount |
559+
| settlementAddress | string | No | Draft ([TAIP-17]) | Blockchain address for settlement. If omitted, uses address from earlier Authorize |
560+
561+
> **Note:** The message refers to the original Escrow message via the DIDComm `thid` (thread ID) in the message envelope.
562+
563+
#### Examples
564+
565+
##### Full capture
566+
```json
567+
{
568+
"id": "capture-123",
569+
"type": "https://tap.rsvp/schema/1.0#Capture",
570+
"from": "did:web:merchant.example",
571+
"to": ["did:web:paymentprocessor.example"],
572+
"thid": "123e4567-e89b-12d3-a456-426614174000",
573+
"body": {
574+
"@context": "https://tap.rsvp/schema/1.0",
575+
"@type": "https://tap.rsvp/schema/1.0#Capture",
576+
"settlementAddress": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f1234"
577+
}
578+
}
579+
```
580+
581+
##### Partial capture
582+
```json
583+
{
584+
"id": "capture-456",
585+
"type": "https://tap.rsvp/schema/1.0#Capture",
586+
"from": "did:web:merchant.example",
587+
"to": ["did:web:paymentprocessor.example"],
588+
"thid": "123e4567-e89b-12d3-a456-426614174000",
589+
"body": {
590+
"@context": "https://tap.rsvp/schema/1.0",
591+
"@type": "https://tap.rsvp/schema/1.0#Capture",
592+
"amount": "95.00",
593+
"settlementAddress": "eip155:1:0x742d35Cc6634C0532925a3b844Bc9e7595f1234"
594+
}
595+
}
596+
```
597+
449598
## Participant Management Messages
450599

451600
### UpdateAgent

packages/typescript/src/tap.ts

Lines changed: 107 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,110 @@ export interface AuthorizationRequiredMessage
11641164
type: "https://tap.rsvp/schema/1.0#AuthorizationRequired";
11651165
}
11661166

1167+
/**
1168+
* Escrow Message
1169+
* Requests an agent to hold assets in escrow on behalf of parties.
1170+
* Enables payment guarantees, asset swaps, and conditional payments.
1171+
*
1172+
* @see {@link https://github.com/TransactionAuthorizationProtocol/TAIPs/blob/main/TAIPs/taip-17.md | TAIP-17: Composable Escrow}
1173+
*/
1174+
export interface Escrow extends TapMessageObject<"Escrow"> {
1175+
/**
1176+
* Asset to be held in escrow
1177+
* CAIP-19 identifier for blockchain assets
1178+
* Either asset OR currency is required
1179+
*/
1180+
asset?: CAIP19;
1181+
1182+
/**
1183+
* ISO 4217 currency code
1184+
* For fiat-denominated escrows
1185+
* Either asset OR currency is required
1186+
*/
1187+
currency?: IsoCurrency;
1188+
1189+
/**
1190+
* Amount to be held in escrow
1191+
* String representation of the decimal amount
1192+
*/
1193+
amount: Amount;
1194+
1195+
/**
1196+
* Party whose assets will be placed in escrow
1197+
* The party providing the funds
1198+
*/
1199+
originator: Participant<"Party">;
1200+
1201+
/**
1202+
* Party who will receive the assets when released
1203+
* The intended recipient of the escrowed funds
1204+
*/
1205+
beneficiary: Participant<"Party">;
1206+
1207+
/**
1208+
* Expiration timestamp
1209+
* After this time, funds automatically return to originator
1210+
*/
1211+
expiry: ISO8601DateTime;
1212+
1213+
/**
1214+
* Optional agreement reference
1215+
* URL or URI of the escrow terms and conditions
1216+
*/
1217+
agreement?: string;
1218+
1219+
/**
1220+
* List of agents involved in the escrow
1221+
* Exactly one agent MUST have role "EscrowAgent"
1222+
*/
1223+
agents: Participant<"Agent">[];
1224+
}
1225+
1226+
/**
1227+
* Capture Message
1228+
* Authorizes the release of escrowed funds to the beneficiary.
1229+
* Sent by an agent acting for the beneficiary.
1230+
*
1231+
* @see {@link https://github.com/TransactionAuthorizationProtocol/TAIPs/blob/main/TAIPs/taip-17.md | TAIP-17: Composable Escrow}
1232+
*/
1233+
export interface Capture extends TapMessageObject<"Capture"> {
1234+
/**
1235+
* Optional amount to capture
1236+
* If omitted, captures full escrow amount
1237+
* Must be less than or equal to original escrow amount
1238+
*/
1239+
amount?: Amount;
1240+
1241+
/**
1242+
* Optional settlement address
1243+
* Blockchain address for settlement
1244+
* If omitted, uses address from earlier Authorize
1245+
*/
1246+
settlementAddress?: CAIP10;
1247+
}
1248+
1249+
/**
1250+
* Escrow Message Wrapper
1251+
* DIDComm envelope for an Escrow message.
1252+
*
1253+
* @see {@link https://github.com/TransactionAuthorizationProtocol/TAIPs/blob/main/TAIPs/taip-2.md | TAIP-2: Message Format}
1254+
* @see {@link https://github.com/TransactionAuthorizationProtocol/TAIPs/blob/main/TAIPs/taip-17.md | TAIP-17: Composable Escrow}
1255+
*/
1256+
export interface EscrowMessage extends DIDCommMessage<Escrow> {
1257+
type: "https://tap.rsvp/schema/1.0#Escrow";
1258+
}
1259+
1260+
/**
1261+
* Capture Message Wrapper
1262+
* DIDComm envelope for a Capture message.
1263+
*
1264+
* @see {@link https://github.com/TransactionAuthorizationProtocol/TAIPs/blob/main/TAIPs/taip-2.md | TAIP-2: Message Format}
1265+
* @see {@link https://github.com/TransactionAuthorizationProtocol/TAIPs/blob/main/TAIPs/taip-17.md | TAIP-17: Composable Escrow}
1266+
*/
1267+
export interface CaptureMessage extends DIDCommReply<Capture> {
1268+
type: "https://tap.rsvp/schema/1.0#Capture";
1269+
}
1270+
11671271
/**
11681272
* TAP Message
11691273
* Union type of all possible TAP messages.
@@ -1188,6 +1292,8 @@ export type TAPMessage =
11881292
| ConfirmRelationshipMessage
11891293
| UpdatePoliciesMessage
11901294
| ConnectMessage
1191-
| AuthorizationRequiredMessage;
1295+
| AuthorizationRequiredMessage
1296+
| EscrowMessage
1297+
| CaptureMessage;
11921298

11931299
// All types and interfaces are now exported directly in their declarations

schemas/data-structures/agent.json

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,47 @@
44
"title": "Agent",
55
"description": "Represents software acting on behalf of a participant",
66
"type": "object",
7-
"required": ["did", "role"],
7+
"required": ["@id"],
88
"properties": {
9-
"did": {
9+
"@id": {
1010
"$ref": "../common/base-types.json#/$defs/did",
1111
"description": "Decentralized Identifier of the agent"
1212
},
13+
"@type": {
14+
"const": "Agent",
15+
"description": "Type identifier for Agent"
16+
},
1317
"role": {
1418
"type": "string",
15-
"enum": ["originator", "beneficiary", "vasp", "wallet", "mediator", "observer"],
16-
"description": "Role of the agent in the transaction"
19+
"pattern": "^[A-Z][a-zA-Z]*$",
20+
"description": "Role of the agent in the transaction (PascalCase). Standard values include: SettlementAddress, SourceAddress, CustodialService, EscrowAgent"
1721
},
1822
"for": {
19-
"$ref": "../common/base-types.json#/$defs/did",
20-
"description": "DID of the party this agent represents"
23+
"oneOf": [
24+
{
25+
"$ref": "../common/base-types.json#/$defs/did"
26+
},
27+
{
28+
"type": "array",
29+
"items": {
30+
"$ref": "../common/base-types.json#/$defs/did"
31+
},
32+
"minItems": 1
33+
}
34+
],
35+
"description": "DID(s) of the party/parties this agent represents"
36+
},
37+
"name": {
38+
"type": "string",
39+
"description": "Human-readable name of the agent"
40+
},
41+
"nameHash": {
42+
"$ref": "../common/base-types.json#/$defs/base64",
43+
"description": "SHA-256 hash of the normalized agent name"
44+
},
45+
"lei:leiCode": {
46+
"$ref": "../common/base-types.json#/$defs/lei",
47+
"description": "Legal Entity Identifier code"
2148
},
2249
"policies": {
2350
"type": "array",

0 commit comments

Comments
 (0)