Notify.js

Client library for a full notification UI experience

Live Demo

Checkout our live demo using React at https://reactdemo.blocknative.com/

The demo is open source so you can see a sample implementation of Notify (and Onboard): https://github.com/blocknative/onboard-notify-react

Sample Notifications

To see the notify.js library in action, checkout the code sandboxes at the end of this documentation or the open source demo site at https://reactdemo.blocknative.com/.

Notify.js uses Notify API, which has rate limits. Please see Rate Limits for more details.

Quickstart

It should take less than 5 minutes to get going with Blocknative Notify.

Create a Blocknative Account

Go to the Account Dashboard at https://account.blocknative.com/ and setup an account with an email address. You will receive an email to confirm your account.

Create your API Key

On the Account Dashboard, create an API key with your choice of name using the API Keys link (https://account.blocknative.com/api-keys). API keys segment analytics data. Consider using different API keys for development, staging, and production releases.

API key creation in Account Dashboard

Install the widget using npm

npm install bnc-notify

Initialize the Library

Use the minimum required config. There are more options available in our documentation.

import Notify from "bnc-notify"
var notify = Notify({
dappId: apiKey, // [String] The API key created by step one above
networkId: networkId // [Integer] The Ethereum network ID your Dapp uses.
});

Track transactions

Send a transaction using web3.js and get the transaction hash while its processing. Let notify know the hash and it will track its progress through the mempool and into a block.

// get current account
const accounts = await web3.eth.getAccounts();
const address = accounts[0];
// send the transaction using web3.js and get the hash
web3.eth.sendTransaction({
from: address,
to: "0x792ec62e6840bFcCEa00c669521F678CE1236705",
value: "1000000"})
.on('transactionHash', function(hash){
// pass the hash to notify to track it
notify.hash(hash)
};

And you are live!

Sample Notifications

Example Code

For an example of a basic React demo integration of both Notify.js and Onboard.js, checkout the GitHub repo: https://github.com/blocknative/onboard-notify-react

and the live demo:

https://reactdemo.blocknative.com/

Screencasts

See the above Quickstart guide in a screencast:

Notify.js Quickstart Screencast

See how to add and customize advanced notifications to your Dapp:

Add and Customize Advanced Notifications

Initialization

import Notify from "bnc-notify"
const options = {
dappId: String,
system: String
networkId: Number,
darkMode: Boolean, // (default: false)
mobilePosition: String, // 'top', 'bottom' (default: 'top')
desktopPosition: String, // 'bottomLeft', 'bottomRight', 'topLeft', 'topRight' (default: 'bottomRight')
txApproveReminderTimeout: Number, // (default: 20000)
txStallPendingTimeout: Number, // (default: 20000)
txStallConfirmedTimeout: Number // (default: 90000)
transactionHandler: Function,
clientLocale: String, // (default: 'en')
notifyMessages: Object
}
const notify = Notify(options)

dappId [required] (optional if in UI only mode)

Your unique api key that identifies your application. You can generate a dappId by visiting the Blocknative account page and create a free account.

system [default = 'ethereum']

The blockchain system that you would like to track transactions on. Currently supported systems are 'bitcoin' and 'ethereum'.

networkId [required] (optional if in UI only mode)

The network id that your application runs on. The following values are valid:

Ethereum

  • 1 Main Network

  • 3 Ropsten Test Network

  • 4 Rinkeby Test Network

  • 5 Goerli Test Network

  • 42 Kovan Test Network

  • 100 xDai POA Network

Bitcoin

  • 1 Main Network

  • 2 Testnet Network

darkMode

Boolean value sets notification rendering to use light text on dark background. Default is false.

mobilePosition

String value sets where notifications appear on mobile devices. Value must be either top or bottom. Default is top.

desktopPosition

String value sets where notifications appear on desktop devices. Value must be bottomLeft, bottomRight, topLeft, or topRight. Default is bottomRight.

txApproveReminderTimeout

Number value sets time to wait until approval reminder notification is presented. This notifications reminds user to confirm/approve a transaction for processing by the wallet. Default is 20000 milliseconds (20 seconds).

tsStallPendingTimeout

Number value sets time to wait until stall notification is presented if transaction is not detected in the txPool. Default is 20000 milliseconds (20 seconds).

tsStallConfirmedTimeout

Number value sets time to wait until stall notification is presented if transaction is not confirmed in a block. Default is 90000 milliseconds (90 seconds).

transactionHandler

The function defined for the transactionHandler parameter will be called once for every status update for every transaction that is associated with a watched address or a watched transaction. This is useful as a global handler for all transactions and status updates. The callback is called with the following object:

{
emitterResult: Any, // The value that was returned from the emitter for this transaction
transaction: TransactionObject // See below for details
}

See the Transaction Object section for more info on what is included in the transaction parameter.

clientLocale

Sets the locale for internationalization within notify. Defaults to English ('en'). See the i18n section for more details.

notifyMessages

An object that defines all of the transaction messages. Can be used to customize the default messages, and can also be used to add multiple language support for transaction notifications. See the i18n section for more details.

Notifications

hash

To get notifications for every status that occurs after sending a transaction ("post-flight"), use the hash function:

// Ethereum
// send the transaction using web3.js and get the hash
web3.eth.sendTransaction(txOptions).on("transactionHash", hash => {
// pash the hash in to notify.hash
const { emitter } = notify.hash(hash)
})
// Bitcoin
const { emitter } = notify.hash(txid)

Check out the Emitter Section for details on the emitter object

account

You can register an address with Notify to display notifications for all incoming and outgoing transactions that occur on that account by using the account function:

// Etherum
const accounts = await provider.enable()
// register address for all transactions that occur on the user's account
const { emitter } = notify.account(accounts[0])
// Bitcoin
const { emitter } = notify.account(address)

Check out the Emitter Section for details on the emitter object

transaction

To get notifications for every status that occurs for the full transaction lifecycle ("pre-flight" and "post-flight"), use the transaction function:

The transaction function only applies to Ethereum transactions

const { emitter, result } = notify.transaction({
estimateGas: Function,
gasPrice: Function,
balance: String,
txDetails: {
to: String,
value: Number || String
},
sendTransaction: Function,
contractCall: {
methodName: String,
params: Array
}
})

result is a promise that resolves with the id of the transaction or rejects with an error if there was an error initiating the transaction. The id is useful for when you would like to initiate the transaction yourself and didn't pass a sendTransaction function in to transaction. You can then send the transaction yourself, receive the hash, and then call notify.hash(hash, id). By passing in the id to hash you enable notify to link the preflight notifications to the post send transaction notifications, ensuring a consistent UX.

The transaction function takes an object as the argument which allows you to progressively opt in to which checks and corresponding notifications that you would like during the "pre-flight" phase of the transaction lifecycle. Below is a list of the parameters, what is expected for each of those parameters, and the corresponding notifications you will get by including those parameters:

estimateGas - [balance check notification]

The estimateGas function must return a Promise that resolves with a String that is the gas estimate in wei. This function can vary depending on whether it is a contract transaction or just a regular send transaction call.

gasPrice - [balance check notification]

The gasPrice function must return a Promise that resolves with a String that is the gas price in wei.

balance - [balance check notification]

The users' balance in wei

txDetails - [repeat transaction check notification]

The txDetails object includes a to parameter which is the address the transaction is being sent to and the value parameter, which is the value of the transaction.

contractCall - [repeat transaction check notification]

The contractCall object includes a methodName parameter which is the name of the method on the contract being called and the params parameter is the parameters that the contract method was called with.

sendTransaction - [send transaction error, approval reminder, and stall notifications]

The sendTransaction function must return a Promise that resolves with a String that is the transaction hash.

notification

You may want to trigger a notification for a custom event that may not be related to a transaction. You can use the notification function to do that:

const notificationObject = {
eventCode: "dbUpdate"
type: "pending",
message: "Updating the database with your information"
}
const { update, dismiss } = notify.notification(notificationObject)
//.... somewhere else in your code
if (dbUpdated) {
update({
eventCode: "dbUpdateComplete"
type: "success",
message: "Your info is up to date!"
})
} else {
update({
eventCode: "dbUpdateSlow"
type: "pending",
message: "Database update is taking longer than usual, hang in there!"
})
}

The notification function is called with a notification object with the following parameters:

  • eventCode: a string which is used to keep track of that event for your analytics dashboard

  • type: a string that defines the style - ['hint' (gray), 'pending' (yellow), 'success' (green), 'error' (red)]

  • message: a message string that is displayed on the notification

  • autoDismiss: a number in milliseconds before the notification auto dismisses or 0 for no auto dismissal. success and hint types default to 4000

  • onclick: a function to call when the notification is clicked by the user

Returned from the notification function is an object that has two functions defined on it:

  • update: a function that can be called with a new notification object to replace the original notification with

  • dismiss: a function that can be called to dismiss the notification manually

unsubscribe

You may want to unsubscribe from an account address or transaction hash that you are watching and stop receiving notifications:

// unsubscribe from watched address
notify.unsubscribe(address)
// unsubscribe from watched transaction
notify.unsubscribe(hash | txid)

config

Some configuration options can be set or updated after the library is initialized:

notify.config({
darkMode: Boolean, // (default: false)
mobilePosition: String, // 'top', 'bottom' (default: 'top')
desktopPosition: String, // 'bottomLeft', 'bottomRight', 'topLeft', 'topRight' (default: 'bottomRight')
txApproveReminderTimeout: Number, // (default: 20000)
txStallPendingTimeout: Number, // (default: 20000)
txStallConfirmedTimeout: Number, // (default: 90000)
clientLocale: String, // (default: 'en')
notifyMessages: Object
})

Emitter

The emitter object returned is used to listen for transaction events:

emitter.on("txRepeat", transaction => {
// return false for no notification
// no return (or return undefined) to show default notification
// return custom notification object to show custom notifications, can return all or one of the following parameters:
return {
type: String, // ['hint' (gray), 'pending' (yellow), 'success' (green), 'error' (red)]
message: String, // The message you would like to display
autoDismiss: Number // The number of milliseconds before the notification automatically hides or 0 for no autodismiss
onclick: Function // A function to call when the notification is clicked
link: String // a url string that will make the notification a link when clicked on
}
})
// You can also use the `all` event to register a listener for all events for that transaction. The `all` listener will only be called if there isn't a listener defined for the particular event:
emitter.on("all", transaction => {
// called on every event that doesn't have a listener defined on this transaction
})

Linking to a Block Explorer

You may want to link to a block explorer (such as Etherscan, Alethio, Bloxy etc) on every transaction notification. To do this, a link parameter can be added to the notification object returned from the emitter callback specifying the url:

function addEtherscan(transaction) {
return {
link: `https://etherscan.io/tx/${transaction.hash}`
}
}
// then on each transaction...
const { emitter } = notify.hash(hash)
emitter.on('all', addEtherscan)

Event Codes

The following event codes are valid events to listen to on the transaction emitter:

Client Side Generated Events (when using transaction function):

  • txRequest: Transaction has been initiated and is waiting approval from the user

  • txRepeat: Transaction has the same value and to address, so may be a repeat transaction

  • txAwaitingApproval: A previous transaction is awaiting approval

  • txConfirmReminder: Transaction has not been confirmed after timeout

  • txStallPending: Transaction has not been received in the mempool after timeout

  • txStallConfirmed: Transaction has been in the mempool for longer than the timeout

  • txError: An error has occurred initiating the transaction

  • txSendFail: The user rejected the transaction

  • txUnderpriced: The gas was set too low for the transaction to complete

  • txSent: Transaction has been sent to the network

Server Side (Notify SDK) Generated Events

  • txPool: Transaction was detected in the "pending" area of the mempool and is eligible for inclusion in a block

  • txStuck: Transaction was detected in the "queued" area of the mempool and is not eligible for inclusion in a block

  • txConfirmed: Transaction has been mined

  • txFailed: Transaction has failed

  • txSpeedUp: A new transaction has been submitted with the same nonce and a higher gas price, replacing the original transaction

  • txCancel: A new transaction has been submitted with the same nonce, a higher gas price, a value of zero and sent to an external address (not a contract)

  • txDropped: Transaction was dropped from the mempool without being added to a block. NOTE: Transaction could reappear in mempool.

Local Networks

When using a local network (such as Ganache), Notify has no way of seeing pending and confirmed statuses for transactions on that network and will not display any notifications. The emitter will also not emit events for those statuses. Notify will set the network to local if a networkId is passed in during initialization that is not one of the supported networks

Transaction Object

The callback that is registered for events on the emitter will be called with the following transaction object:

{
status: String, // current status of the transaction
hash: String, // transaction hash (ethereum)
txid: String, // transaction id (bitcoin)
to: String, // the address the transaction is being sent to
from: String, // the address the transaction is being sent from
gas: Number, // the gas in wei
gasPrice: String, // the gasPrice in wei
nonce: Number, // the nonce of the transaction
value: String, // the value being sent
eventCode: String, // the event code for this status
blockHash: String, // the hash of the block that this transaction was included in
blockNumber: Number, // the block number of the block that this transaction was included in
input: String, // hex string of the input data
transactionIndex: Number, // same as the nonce
counterParty: String, // address of the counterparty of the transaction when watching an account
direction: String, // the direction of the transaction in relation to the account that is being watched ("incoming" or "outgoing")
watchedAddress: String, // the address of the account being watched
originalHash: String, // if a speedup or cancel status, this will be the hash of the original transaction
asset: String, // the asset that was transferred
contractCall: { // if transaction was a contract call otherwise undefined
contractAddress: String, // the address of the contract that has been called
contractType: String, // the contract type eg: ERC20, ERC721
methodName: String, // the name of the method that was called
params: {
// params that the contract method was called with
}
},
system: String // 'bitcoin' or 'ethereum'
}

Customizing CSS

To gain the required specificity to override the default styles, use the class name .bn-notify-custom plus the class name that you would like to override in your CSS file. For example, if you would like to customize the font-family of the notifications, then you would target the top level ul element that has the class bn-notify-notifications in your CSS file:

.bn-notify-custom .bn-notify-notifications {
font-family: Roboto;
}

Below is a list of the main classes that you would target to customize the CSS:

class name

description

.bn-notify-notifications

container holding all of the notifications

.bn-notify.notification

top level element of each notification

.bn-notify-notification-info

notification content container

.bn-notify-notification-info-message

notification message

.bn-notify-notification-close

close notification icon container

i18n

Notify has internationalization built in, allowing you to enable transaction notifications that match your user's locale and to give the user an option to switch locale.

clientLocale

Notify will automatically detect the browser's locale and set an internal clientLocale. If that locale is defined within the notifyMessages object, then it will use that locale for all transaction messages. If it isn't defined, then it will fallback to the default 'en' locale. You can explicitly set the clientLocale for the user by calling the config function or passing it in via initializationObject.

notifyMessages

This object contains the messages for all the transaction states supported by Notify. The library has default transaction messages for the 'en' clientLocale and can be extended to include transaction messages for additional clientLocale settings. To extend the default notifyMessages object, you can pass in a notifyMessages object to either the config function or to the initializationObject.

Below is an example object that implements a 'es' (Spanish) notifyMessages object:

const notifyMessages = {
es: {
transaction: {
txRequest: 'Su transacción está esperando que confirme',
nsfFail: 'No tiene fondos suficientes para completar esta transacción.',
txUnderpriced:
'El precio del gas para su transacción es demasiado bajo, intente nuevamente con un precio del gas más alto',
txRepeat: 'Esto podría ser una transacción repetida',
txAwaitingApproval:
'Tienes una transacción anterior esperando que confirmes',
txConfirmReminder:
'Confirme su transacción para continuar, la ventana de transacción puede estar detrás de su navegador',
txSendFail: 'Rechazaste la transacción',
txSent: 'Su transacción ha sido enviada a la red.',
txStallPending:
'Su transacción se ha estancado y no ha ingresado al grupo de transacciones',
txPool: 'Su transacción ha comenzado',
txStallConfirmed:
'Su transacción se ha estancado y no ha sido confirmada.',
txSpeedUp: 'Su transacción ha sido acelerada',
txCancel: 'Tu transacción está siendo cancelada',
txFailed: 'Su transacción ha fallado',
txConfirmed: 'Su transacción ha tenido éxito.',
txError: 'Vaya, algo salió mal, por favor intente nuevamente'
},
watched: {
txPool:
'su cuenta está {verb, select, receiving {recibiendo} sending {enviando}} {formattedValue} {asset} {preposition, select, from {desde} to {a}} {counterpartyShortened}',
txSpeedUp:
'su cuenta está {verb, select, receiving {recibiendo} sending {enviando}} {formattedValue} {asset} {preposition, select, from {desde} to {a}} {counterpartyShortened}',
txCancel:
'su cuenta está {verb, select, receiving {recibiendo} sending {enviando}} {formattedValue} {asset} {preposition, select, from {desde} to {a}} {counterpartyShortened}',
txConfirmed:
'su cuenta {verb, select, received {recibió} sent {ha enviado}} con éxito {formattedValue} {asset} {preposition, select, from {de} to {a}} {counterpartyShortened}',
txFailed:
'su cuenta fallado {verb, select, received {recibió} sent {ha enviado}} con éxito {formattedValue} {asset} {preposition, select, from {de} to {a}} {counterpartyShortened}'
},
time: {
minutes: 'min',
seconds: 'sec'
}
}
}
notify.config({ notifyMessages })

The notifyMessages object above would get merged with Notify's internal notifyMessages object, extending Notify to support both English and Spanish transaction notification messages.

You can include as many of the above parameters as you would like in each language object. If Notify gets an undefined value back from the language object, then it will fallback to the English default included in Notify.

Notify uses format.js under the hood, which uses the ICU message syntax to format messages. Check out their guide to the ICU message syntax here.

For each language, you can include a transaction object, a watched object and a time object.

The transaction object will be referenced for notifications that have been triggered via the hash or transaction function. The watched object will be referenced for notifications that have been triggered by watching an address via the account function. The time object will be referenced for expressing the amount of time that has passed during pending states on the notification.

Each message will be called with the following inputs that will be formatted in to a message string:

The formatted value of the transaction: formattedValue - (transaction, watched)

The asset that is being sent or received: asset - (transaction, watched)

The correct verb based on whether the transaction is being incoming or outgoing and whether it is confirmed or pending: verb - (watched) Possible values are: 'received', 'sent', 'receiving', 'sending'

The correct preposition based on the direction of the transaction: preposition - (watched) Possible values are: 'from', 'to'

A shortened address of the counter party of the transaction: counterpartyShortened - (watched)

UI Only Mode

You can optionally run Notify.js as a simple notification UI library by not including a dappId in your initialization options. In this scenario, Notify.js will not initiate a WebSocket connection to the Blocknative servers and all functionality other than the notification function will be disabled.

Rollup Builds

You may run in to an error: Uncaught TypeError: dist is not a constructor when building with Rollup.js. To fix this issue make sure that you are using @rollup/plugin-commonjs version 16.0.0 and above

Get Started Today

Sign up for a free Blocknative Account at https://account.blocknative.com/ with your work email address.

If you have any questions, connect with the team on our discord

React Demo

To see a Notify integration in a simple React app you can check out our react-demo repo on GitHub: https://github.com/blocknative/react-demo We have the reactdemo codebase deployed so that you try Notify from an end user perspective: https://reactdemo.blocknative.com/