Skip to content

Commit

Permalink
Close message type (#110)
Browse files Browse the repository at this point in the history
* add @KendallWeihe to `CODEOWNERS`
  • Loading branch information
mistermoe authored Jul 5, 2023
1 parent 123c185 commit e5caa2a
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 142 deletions.
2 changes: 1 addition & 1 deletion CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# The format is described: https://github.blog/2017-07-06-introducing-code-owners/

# These owners will be the default owners for everything in the repo.
* @michaelneale @mistermoe @jiyoontbd @phoebe-lew
* @michaelneale @mistermoe @jiyoontbd @phoebe-lew @KendallWeihe


# -----------------------------------------------
Expand Down
73 changes: 49 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
# tbDEX Protocol

## Introduction
# tbDEX Protocol <!-- omit in toc -->

- [Introduction](#introduction)
- [tbDEX Types](#tbdex-types)
- [Resources](#resources)
- [Messages](#messages)
- [Resource Types](#resource-types)
- [`Offering`](#offering)
- [Note on `baseCurrency` and `quoteCurrency`](#note-on-basecurrency-and-quotecurrency)
- [`Offering.PaymentMethod`](#offeringpaymentmethod)
- [Message Structure](#message-structure)
- [ID for each message types](#id-for-each-message-types)
- [Message Types](#message-types)
- [`RFQ (Request For Quote)`](#rfq-request-for-quote)
- [`RFQ.PaymentMethodResponse`](#rfqpaymentmethodresponse)
- [`Close`](#close)
- [`Quote`](#quote)
- [`Quote.PaymentInstructions`](#quotepaymentinstructions)
- [`Quote.PaymentInstructions.PaymentInstruction`](#quotepaymentinstructionspaymentinstruction)
- [`QuoteResponse.QuoteError`](#quoteresponsequoteerror)
- [`OrderStatus`](#orderstatus)
- [Fields that may change in future versions of the schema](#fields-that-may-change-in-future-versions-of-the-schema)
- [tbDEX conversation sequence](#tbdex-conversation-sequence)
- [Resources](#resources-1)


# Introduction

The central aim of this repo is to act as a playground that is set up for us to easily test the ideas we come up with as we iterate our way to what we hope is a robust protocol. Specifically, this repo is focused on fleshing out:
- tbDEX message schemas
Expand Down Expand Up @@ -106,13 +130,13 @@ The `body` of each message can be any of the following message types.
## `RFQ (Request For Quote)`
> Alice -> PFI: "OK, that offering looks good. Give me a Quote against that Offering, and here is how much USD I want to trade for BTC. Here is my proof of KYC, the payment method I intend to pay you USD with, and the payment method I expect you to pay me BTC in."
| field | data type | required | description |
| --------------- | --------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| `offeringId` | string | Y | Offering which Alice would like to get a quote for |
| `amount` | string | Y | Amount of quote currency you want to spend in order to receive base currency |
| `kycProof` | string | Y | VerifiablePresentation in JWT string format that meets the specification per PresentationDefinition in the Offering |
| `payinMethod` | PaymentMethodResponse | Y | Specify which payment method to send quote currency. |
| `payoutMethod` | PaymentMethodResponse | Y | Specify which payment method to receive base currency. |
| field | data type | required | description |
| -------------- | --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------- |
| `offeringId` | string | Y | Offering which Alice would like to get a quote for |
| `amount` | string | Y | Amount of quote currency you want to spend in order to receive base currency |
| `kycProof` | string | Y | VerifiablePresentation in JWT string format that meets the specification per PresentationDefinition in the Offering |
| `payinMethod` | PaymentMethodResponse | Y | Specify which payment method to send quote currency. |
| `payoutMethod` | PaymentMethodResponse | Y | Specify which payment method to receive base currency. |

### `RFQ.PaymentMethodResponse`
| field | data type | required | description |
Expand All @@ -136,33 +160,34 @@ The `body` of each message can be any of the following message types.
}
```

## `QuoteResponse`
> PFI -> Alice: "OK, here's your Quote that describes how much BTC you will receive based on your RFQ. Here's the total fee in USD associated with the payment methods you selected. Here's how to pay us, and how to let us pay you, when you're ready to execute the Quote. This quote expires at X time."
## `Close`
> Alice -> PFI: "Not interested anymore." or "oops sent by accident"
_Alternatively, in the case of an error_
> PFI -> Alice: "Can't fulfill what you sent me for whatever reason (e.g. RFQ is erroneous, don't have enough liquidity etc.)"
> PFI -> Alice: "Whoops, I wasn't able to generate a quote. Here's an error message explaining why."
a `Close` can be sent by Alice _or_ the PFI as a reply to an RFQ or a Quote

| field | data type | required | description |
| -------- | ------------------ | -------- | --------------------------------------------------------- |
| `quote` | Quote | N | Quote, if the RFQ was successful |
| `error` | QuoteError | N | Error, if the RFQ was not successful |
| Field | Data Type | Required | Description |
| -------- | --------- | -------- | ------------------------------------------------ |
| `reason` | string | N | an explanation of why the thread is being closed |

## `Quote`
> PFI -> Alice: "OK, here's your Quote that describes how much BTC you will receive based on your RFQ. Here's the total fee in USD associated with the payment methods you selected. Here's how to pay us, and how to let us pay you, when you're ready to execute the Quote. This quote expires at X time."
### `QuoteResponse.Quote`
| field | data type | required | description |
| --------------------- | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `expiryTime` | datetime | Y | When this quote expires. Expressed as ISO8601 |
| `totalFee` | string | Y | Total fee (base + PaymentMethod specific) included in quote in quote currency. |
| `amount` | string | Y | Amount of base currency that the PFI is willing to sell in exchange for quote currency `amount` in the original RFQ |
| `paymentInstructions` | PaymentInstructions | N | Object that describes how to pay the PFI, and how to get paid by the PFI, in the instances where payment is performed "out-of-band" (e.g. PFI cannot be both a merchant and a payment processor simultaneously) |

#### `QuoteResponse.Quote.PaymentInstructions`
### `Quote.PaymentInstructions`
| field | data type | required | description |
| -------- | ------------------ | -------- | --------------------------------------------------------- |
| `payin` | PaymentInstruction | N | Link or Instruction describing how to pay the PFI. |
| `payout` | PaymentInstruction | N | Link or Instruction describing how to get paid by the PFI |

#### `Quote.PaymentInstructions.PaymentInstruction`
### `Quote.PaymentInstructions.PaymentInstruction`
| field | data type | required | description |
| ------------- | --------- | -------- | ------------------------------------------------------------------------- |
| `link` | String | N | Link to allow Alice to pay PFI, or be paid by the PFI |
Expand All @@ -183,9 +208,9 @@ _Alternatively, in the case of an error_
```

### `QuoteResponse.QuoteError`
| field | data type | required | description |
| --------------------- | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `details` | string | Y | Message describing the error |
| field | data type | required | description |
| --------- | --------- | -------- | ---------------------------- |
| `details` | string | Y | Message describing the error |

```json
{
Expand Down
2 changes: 2 additions & 0 deletions js/build/compile-validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import tbdexMessage from '../../json-schemas/message.schema.json' assert { type:
import offering from '../../json-schemas/offering.schema.json' assert { type: 'json' }
import rfq from '../../json-schemas/rfq.schema.json' assert { type: 'json' }
import quote from '../../json-schemas/quote.schema.json' assert { type: 'json' }
import close from '../../json-schemas/close.schema.json' assert { type: 'json' }
import order from '../../json-schemas/order.schema.json' assert { type: 'json' }
import orderStatus from '../../json-schemas/order-status.schema.json' assert { type: 'json' }

Expand All @@ -30,6 +31,7 @@ const schemas = {
tbdexMessage,
offering,
rfq,
close,
quote,
order,
orderStatus
Expand Down
4 changes: 2 additions & 2 deletions js/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 46 additions & 11 deletions js/src/protocol-definitions.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
const CloseRules = {
$actions: [
{
who : 'recipient',
of : 'RFQ',
can : 'write'
},
{
who : 'author',
of : 'RFQ',
can : 'write'
},
],
}

export const aliceProtocolDefinition = {
protocol : 'https://tbd.website/protocols/tbdex',
types : {
Expand All @@ -7,8 +22,14 @@ export const aliceProtocolDefinition = {
'application/json'
]
},
QuoteResponse: {
schema : 'https://tbd.website/protocols/tbdex/QuoteResponse',
Quote: {
schema : 'https://tbd.website/protocols/tbdex/Quote',
dataFormats : [
'application/json'
]
},
Close: {
schema : 'https://tbd.website/protocols/tbdex/Close',
dataFormats : [
'application/json'
]
Expand All @@ -23,26 +44,30 @@ export const aliceProtocolDefinition = {
structure: {
// alice sends RFQs, not receives them
RFQ: {
// whoever received the RFQ that Alice sent, can write back a QuoteResponse to Alice
QuoteResponse: {
// whoever received the RFQ that Alice sent, can write back a Quote to Alice
Quote: {
$actions: [
{
who : 'recipient',
of : 'RFQ',
can : 'write'
}
],
// Alice _or_ the PFI can Close/End the thread here.
Close: CloseRules,
// OrderStatus can be written to Alice's DWN by someone who wrote RFQ/QuoteResponse (i.e. PFI)
OrderStatus: {
$actions: [
{
who : 'author',
of : 'RFQ/QuoteResponse',
of : 'RFQ/Quote',
can : 'write'
}
]
}
}
},
// Alice _or_ the PFI can Close/End the thread here.
Close: CloseRules
}
}
}
Expand All @@ -57,8 +82,14 @@ export const pfiProtocolDefinition = {
'application/json'
]
},
QuoteResponse: {
schema : 'https://tbd.website/protocols/tbdex/QuoteResponse',
Quote: {
schema : 'https://tbd.website/protocols/tbdex/Quote',
dataFormats : [
'application/json'
]
},
Close: {
schema : 'https://tbd.website/protocols/tbdex/Close',
dataFormats : [
'application/json'
]
Expand All @@ -80,11 +111,15 @@ export const pfiProtocolDefinition = {
can : 'write'
}
],
// Alice _or_ the PFI can Close/End the thread here.
Close: CloseRules,
// PFI is sending OUT quote responses. no one should be writing QuoteResponse to PFIs.
QuoteResponse: {
Quote: {
// PFI is sending OUT OrderStatus. no one should be writing OrderStatus to PFIs.
OrderStatus: { }
OrderStatus: { },
// Alice _or_ the PFI can Close/End the thread here.
Close: CloseRules
}
}
}
}
}
24 changes: 9 additions & 15 deletions js/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export type MessageType<M extends keyof MessageTypes> = MessageTypes[M]

export type MessageTypes = {
rfq: Rfq
quoteResponse: QuoteResponse
quote: Quote
close: Close
orderStatus: OrderStatus
}

Expand All @@ -52,7 +53,7 @@ export type TbDEXMessage<T extends keyof MessageTypes> = MessageMetadata & {
}

export interface Rfq {
offeringId: string,
offeringId: string
amount: string
kycProof: string
payinMethod: PaymentMethodResponse
Expand All @@ -64,22 +65,15 @@ export interface PaymentMethodResponse {
paymentVerifiablePresentationJwt?: string
}

export type QuoteResponse = XOR<Quote, QuoteError>

export interface Quote {
quote: {
expiryTime: string
totalFee: string
amount: string
paymentInstructions?: PaymentInstructions
}
expiryTime: string
totalFee: string
amount: string
paymentInstructions?: PaymentInstructions
}

export interface QuoteError {
error: {
// add some sort of error enum too? i.e MALFORMED_RFQ, CIRCLE_ERROR, SQUARE_ERROR
details: string
}
export interface Close {
reason?: string
}

export interface PaymentInstructions {
Expand Down
Loading

0 comments on commit e5caa2a

Please sign in to comment.