Skip to content

Commit

Permalink
Release 2.1.0 (#69)
Browse files Browse the repository at this point in the history
* Add validation for new init options

* Add new init options to interfaces

* Add heartbeat for node ws and new init options

* Enhancement: Linting and Formatting (#55)

* Add linting/formatting plugins and settings

* Fix Prettier config

* Format code

* Update circle CI to use newer version of node

* Feature: Bitcoin Support (#56)

* Add Bitcoin Support

* Formatting

* Don't lowercase btc address

* Add prepare script

* Enhancement: WebSocket Handlers (#59)

* Enhancement: Destroy Method (#60)

* Call onclose manually (#62)

Closes #61

* Add better validation (#64)

Closes #63

* Enhancement: Error Handling (#65)

* All errors go through onerror handler if provided

* Add missing return statements

Closes #66

* Enhancement: Handle Server Errors (#68)

Closes #67

* Change to version 2.1.0
  • Loading branch information
lnbc1QWFyb24 authored May 1, 2020
1 parent 294d12c commit 1c80af2
Show file tree
Hide file tree
Showing 17 changed files with 1,256 additions and 174 deletions.
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2
jobs:
test:
docker:
- image: circleci/node:8.15-browsers
- image: circleci/node:10.18.1-browsers
steps:
- checkout
- restore_cache:
Expand All @@ -18,7 +18,7 @@ jobs:
key: v1-dependencies-{{ checksum "package.json" }}
deploy_stage:
docker:
- image: circleci/node:8.15-browsers
- image: circleci/node:10.18.1-browsers
user: root
steps:
- checkout
Expand All @@ -40,7 +40,7 @@ jobs:
- run: aws s3 sync /root/project/deploy-temp/${VERSION}/ s3://staging.sdk.blocknative.com/${VERSION}/ --content-type "text/javascript" --content-encoding "gzip" --cache-control "max-age=31536000" --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers
deploy_prod:
docker:
- image: circleci/node:8.15-browsers
- image: circleci/node:10.18.1-browsers
user: root
steps:
- checkout
Expand Down
18 changes: 18 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2020,
sourceType: 'module'
},
extends: [
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
'plugin:prettier/recommended'
],

rules: {
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/explicit-function-return-type': 'off'
}
}
8 changes: 0 additions & 8 deletions .prettierrc

This file was deleted.

8 changes: 8 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
semi: false,
trailingComma: 'none',
singleQuote: true,
printWidth: 80,
tabWidth: 2,
arrowParens: 'avoid'
}
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bnc-sdk",
"version": "2.0.1",
"version": "2.1.0",
"description": "SDK to connect to the blocknative backend via a websocket connection",
"keywords": [
"ethereum",
Expand All @@ -22,7 +22,8 @@
"license": "MIT",
"scripts": {
"build": "rimraf dist && rollup -c && babel dist/esm/index.js -o dist/esm/index.js && babel dist/cjs/index.js -o dist/cjs/index.js",
"test": "echo \"TBD\" && exit 0"
"test": "echo \"TBD\" && exit 0",
"prepare": "npm run build"
},
"devDependencies": {
"@babel/cli": "^7.7.0",
Expand All @@ -31,7 +32,13 @@
"@rollup/plugin-commonjs": "^11.0.2",
"@rollup/plugin-json": "^4.0.0",
"@rollup/plugin-node-resolve": "^7.1.1",
"@typescript-eslint/eslint-plugin": "^2.30.0",
"@typescript-eslint/parser": "^2.30.0",
"babel-plugin-external-helpers": "^6.18.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.3",
"prettier": "^2.0.5",
"rimraf": "^3.0.0",
"rollup": "^1.27.5",
"rollup-plugin-typescript2": "0.21.0",
Expand Down
24 changes: 12 additions & 12 deletions rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,43 +10,43 @@ export default [
dir: 'dist/iife/',
format: 'iife',
name: 'bncSdk',
globals: ['SturdyWebSocket', 'crypto-es'],
globals: ['SturdyWebSocket', 'crypto-es']
},
plugins: [
json(),
resolve(),
commonjs(),
typescript({ useTsconfigDeclarationDir: true, clean: true }),
],
typescript({ useTsconfigDeclarationDir: true, clean: true })
]
},
{
input: `src/index.ts`,
output: [
{
format: 'esm',
dir: 'dist/esm/',
},
dir: 'dist/esm/'
}
],
external: ['sturdy-websocket', 'crypto-es'],
plugins: [
json(),
resolve(),
typescript({ useTsconfigDeclarationDir: true, clean: true }),
],
typescript({ useTsconfigDeclarationDir: true, clean: true })
]
},
{
input: `src/index.ts`,
output: [
{
format: 'cjs',
dir: 'dist/cjs/',
},
dir: 'dist/cjs/'
}
],
plugins: [
json(),
resolve(),
commonjs({ include: /node_modules/ }),
typescript({ useTsconfigDeclarationDir: true, clean: true }),
],
},
typescript({ useTsconfigDeclarationDir: true, clean: true })
]
}
]
23 changes: 15 additions & 8 deletions src/account.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
import { createEmitter } from './utilities'
import { Emitter, Ac } from './interfaces'
import { validateAccount } from './validation'

function account(this: any, address: string): { emitter: Emitter; details: { address: string } } {
validateAccount(address)
function account(
this: any,
address: string
): { emitter: Emitter; details: { address: string } } {
if (this._destroyed)
throw new Error(
'The WebSocket instance has been destroyed, re-initialize to continue making requests.'
)

// lowercase the address
address = address.toLowerCase()
// lowercase the address if Ethereum
address = this._system === 'ethereum' ? address.toLowerCase() : address

// create emitter for transaction
const emitter: Emitter = createEmitter()

// create eventCode for transaction
const eventCode: string = 'accountAddress'
const eventCode = 'watch'

const existingAddressWatcher = this._watchedAccounts.find((ac: Ac) => ac.address === address)
const existingAddressWatcher = this._watchedAccounts.find(
(ac: Ac) => ac.address === address
)

if (existingAddressWatcher) {
// add to existing emitters array
Expand All @@ -30,7 +37,7 @@ function account(this: any, address: string): { emitter: Emitter; details: { add
// logEvent to server
this._sendMessage({
eventCode,
categoryCode: 'watch',
categoryCode: 'accountAddress',
account: {
address
}
Expand Down
13 changes: 13 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const networks: { [key: string]: { [key: string]: string } } = {
bitcoin: {
'1': 'main',
'2': 'testnet'
},
ethereum: {
'1': 'main',
'3': 'ropsten',
'4': 'rinkeby',
'5': 'goerli',
'42': 'kovan'
}
}
7 changes: 5 additions & 2 deletions src/event.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { EventObject } from './interfaces'
import { validateEvent } from './validation'

function event(this: any, eventObj: EventObject): void {
validateEvent(eventObj)
if (this._destroyed)
throw new Error(
'The WebSocket instance has been destroyed, re-initialize to continue making requests.'
)

this._sendMessage(eventObj)
}

Expand Down
91 changes: 83 additions & 8 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,52 @@ import {
Transaction,
Account,
Event,
Unsubscribe
Unsubscribe,
Destroy,
SDKError
} from './interfaces'

const DEFAULT_NAME = 'unknown'
const DEFAULT_SYSTEM = 'ethereum'

class Blocknative {
private _storageKey: string
private _connectionId: string | undefined
private _dappId: string
private _system: string
private _networkId: number
private _transactionHandlers: TransactionHandler[]
private _socket: any
private _connected: boolean
private _sendMessage: (msg: EventObject) => void
private _watchedTransactions: Tx[]
private _watchedAccounts: Ac[]
private _pingTimeout?: NodeJS.Timeout
private _heartbeat?: () => void
private _destroyed: boolean
private _onerror: ((error: SDKError) => void) | undefined

public transaction: Transaction
public account: Account
public event: Event
public unsubscribe: Unsubscribe
public destroy: Destroy

constructor(options: InitializationOptions) {
validateOptions(options)
const {
dappId,
system = DEFAULT_SYSTEM,
name = DEFAULT_NAME,
networkId,
transactionHandlers = [],
apiUrl,
ws
ws,
onopen,
ondown,
onreopen,
onerror,
onclose
} = options

const socket = new SturdyWebSocket(
Expand All @@ -60,10 +75,16 @@ class Blocknative {
: {}
)

socket.onopen = onOpen.bind(this)
socket.ondown = onDown.bind(this)
socket.onreopen = onReopen.bind(this)
socket.onopen = onOpen.bind(this, onopen)
socket.ondown = onDown.bind(this, ondown)
socket.onreopen = onReopen.bind(this, onreopen)
socket.onmessage = handleMessage.bind(this)
socket.onerror = (error: any) =>
onerror && onerror({ message: 'There was a WebSocket error', error })
socket.onclose = () => {
this._pingTimeout && clearInterval(this._pingTimeout)
onclose && onclose()
}

const storageKey = CryptoEs.SHA1(`${dappId} - ${name}`).toString()
const storedConnectionId =
Expand All @@ -72,36 +93,77 @@ class Blocknative {
this._storageKey = storageKey
this._connectionId = storedConnectionId || undefined
this._dappId = dappId
this._system = system
this._networkId = networkId
this._transactionHandlers = transactionHandlers
this._socket = socket
this._connected = false
this._sendMessage = sendMessage.bind(this)
this._watchedTransactions = []
this._watchedAccounts = []
this._pingTimeout = undefined
this._destroyed = false
this._onerror = onerror

if (this._socket.ws.on) {
this._heartbeat = () => {
this._pingTimeout && clearTimeout(this._pingTimeout)

this._pingTimeout = setTimeout(() => {
// terminate connection if we haven't heard the server ping after server timeout plus conservative latency delay
// Sturdy Websocket will handle the new connection logic
this._socket.ws.terminate()
}, 30000 + 1000)
}

this._socket.ws.on('ping', () => {
this._heartbeat && this._heartbeat()
})
}

// public API
this.transaction = transaction.bind(this)
this.account = account.bind(this)
this.event = event.bind(this)
this.unsubscribe = unsubscribe.bind(this)
this.destroy = () => {
this._socket.close()
this._destroyed = true

// call onclose manually here as SturdyWebSocket doesn't currently work as expected
// https://github.com/dphilipson/sturdy-websocket/issues/5
this._socket.onclose()
}
}
}

function onOpen(this: any) {
function onOpen(this: any, handler: (() => void) | undefined) {
this._connected = true
this._sendMessage({
categoryCode: 'initialize',
eventCode: 'checkDappId',
connectionId: this._connectionId
})

this._heartbeat && this._heartbeat()
handler && handler()
}

function onDown(this: any) {
function onDown(
this: any,
handler: ((closeEvent: CloseEvent) => void) | undefined,
closeEvent: CloseEvent
) {
this._connected = false

if (handler) {
handler(closeEvent)
}

this._pingTimeout && clearTimeout(this._pingTimeout)
}

function onReopen(this: any) {
function onReopen(this: any, handler: (() => void) | undefined) {
this._connected = true

this._sendMessage({
Expand All @@ -122,6 +184,19 @@ function onReopen(this: any) {
}
})
})

if (handler) {
handler()
}

if (this._socket.ws.on) {
// need to re-register ping event since new connection
this._socket.ws.on('ping', () => {
this._heartbeat && this._heartbeat()
})

this._heartbeat()
}
}

export default Blocknative
Loading

0 comments on commit 1c80af2

Please sign in to comment.