Skip to content
This repository was archived by the owner on Dec 12, 2024. It is now read-only.

Commit 3c04496

Browse files
authored
feat: add order instructions (#52)
1 parent ceaaf1c commit 3c04496

19 files changed

+221
-69
lines changed

lib/src/http_client/tbdex_http_client.dart

-13
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,8 @@
11
import 'dart:convert';
22
import 'package:http/http.dart' as http;
3-
import 'package:tbdex/src/http_client/exceptions/http_exceptions.dart';
4-
import 'package:tbdex/src/http_client/exceptions/token_exceptions.dart';
5-
import 'package:tbdex/src/http_client/exceptions/validation_exceptions.dart';
6-
import 'package:tbdex/src/http_client/models/create_exchange_request.dart';
7-
import 'package:tbdex/src/http_client/models/exchange.dart';
8-
import 'package:tbdex/src/http_client/models/get_offerings_filter.dart';
93
import 'package:tbdex/src/http_client/models/submit_cancel_request.dart';
104
import 'package:tbdex/src/http_client/models/submit_close_request.dart';
115
import 'package:tbdex/src/http_client/models/submit_order_request.dart';
12-
import 'package:tbdex/src/protocol/models/balance.dart';
13-
import 'package:tbdex/src/protocol/models/close.dart';
14-
import 'package:tbdex/src/protocol/models/offering.dart';
15-
import 'package:tbdex/src/protocol/models/order.dart';
16-
import 'package:tbdex/src/protocol/models/rfq.dart';
17-
import 'package:tbdex/src/protocol/parser.dart';
18-
import 'package:tbdex/src/protocol/validator.dart';
196
import 'package:tbdex/tbdex.dart';
207
import 'package:typeid/typeid.dart';
218
import 'package:web5/web5.dart';

lib/src/protocol/jcs.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'dart:convert';
22
import 'dart:typed_data';
33

4-
// TODO: turn into standalone lib
4+
// TODO(ethan-tbd): turn into standalone lib
55

66
/// Implements the JSON Canonicalization Scheme specified in
77
/// [RFC8785](https://www.rfc-editor.org/rfc/rfc8785)

lib/src/protocol/json_schemas/message_schema.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class MessageSchema {
1818
},
1919
"kind": {
2020
"type": "string",
21-
"enum": ["rfq", "quote", "order", "orderstatus", "close", "cancel"],
21+
"enum": ["rfq", "quote", "order", "orderstatus", "close", "cancel", "orderinstructions"],
2222
"description": "The message kind (e.g. rfq, quote)"
2323
},
2424
"id": {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class OrderinstructionsSchema {
2+
static const String json = r'''
3+
{
4+
"$schema": "http://json-schema.org/draft-07/schema#",
5+
"$id": "https://tbdex.dev/orderinstructions.schema.json",
6+
"type": "object",
7+
"additionalProperties": false,
8+
"properties": {
9+
"payin": {
10+
"$ref": "#/definitions/PaymentInstruction"
11+
},
12+
"payout": {
13+
"$ref": "#/definitions/PaymentInstruction"
14+
}
15+
},
16+
"definitions": {
17+
"PaymentInstruction": {
18+
"type": "object",
19+
"additionalProperties": false,
20+
"properties": {
21+
"link": {
22+
"type": "string",
23+
"description": "Link to allow Alice to pay PFI, or be paid by the PFI"
24+
},
25+
"instruction": {
26+
"type": "string",
27+
"description": "Instruction on how Alice can pay PFI, or how Alice can be paid by the PFI"
28+
}
29+
}
30+
}
31+
},
32+
"required": ["payin", "payout"]
33+
}
34+
''';
35+
}

lib/src/protocol/json_schemas/quote_schema.dart

-17
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,9 @@ class QuoteSchema {
2323
"total": {
2424
"$ref": "definitions.json#/definitions/decimalString",
2525
"description": "The total amount of currency to be paid in or paid out. It is always a sum of subtotal and fee"
26-
},
27-
"paymentInstruction": {
28-
"$ref": "#/definitions/PaymentInstruction"
2926
}
3027
},
3128
"required": ["currencyCode", "subtotal", "total"]
32-
},
33-
"PaymentInstruction": {
34-
"type": "object",
35-
"additionalProperties": false,
36-
"properties": {
37-
"link": {
38-
"type": "string",
39-
"description": "Link to allow Alice to pay PFI, or be paid by the PFI"
40-
},
41-
"instruction": {
42-
"type": "string",
43-
"description": "Instruction on how Alice can pay PFI, or how Alice can be paid by the PFI"
44-
}
45-
}
4629
}
4730
},
4831
"type": "object",

lib/src/protocol/models/message.dart

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ enum MessageKind {
1616
cancel,
1717
order,
1818
orderstatus,
19+
orderinstructions,
1920
}
2021

2122
class MessageMetadata extends Metadata {

lib/src/protocol/models/message_data.dart

+22-7
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,12 @@ class QuoteDetails {
209209
final String subtotal;
210210
final String total;
211211
final String? fee;
212-
final PaymentInstruction? paymentInstruction;
213212

214213
QuoteDetails({
215214
required this.currencyCode,
216215
required this.subtotal,
217216
required this.total,
218217
this.fee,
219-
this.paymentInstruction,
220218
});
221219

222220
factory QuoteDetails.fromJson(Map<String, dynamic> json) {
@@ -225,9 +223,6 @@ class QuoteDetails {
225223
subtotal: json['subtotal'],
226224
total: json['total'],
227225
fee: json['fee'],
228-
paymentInstruction: json['paymentInstruction'] != null
229-
? PaymentInstruction.fromJson(json['paymentInstruction'])
230-
: null,
231226
);
232227
}
233228

@@ -237,8 +232,6 @@ class QuoteDetails {
237232
'subtotal': subtotal,
238233
'total': total,
239234
if (fee != null) 'fee': fee,
240-
if (paymentInstruction != null)
241-
'paymentInstruction': paymentInstruction?.toJson(),
242235
};
243236
}
244237
}
@@ -338,3 +331,25 @@ class OrderStatusData extends MessageData {
338331
};
339332
}
340333
}
334+
335+
class OrderInstructionsData extends MessageData {
336+
final PaymentInstruction payin;
337+
final PaymentInstruction payout;
338+
339+
OrderInstructionsData({required this.payin, required this.payout});
340+
341+
factory OrderInstructionsData.fromJson(Map<String, dynamic> json) {
342+
return OrderInstructionsData(
343+
payin: PaymentInstruction.fromJson(json['payin']),
344+
payout: PaymentInstruction.fromJson(json['payout']),
345+
);
346+
}
347+
348+
@override
349+
Map<String, dynamic> toJson() {
350+
return {
351+
'payin': payin.toJson(),
352+
'payout': payout.toJson(),
353+
};
354+
}
355+
}

lib/src/protocol/models/order.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ class Order extends Message {
99
final OrderData data;
1010

1111
@override
12-
Set<MessageKind> get validNext => {MessageKind.orderstatus};
12+
Set<MessageKind> get validNext =>
13+
{MessageKind.orderstatus, MessageKind.close, MessageKind.cancel};
1314

1415
Order._({
1516
required this.metadata,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import 'package:tbdex/src/protocol/models/message.dart';
2+
import 'package:tbdex/src/protocol/models/message_data.dart';
3+
import 'package:tbdex/src/protocol/parser.dart';
4+
5+
class OrderInstructions extends Message {
6+
@override
7+
final MessageMetadata metadata;
8+
@override
9+
final OrderInstructionsData data;
10+
11+
@override
12+
Set<MessageKind> get validNext =>
13+
{MessageKind.orderstatus, MessageKind.close, MessageKind.cancel};
14+
15+
OrderInstructions._({
16+
required this.metadata,
17+
required this.data,
18+
String? signature,
19+
}) : super() {
20+
this.signature = signature;
21+
}
22+
23+
static OrderInstructions create(
24+
String to,
25+
String from,
26+
String exchangeId,
27+
OrderInstructionsData data, {
28+
String? externalId,
29+
String protocol = '1.0',
30+
}) {
31+
final now = DateTime.now().toUtc().toIso8601String();
32+
final metadata = MessageMetadata(
33+
kind: MessageKind.orderinstructions,
34+
to: to,
35+
from: from,
36+
id: Message.generateId(MessageKind.orderinstructions),
37+
exchangeId: exchangeId,
38+
createdAt: now,
39+
protocol: protocol,
40+
externalId: externalId,
41+
);
42+
43+
return OrderInstructions._(
44+
metadata: metadata,
45+
data: data,
46+
);
47+
}
48+
49+
static Future<OrderInstructions> parse(String rawMessage) async {
50+
final orderStatus = Parser.parseMessage(rawMessage) as OrderInstructions;
51+
await orderStatus.verify();
52+
return orderStatus;
53+
}
54+
55+
factory OrderInstructions.fromJson(Map<String, dynamic> json) {
56+
return OrderInstructions._(
57+
metadata: MessageMetadata.fromJson(json['metadata']),
58+
data: OrderInstructionsData.fromJson(json['data']),
59+
signature: json['signature'],
60+
);
61+
}
62+
63+
Map<String, dynamic> toJson() {
64+
return {
65+
'metadata': metadata.toJson(),
66+
'data': data.toJson(),
67+
'signature': signature,
68+
};
69+
}
70+
}

lib/src/protocol/models/order_status.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class OrderStatus extends Message {
1010

1111
@override
1212
Set<MessageKind> get validNext =>
13-
{MessageKind.orderstatus, MessageKind.close};
13+
{MessageKind.orderstatus, MessageKind.close, MessageKind.cancel};
1414

1515
OrderStatus._({
1616
required this.metadata,

lib/src/protocol/models/quote.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ class Quote extends Message {
99
final QuoteData data;
1010

1111
@override
12-
Set<MessageKind> get validNext => {MessageKind.order, MessageKind.close};
12+
Set<MessageKind> get validNext =>
13+
{MessageKind.order, MessageKind.close, MessageKind.cancel};
1314

1415
Quote._({
1516
required this.metadata,

lib/src/protocol/models/rfq.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ class Rfq extends Message {
1414
final RfqPrivateData? privateData;
1515

1616
@override
17-
Set<MessageKind> get validNext => {MessageKind.quote, MessageKind.close};
17+
Set<MessageKind> get validNext =>
18+
{MessageKind.quote, MessageKind.close, MessageKind.cancel};
1819

1920
Rfq._({
2021
required this.metadata,

lib/src/protocol/parser.dart

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:tbdex/src/protocol/models/close.dart';
88
import 'package:tbdex/src/protocol/models/message.dart';
99
import 'package:tbdex/src/protocol/models/offering.dart';
1010
import 'package:tbdex/src/protocol/models/order.dart';
11+
import 'package:tbdex/src/protocol/models/order_instructions.dart';
1112
import 'package:tbdex/src/protocol/models/order_status.dart';
1213
import 'package:tbdex/src/protocol/models/quote.dart';
1314
import 'package:tbdex/src/protocol/models/resource.dart';
@@ -147,6 +148,8 @@ abstract class Parser {
147148
return Order.fromJson(jsonObject);
148149
case MessageKind.orderstatus:
149150
return OrderStatus.fromJson(jsonObject);
151+
case MessageKind.orderinstructions:
152+
return OrderInstructions.fromJson(jsonObject);
150153
}
151154
}
152155

lib/src/protocol/validator.dart

+13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:tbdex/src/protocol/json_schemas/definitions_schema.dart';
99
import 'package:tbdex/src/protocol/json_schemas/message_schema.dart';
1010
import 'package:tbdex/src/protocol/json_schemas/offering_schema.dart';
1111
import 'package:tbdex/src/protocol/json_schemas/order_schema.dart';
12+
import 'package:tbdex/src/protocol/json_schemas/orderinstructions_schema.dart';
1213
import 'package:tbdex/src/protocol/json_schemas/orderstatus_schema.dart';
1314
import 'package:tbdex/src/protocol/json_schemas/quote_schema.dart';
1415
import 'package:tbdex/src/protocol/json_schemas/resource_schema.dart';
@@ -19,6 +20,7 @@ import 'package:tbdex/src/protocol/models/close.dart';
1920
import 'package:tbdex/src/protocol/models/message.dart';
2021
import 'package:tbdex/src/protocol/models/offering.dart';
2122
import 'package:tbdex/src/protocol/models/order.dart';
23+
import 'package:tbdex/src/protocol/models/order_instructions.dart';
2224
import 'package:tbdex/src/protocol/models/order_status.dart';
2325
import 'package:tbdex/src/protocol/models/quote.dart';
2426
import 'package:tbdex/src/protocol/models/resource.dart';
@@ -103,6 +105,13 @@ class Validator {
103105
orderStatus.metadata.kind.name,
104106
);
105107
break;
108+
case MessageKind.orderinstructions:
109+
final orderInstructions = message as OrderInstructions;
110+
_instance._validate(orderInstructions.toJson(), 'message');
111+
_instance._validate(
112+
orderInstructions.data.toJson(),
113+
orderInstructions.metadata.kind.name,
114+
);
106115
}
107116
}
108117

@@ -152,6 +161,10 @@ class Validator {
152161
JsonSchema.create(MessageSchema.json, refProvider: refProvider);
153162
_schemaMap['order'] =
154163
JsonSchema.create(OrderSchema.json, refProvider: refProvider);
164+
_schemaMap['orderinstructions'] = JsonSchema.create(
165+
OrderinstructionsSchema.json,
166+
refProvider: refProvider,
167+
);
155168
_schemaMap['orderstatus'] =
156169
JsonSchema.create(OrderstatusSchema.json, refProvider: refProvider);
157170
_schemaMap['quote'] =

0 commit comments

Comments
 (0)