Notify.js

Client library for a full notification UI experience
Sample Notifications

To see the notify.js library in action, checkout the code sandboxes at the end of this documentation.

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 myAccounts = await web3.eth.getAccounts();
const myAddress = accounts[0];
// send the transaction using web3.js and get the hash
web3.eth.sendTransaction({
from: myAddress,
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

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: "Your dappId here",
networkId: 1,
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)

Required Fields

dappId

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

networkId

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

  • 1 Main Network

  • 3 Ropsten Test Network

  • 4 Rinkeby Test Network

  • 5 Goerli Test Network

  • 42 Kovan Test Network

Optional Fields

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:

// 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)
})

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:

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

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:

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 false 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

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 false for no autodismiss
onclick: Function // A function to call when the notification is clicked
}
})
// 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
})

Event Codes

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

  • 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 with the transaction

  • txSendFail: The user rejected the transaction

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

  • txPool: Transaction is in the mempool and is pending

  • 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.

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
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
r: String, // transaction signature
s: String, // transaction signature
v: String, // transaction signature
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
}
}
}

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 set within the notifyMessages object, then it will use that locale for all transaction messages. If it doesn't exist 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 support 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}'
}
}
}
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 and a watched 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.

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)

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

Sandboxes

Use this sandbox to see live running code and experiment with the library. You will need an active wallet with some funds to try the transactions. We recommend using a supported testnet (ropsten, rinkeby, goerli, or kovan).

web3.js 1.2

ethers.js 5