# RFQ Channel

The RFQ channel is where a user will either *<mark style="color:green;">publish/stream</mark>* a RFQ.  The user who is *<mark style="color:green;">publishing</mark>* a RFQ is the requester for a quote.  They are considered the "taker" in the transaction request.  The user who is *<mark style="color:green;">streaming</mark>* for RFQ's is the provider of the quote. They are considered the "maker" of the quote.&#x20;

{% hint style="success" %}
&#x20;It is important to note that the RFQ channel is <mark style="color:red;">not</mark> where RFQ quotes are actually generated or filled. It is only used to broadcast & listen to requests.

\
When an actual quote is generated by the quote provider, it can only be seen on the Quote channel.  So if you intend to *<mark style="color:green;">publish</mark>* on the RFQ Channel, you will need to *<mark style="color:green;">stream</mark>* on the [Quote Channel](https://docs.premia.blue/developer-center/apis/containerized-api/websockets-reference/quotes-channel) to see quotes that are returned to you.\
\
The quote provider who is *<mark style="color:green;">streaming</mark>* on the RFQ Channel will respond to request by [posting](https://docs.premia.blue/developer-center/apis/api-reference/orderbook/quotes#orderbook-quotes-1) the quotes via rest api.&#x20;
{% endhint %}

### <mark style="color:blue;">Responding to RFQ (RFQ Streamers Only)</mark>

If you are a *<mark style="color:green;">streamer</mark>* of RFQ's you will need to produce quote objects and post them via REST API.  When doing so, the quotes must have the `takerAddress` populated with the requesters address.  This is an optional param when posting quotes via REST API.  If it is intentionally omitted when posting a quote, the order is considered PUBLIC and can be filled by anyone. &#x20;

{% tabs %}
{% tab title="Publish RFQ " %}

```javascript
/*
TypeScript Sample Code
NOTE: since this is an API,  WS logic can be written in any language. This example
is in typescript, but the overall sequence will be the same for any language.
*/

import { RawData, WebSocket } from 'ws'

// Example for for local container runtime
const url = `ws://localhost:${process.env.HTTP_PORT}`
const wsConnection = new WebSocket(url)
const MOCK_API_KEY = '3423ee2bfd89491f82b351404'


const authMessage: AuthMessage = {
  type: 'AUTH',
  apiKey: MOCK_API_KEY,
  body: null
}

// send AuthMessage
wsConnection.send(JSON.stringify(authMsg))

// IMPORTANT!!! published RFQ messages must be in web3 format
const rfqRequest = {
  type: 'RFQ',
  body: {
    poolKey: {
      	base: '0x7F5bc2250ea57d8ca932898297b1FF9aE1a04999'
	quote: '0x53421DB1f41368E028A4239954feB5033C7B3729'
	oracleAdapter: string
	strike: parseEther('1700').toString()
	maturity: 1702022400
	isCallPool: boolean
    },
    side: 'ask',
    chainId: '421613', // or '42161' for prod environment
    size: parseEther('1').toString(),
    taker: '0x3D1dcc44D65C08b39029cA8673D705D7e5c4cFF2'
  }
}

const wsCallback = (data: RawData) => {
  const message: InfoMessage | ErrorMessage | RFQMessage | PostQuoteMessage | FillQuoteMessage | DeleteQuoteMessage = JSON.parse(data.toString())
    switch (message.type) {
      case 'INFO': {
        // auth result message will arrive here
        break
      }  
      case 'ERROR': {
        // any error message will arrive here
        break
      }
      default: {
        throw `Unexpected message type ${message.type}`
      }
}

// subscribe to WS messages
wsConnection.on('message', wsCallback)

// publish RFQMessage to start getting quotes streamed on QUOTES channel
wsConnection.send(JSON.stringify(rfqRequest))


// unsubscribe to WS messages
// NOTE: unsubscribing does NOT close the ws connection
const unsubscribeMsg: WSUnsubscribeMessage = {
    type: 'UNSUBSCRIBE',
    channel: channel,
    body: null,
}

wsConnection.send(JSON.stringify(unsubscribeMsg))
```

{% endtab %}

{% tab title="Stream RFQ" %}

```typescript
/*
TypeScript Sample Code
NOTE: since this is an API,  WS logic can be written in any language. This example
is in typescript, but the overall sequence will be the same for any language.
*/

import { RawData, WebSocket } from 'ws'

// Example for for local container runtime
const url = `ws://localhost:${process.env.HTTP_PORT}`
const wsConnection = new WebSocket(url)
const MOCK_API_KEY = '3423ee2bfd89491f82b351404'


const authMessage: AuthMessage = {
  type: 'AUTH',
  apiKey: MOCK_API_KEY,
  body: null
}

// send AuthMessage
wsConnection.send(JSON.stringify(authMsg))


const webSocketFilter: FilterMessage = {
  type: 'FILTER',
  channel: 'RFQ',
  body: {
    chainId: '42161',
    taker: '0x170f9e3eb81ed29491a2efdcfa2edd34fdd24a71' // fake address
  }
}

const wsCallback = (data: RawData) => {
  const message: InfoMessage | ErrorMessage | RFQMessage | PostQuoteMessage | FillQuoteMessage | DeleteQuoteMessage = JSON.parse(data.toString())
    switch (message.type) {
      case 'INFO': {
        // auth result message will arrive here
        break
      }
      case 'RFQ': {
        // streamed requests will arrive here
        // business logic to POST quote via REST API HERE
      }  
      case 'ERROR': {
        // any error message will arrive here
        break
      }
      default: {
        throw `Unexpected message type ${message.type}`
      }
}

// subscribe to WS messages
wsConnection.on('message', wsCallback)

// send FilterMessage to start listening to RFQ stream
wsConnection.send(JSON.stringify(webSocketFilter))
```

{% endtab %}

{% tab title="Interface" %}

```typescript
interface AuthMessage {
  type: 'AUTH'
  apiKey: string
  body: null
}

// INFO message from Premia orderbook
interface InfoMessage {
  type: 'INFO'
  body: null
  message: string
}

// ERROR message from Premia orderbook
interface ErrorMessage {
  type: 'ERROR'
  body: null
  message: string
}

// human-readable format of a RFQ request
interface RFQMessage {
  type: 'RFQ'
  body: {
    base: string // base token name i.e. WETH
    quote: string // base token name i.e. USDC
    expiration: string // i.e. 23NOV2023
    strike: number
    type: 'C' | 'P'
    side: 'bid' | 'ask'
    size: number
    taker: string
  }
}

// Unsubscribe message
interface WSUnsubscribeMessage {
    type: 'UNSUBSCRIBE'
    channel: 'QUOTES' | 'RFQ'
    body: null
}
```

{% endtab %}
{% endtabs %}
