Skip to content

Commit

Permalink
core: utils: websocket: send unsubscription before closing
Browse files Browse the repository at this point in the history
  • Loading branch information
akirillo committed Oct 18, 2024
1 parent 09989c3 commit d499cea
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 108 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"devDependencies": {
"@biomejs/biome": "1.8.3",
"@biomejs/biome": "^1.9.4",
"@changesets/cli": "^2.27.1",
"@types/node": "^20.12.7",
"happy-dom": "^12.2.1",
Expand All @@ -24,4 +24,4 @@
"typecheck": "pnpm run --r --parallel typecheck"
},
"packageManager": "pnpm@9.1.4+sha512.9df9cf27c91715646c7d675d1c9c8e41f6fce88246f1318c1aa6a1ed1aeb3c4f032fcdf4ba63cc69c4fe6d634279176b5358727d8f2cc1e65b65f43ce2f8bfb0"
}
}
20 changes: 10 additions & 10 deletions packages/core/src/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,16 +252,16 @@ export * from '../types/wallet.js'
export * from '../types/order.js'
export * from '../types/task.js'

export {
type Evaluate,
type ExactPartial,
type Mutable,
type StrictOmit as Omit,
type OneOf,
type RemoveUndefined,
type UnionCompute,
type UnionStrictOmit,
type UnionExactPartial,
export type {
Evaluate,
ExactPartial,
Mutable,
StrictOmit as Omit,
OneOf,
RemoveUndefined,
UnionCompute,
UnionStrictOmit,
UnionExactPartial,
} from '../types/utils.js'

////////////////////////////////////////////////////////////////////////////////
Expand Down
149 changes: 90 additions & 59 deletions packages/core/src/utils/websocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,25 @@ export type RelayerWebsocketParams = {
onerrorCallback?: (this: WebSocket, ev: Event) => any
}

type SubscriptionMessage = {
headers?: Record<string, string>
body: SubscriptionBody
}

type UnsubscriptionMessage = {
body: UnsubscriptionBody
}

type SubscriptionBody = {
method: 'subscribe'
topic: string
}

type UnsubscriptionBody = {
method: 'unsubscribe'
topic: string
}

export class RelayerWebsocket {
private config: Config
private topic: string
Expand All @@ -43,6 +62,10 @@ export class RelayerWebsocket {
this.onerrorCallback = params.onerrorCallback ?? null
}

// --------------
// | Public API |
// --------------

public connect(): void {
if (this.ws) {
throw new Error(
Expand All @@ -54,11 +77,7 @@ export class RelayerWebsocket {
instance.ws = new WebSocket(this.config.getWebsocketBaseUrl())

instance.ws.onopen = function (this: WebSocket, event: Event) {
const message = buildSubscriptionMessage(
instance.config,
instance.topic,
instance.authType,
)
const message = instance.buildSubscriptionMessage()
this.send(JSON.stringify(message))

return instance.onopenCallback?.call(this, event)
Expand All @@ -82,78 +101,90 @@ export class RelayerWebsocket {
throw new Error('WebSocket connection not open')
}

const message = this.buildUnsubscriptionMessage()
this.ws.send(JSON.stringify(message))

this.ws.close()
}

private cleanup(): void {
this.ws = null
}
}
// ---------------
// | Private API |
// ---------------

// -----------
// | Helpers |
// -----------

function buildSubscriptionMessage(
config: Config,
topic: string,
authType: AuthType,
) {
const body = {
method: 'subscribe',
topic,
}
private buildSubscriptionMessage(): SubscriptionMessage {
const body = {
method: 'subscribe' as const,
topic: this.topic,
}

if (this.authType === AuthType.None) {
return { body }
}

if (this.authType === AuthType.Wallet) {
const headers = this.buildWalletAuthHeaders(body)
return {
headers,
body,
}
}

if (authType === AuthType.None) {
return body
if (this.authType === AuthType.Admin) {
const headers = this.buildAdminAuthHeaders(body)
return {
headers,
body,
}
}

throw new Error(`Unsupported auth type: ${this.authType}`)
}

if (authType === AuthType.Wallet) {
const headers = buildWalletAuthHeaders(config, body)
private buildUnsubscriptionMessage(): UnsubscriptionMessage {
return {
headers,
body,
body: {
method: 'unsubscribe' as const,
topic: this.topic,
},
}
}

if (authType === AuthType.Admin) {
const headers = buildAdminAuthHeaders(config, body)
private buildWalletAuthHeaders(
body: SubscriptionBody,
): Record<string, string> {
const symmetricKey = getSymmetricKey(this.config)
const [auth, expiration] = this.config.utils.build_auth_headers_symmetric(
symmetricKey,
JSON.stringify(body),
BigInt(Date.now()),
)

return {
headers,
body,
[RENEGADE_AUTH_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
}
}

throw new Error(`Unsupported auth type: ${authType}`)
}
private buildAdminAuthHeaders(
body: SubscriptionBody,
): Record<string, string> {
if (!this.config.adminKey) {
throw new Error('Admin key is required')
}

function buildWalletAuthHeaders(config: Config, body: any) {
const symmetricKey = getSymmetricKey(config)
const [auth, expiration] = config.utils.build_auth_headers_symmetric(
symmetricKey,
JSON.stringify(body),
BigInt(Date.now()),
)

return {
[RENEGADE_AUTH_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
}
}
const [auth, expiration] = this.config.utils.build_admin_headers(
this.config.adminKey,
JSON.stringify(body),
BigInt(Date.now()),
)

function buildAdminAuthHeaders(config: Config, body: any) {
if (!config.adminKey) {
throw new Error('Admin key is required')
return {
[RENEGADE_AUTH_HMAC_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
}
}

const [auth, expiration] = config.utils.build_admin_headers(
config.adminKey,
JSON.stringify(body),
BigInt(Date.now()),
)

return {
[RENEGADE_AUTH_HMAC_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
private cleanup(): void {
this.ws = null
}
}
74 changes: 37 additions & 37 deletions pnpm-lock.yaml

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

0 comments on commit d499cea

Please sign in to comment.