JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 92
  • Score
    100M100P100Q106227F
  • License MIT

A NodeJS Connector for the Brine API

Package Exports

  • @brine-fi/brine-connector
  • @brine-fi/brine-connector/dist/index.js
  • @brine-fi/brine-connector/dist/index.mjs

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@brine-fi/brine-connector) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Brine Connector NodeJS

The official NodeJS connector for Brine's API πŸš€

npm version Build status npm bundle size

Features

  • Complete endpoints including REST and WebSockets
  • Methods return parsed JSON.
  • High level abstraction for ease of use.
  • Easy authentication
  • Automatically sets JWT token internally
  • Calls refresh endpoint when token expires.
  • Typescript Types✨

Brine Connector includes utility/connector functions which can be used to interact with the Brine API. It uses axios internally to handle all requests. It includes interceptors for setting JWT and handling re-login on token expiry.

Installation

First, go to Brine's Website and create an account with your wallet.

Install from npm

npm i @brine-fi/brine-connector

Getting Started

The default base url for mainnet is https://api.brine.fi and testnet is https://api-testnet.brine.fi. You can choose between mainnet and testnet by providing it through the constructor. The default is mainnet. All REST apis, WebSockets are handled by Client, WsClient classes respectively. All operations must be handled in a try-catch block.

Workflow

Check out the example files to see an example workflow.

To use library inside example files

npm run start
npm run start:ws

Rest Client

Import the REST Client

import { Client } from '@brine-fi/brine-connector'

Create a new instance.
Choose between mainnet or testnet

const client = new Client()
// or
const client = new Client('testnet') // default mainnet

General Endpoints

Utils

Get available markets on Mainnet and Testnet

import { MAINNET, TESTNET } from '@brine-fi/brine-connector'

Test connectivity

GET /sapi/v1/health/

client.testConnection()

24hr Price

GET /sapi/v1/market/tickers/

client.get24hPrice({market: MAINNET.markets.ethusdc})

Kline/Candlestick Data

GET /sapi/v1/market/kline/

client.getCandlestick({
   market: MAINNET.markets.ethusdc,
   period: 120,
})

Order Book

GET /sapi/v1/market/orderbook/

client.getOrderBook({
     market: MAINNET.markets.ethusdc,
})

Recent trades

GET /sapi/v1/market/trades/

client.getRecentTrades({
    market: MAINNET.markets.ethusdc,
})

Login

Both login and completeLogin sets JWT as Authorization Token. Optionally, setAccessToken and setRefreshToken can be used to set tokens directly.

getNonce: POST /sapi/v1/auth/nonce/
login: POST /sapi/v1/auth/login/

import { signMsg } from '@brine-fi/brine-connector'

const nonce = await client.getNonce(ethAddress)
const signedMsg = signMsg(nonce.payload, ethPrivateKey)
const loginRes = await client.login(ethAddress, signedMsg.signature)

// or

const loginRes = await client.completeLogin(ethAddress, ethPrivateKey) //calls above functions internally

// or

client.setAccessToken(access) // same as client.setToken()
client.setRefreshToken(refresh)
// these functions are called internally when you use login or completeLogin

Refresh Token

POST /sapi/v1/auth/token/refresh/

If refresh token is set (manually or by using login functions), the refresh endpoint is called automatically when access token expires. Optionally, you can call refreshTokens manually by passing in refreshToken (passing it is optional, it'll work if has been set before).

const res = await client.refreshTokens(refreshToken)

Logout

Sets tokens to null

client.logOut()

Profile Information (Private πŸ”’)

GET /sapi/v1/user/profile/

client.getProfileInfo()

Balance details (Private πŸ”’)

GET /sapi/v1/user/balance/

client.getBalance()

Profit and Loss Details (Private πŸ”’)

GET /sapi/v1/user/pnl/

client.getProfitAndLoss()

Create order (Private πŸ”’)

Create Nonce Body

const nonceBody: CreateOrderNonceBody = {
    market: MAINNET.markets.ethusdc,
    ord_type: 'market',
    price: 29580.51,
    side: 'buy',
    volume: 0.0001,
}

Create Order

createOrderNonce: POST /sapi/v1/orders/nonce/
createNewOrder: POST /sapi/v1/orders/create/

const order = await client.createCompleteOrder(nonceBody, ethPrivateKey) 
//calls below functions internally, we recommend using createCompleteOrder for ease of use

// or
import { signMsgHash } from '@brine-fi/brine-connector'

const orderNonce = await client.createOrderNonce(nonceBody)
const signedBody = signMsgHash(orderNonce.payload, ethPrivateKey)
const order = await client.createNewOrder(signedBody)


// or
import {
  createUserSignature,
  getKeyPairFromSignature,
  signOrderWithStarkKeys,
} from '@brine-fi/brine-connector'

const orderNonce = await client.createOrderNonce(nonceBody)
const userSignature = createUserSignature(ethPrivateKey, 'testnet') // or sign it yourself; default mainnet
const keyPair = getKeyPairFromSignature(userSignature.signature)
const signedBody = signOrderWithStarkKeys(keyPair, orderNonce.payload)
const order = await client.createNewOrder(signedBody)

Get Order (Private πŸ”’)

GET /sapi/v1/orders/{order_id}/

client.getOrder(orderId)

List orders (Private πŸ”’)

GET /sapi/v1/orders/

client.listOrders()

Cancel Order (Private πŸ”’)

POST /sapi/v1/orders/cancel/

client.cancelOrder(order_id)

List Trades (Private πŸ”’)

GET /sapi/v1/trades/

client.listTrades()

WebSocket Client

Import the WebSocket Client

import { WsClient } from '@brine-fi/brine-connector'

Create a new instance

const wsClient = new WsClient('public')
// or
const wsClient = new WsClient('public', 'testnet') // default is 'mainnet'
// or
const loginRes = await client.completeLogin(ethAddress, ethPrivateKey)
const wsClient = new WsClient('private', 'testnet', loginRes.token.access)
// pass in jwt as 3rd argument for private connections

Connect

wsClient.connect()

Subscribe

const streams = [
  'btcusdc.trades',
  'btcusdc.ob-inc',
  'btcusdc.kline-5m',
]
wsClient.subscribe(streams)

// or fpr private

wsClient.subscribe(['trade', 'order'])

Unsubscribe

const streams = [
  'btcusdc.trades',
  'btcusdc.ob-inc',
  'btcusdc.kline-5m',
]
wsClient.unsubscribe(streams)

// or fpr private

wsClient.unsubscribe(['trade', 'order'])

Disconnect

wsClient.disconnect()

Usage

WsClient includes a member called ws which is initialized with the NodeJS WebSocket library (ws). You may use it to handle WebSocket operations.

wsClient.ws.on('message', (data) => {
    console.log(data.toString())
})

Error Handling

Errors thrown are of types AuthenticationError | AxiosError.

Example

import { isAuthenticationError } from '@brine-fi/brine-connector'
try{
  // async operations
} catch (e) {
  if (isAuthenticationError(e)) {
    console.log(e)
  } else {
    console.log((e as AxiosError<Response<string>>))
  }
}

Create L2 Key Pair

You can create your own stark key pairs using the utility functions below

import { generateKeyPairFromEthPrivateKey } from '@brine-fi/brine-connector'

const keypair = generateKeyPairFromEthPrivateKey(ethPrivateKey, 'testnet'); // default is mainnet

const stark_public_key = keypair.getPublic().getX().toString('hex')
const stark_private_key = keypair.getPrivate().toString('hex')