Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wasm, core, react: update to auth v2 #105

Merged
merged 8 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# @renegade-fi/core

## 0.3.7

### Patch Changes

- core: tidy up

## 0.3.6

### Patch Changes

- wasm, core, react: update to api auth v2

## 0.3.5

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@renegade-fi/core",
"description": "VanillaJS library for Renegade",
"version": "0.3.5",
"version": "0.3.7",
"repository": {
"type": "git",
"url": "https://github.com/renegade-fi/typescript-sdk.git",
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import invariant from 'tiny-invariant'
import type { Address } from 'viem'

/// Header name for the HTTP auth signature
export const RENEGADE_AUTH_HEADER_NAME = 'renegade-auth'
/// Header name for the HTTP auth HMAC
export const RENEGADE_AUTH_HMAC_HEADER_NAME = 'renegade-auth-symmetric'
export const RENEGADE_AUTH_HEADER_NAME = 'x-renegade-auth'
/// Header name for the expiration timestamp of a signature
export const RENEGADE_SIG_EXPIRATION_HEADER_NAME = 'renegade-auth-expiration'
export const RENEGADE_SIG_EXPIRATION_HEADER_NAME = 'x-renegade-auth-expiration'
/// The message used to derive the wallet's root key
export const ROOT_KEY_MESSAGE_PREFIX =
'Unlock your Renegade Wallet on chain ID:'
/// The amount of buffer time to add to the signature expiration
export const SIG_EXPIRATION_BUFFER_MS = 10_000 // 10 seconds

////////////////////////////////////////////////////////////////////////////////
// System-Wide Constants
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,12 +278,14 @@ export {

export { deepEqual } from '../utils/deepEqual.js'

export { postRelayerRaw } from '../utils/http.js'
export { postRelayerRaw, addExpiringAuthToHeaders } from '../utils/http.js'

export {
AuthType,
RelayerWebsocket,
type RelayerWebsocketParams,
type SubscriptionBody,
type UnsubscriptionBody,
} from '../utils/websocket.js'

export {
Expand Down
29 changes: 13 additions & 16 deletions packages/core/src/utils.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,6 @@ export function cancel_order(seed: string, wallet_str: string, order_id: string)
*/
export function update_order(seed: string, wallet_str: string, id: string, base_mint: string, quote_mint: string, side: string, amount: string, worst_case_price: string, min_fill_size: string, allow_external_matches: boolean): any;
/**
* Build authentication headers for a request
* @param {string} key
* @param {string} req
* @param {bigint} current_timestamp
* @returns {any[]}
*/
export function build_auth_headers_symmetric(key: string, req: string, current_timestamp: bigint): any[];
/**
* Build admin authentication headers
* @param {string} key
* @param {string} req
* @param {bigint} current_timestamp
* @returns {any[]}
*/
export function build_admin_headers(key: string, req: string, current_timestamp: bigint): any[];
/**
* @param {string} seed
* @param {bigint} nonce
* @returns {any}
Expand Down Expand Up @@ -141,3 +125,16 @@ export function sign_message(sk_root: string, message: string): any;
* @returns {any}
*/
export function bigint_to_limbs(value: string): any;
/**
* @param {string} path
* @param {any} headers
* @param {string} body
* @param {string} key
* @returns {string}
*/
export function create_request_signature(path: string, headers: any, body: string, key: string): string;
/**
* @param {string} b64_key
* @returns {string}
*/
export function b64_to_hex_hmac_key(b64_key: string): string;
119 changes: 79 additions & 40 deletions packages/core/src/utils/http.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import axios from 'axios'
import invariant from 'tiny-invariant'

import { getSymmetricKey } from '../actions/getSymmetricKey.js'
import {
RENEGADE_AUTH_HEADER_NAME,
RENEGADE_AUTH_HMAC_HEADER_NAME,
RENEGADE_SIG_EXPIRATION_HEADER_NAME,
SIG_EXPIRATION_BUFFER_MS,
} from '../constants.js'
import type { Config } from '../createConfig.js'
import { BaseError } from '../errors/base.js'
Expand Down Expand Up @@ -110,19 +109,19 @@ export async function postRelayerWithAuth(
const symmetricKey = getSymmetricKey(config)
invariant(symmetricKey, 'Failed to derive symmetric key')

const [auth, expiration] = config.utils.build_auth_headers_symmetric(
symmetricKey,
body ?? '',
BigInt(Date.now()),
)

const path = getPathFromUrl(url)
const headers = {
[RENEGADE_AUTH_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
'Content-Type': 'application/json',
}

return await postRelayerRaw(url, body, headers)
const headersWithAuth = addExpiringAuthToHeaders(
config,
path,
headers,
body ?? '',
symmetricKey,
SIG_EXPIRATION_BUFFER_MS,
)
return await postRelayerRaw(url, body, headersWithAuth)
}

export async function postRelayerWithAdmin(
Expand All @@ -132,56 +131,96 @@ export async function postRelayerWithAdmin(
) {
const { adminKey } = config
invariant(adminKey, 'Admin key is required')
const symmetricKey = config.utils.b64_to_hex_hmac_key(adminKey)

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

const path = getPathFromUrl(url)
const headers = {
[RENEGADE_AUTH_HMAC_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
'Content-Type': 'application/json',
}

return await postRelayerRaw(url, body, headers)
const headersWithAuth = addExpiringAuthToHeaders(
config,
path,
headers,
body ?? '',
symmetricKey,
SIG_EXPIRATION_BUFFER_MS,
)
return await postRelayerRaw(url, body, headersWithAuth)
}

export async function getRelayerWithAuth(config: Config, url: string) {
const symmetricKey = getSymmetricKey(config)
invariant(symmetricKey, 'Failed to derive symmetric key')

const [auth, expiration] = config.utils.build_auth_headers_symmetric(
symmetricKey,
'',
BigInt(Date.now()),
)

const path = getPathFromUrl(url)
const headers = {
[RENEGADE_AUTH_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
'Content-Type': 'application/json',
}

return await getRelayerRaw(url, headers)
const headersWithAuth = addExpiringAuthToHeaders(
config,
path,
headers,
'',
symmetricKey,
SIG_EXPIRATION_BUFFER_MS,
)
return await getRelayerRaw(url, headersWithAuth)
}

export async function getRelayerWithAdmin(config: Config, url: string) {
const { adminKey } = config
invariant(adminKey, 'Admin key is required')
const symmetricKey = config.utils.b64_to_hex_hmac_key(adminKey)

const [auth, expiration] = config.utils.build_admin_headers(
adminKey,
const path = getPathFromUrl(url)
const headers = {
'Content-Type': 'application/json',
}
const headersWithAuth = addExpiringAuthToHeaders(
config,
path,
headers,
'',
BigInt(Date.now()),
symmetricKey,
SIG_EXPIRATION_BUFFER_MS,
)

const headers = {
[RENEGADE_AUTH_HMAC_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
'Content-Type': 'application/json',
return await getRelayerRaw(url, headersWithAuth)
}

/// Get the path from a URL
function getPathFromUrl(url: string): string {
try {
const parsedUrl = new URL(url)
return parsedUrl.pathname || '/'
} catch {
return url.startsWith('/') ? url : `/${url}`
}
}

/// Add an auth expiration and signature to a set of headers
export function addExpiringAuthToHeaders(
config: Config,
path: string,
headers: Record<string, string>,
body: string,
key: string,
expiration: number,
): Record<string, string> {
// Add a timestamp
const expirationTs = Date.now() + expiration
const headersWithExpiration = {
...headers,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expirationTs.toString(),
}

// Add the signature
const auth = config.utils.create_request_signature(
path,
headersWithExpiration,
body,
key,
)

return await getRelayerRaw(url, headers)
return { ...headersWithExpiration, [RENEGADE_AUTH_HEADER_NAME]: auth }
}
42 changes: 19 additions & 23 deletions packages/core/src/utils/websocket.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { getSymmetricKey } from '../actions/getSymmetricKey.js'
import {
RENEGADE_AUTH_HEADER_NAME,
RENEGADE_AUTH_HMAC_HEADER_NAME,
RENEGADE_SIG_EXPIRATION_HEADER_NAME,
} from '../constants.js'
import { SIG_EXPIRATION_BUFFER_MS } from '../constants.js'
import type { Config } from '../createConfig.js'
import { addExpiringAuthToHeaders } from './http.js'

export enum AuthType {
None = 'None',
Expand All @@ -31,12 +28,12 @@ type UnsubscriptionMessage = {
body: UnsubscriptionBody
}

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

type UnsubscriptionBody = {
export type UnsubscriptionBody = {
method: 'unsubscribe'
topic: string
}
Expand Down Expand Up @@ -153,16 +150,15 @@ export class RelayerWebsocket {
body: SubscriptionBody,
): Record<string, string> {
const symmetricKey = getSymmetricKey(this.config)
const [auth, expiration] = this.config.utils.build_auth_headers_symmetric(
symmetricKey,

return addExpiringAuthToHeaders(
this.config,
body.topic,
{},
JSON.stringify(body),
BigInt(Date.now()),
symmetricKey,
SIG_EXPIRATION_BUFFER_MS,
)

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

private buildAdminAuthHeaders(
Expand All @@ -171,17 +167,17 @@ export class RelayerWebsocket {
if (!this.config.adminKey) {
throw new Error('Admin key is required')
}
const { adminKey } = this.config
const symmetricKey = this.config.utils.b64_to_hex_hmac_key(adminKey)

const [auth, expiration] = this.config.utils.build_admin_headers(
this.config.adminKey,
return addExpiringAuthToHeaders(
this.config,
body.topic,
{},
JSON.stringify(body),
BigInt(Date.now()),
symmetricKey,
SIG_EXPIRATION_BUFFER_MS,
)

return {
[RENEGADE_AUTH_HMAC_HEADER_NAME]: auth,
[RENEGADE_SIG_EXPIRATION_HEADER_NAME]: expiration,
}
}

private cleanup(): void {
Expand Down
16 changes: 16 additions & 0 deletions packages/node/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# @renegade-fi/node

## 0.3.10

### Patch Changes

- core: tidy up
- Updated dependencies
- @renegade-fi/[email protected]

## 0.3.9

### Patch Changes

- wasm, core, react: update to api auth v2
- Updated dependencies
- @renegade-fi/[email protected]

## 0.3.8

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/node/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@renegade-fi/node",
"description": "Node.js library for Renegade",
"version": "0.3.8",
"version": "0.3.10",
"repository": {
"type": "git",
"url": "https://github.com/renegade-fi/typescript-sdk.git",
Expand Down
Loading
Loading