README
NEW SDK
THIS REPO IS DEPRECATED, PLEASE USE OURPortis
The Portis platform provides convenient access to the Ethereum network from any web application.
How does it work?
Your dApp (decentralized application) communicates with the Portis SDK using standard web3.js API calls, meaning it will work automatically with your existing web application.
Users don’t have to install anything in advance to use your dApp. With Portis, your dApp already comes bundled with a solution by offering them a simple in-browser email/password login method which feels familiar.
Security
Once a user creates a wallet, it is immediately encrypted using AES-GCM. The Portis server only stores encrypted wallets, so we can enable users to easily use the same account across different devices, all without compromising security. Every transaction is signed client-side by the user, meaning the Portis server only relays signed transactions (i.e it can't modify them).
Our code underwent rigorous third party security audits. The SDK is published open source because we believe that is the best way to reach a truly secure codebase. In addition, we want to involve developers as much as possible and welcome any and all comments / pull requests.
For security reasons, dApps using Portis must run over HTTPS.
Installation
To begin using Portis in your dApp, the Portis SDK JavaScript code should be loaded into your dApp's code. There are several ways to carry this out:
npm
The recommended method of loading Portis is by installing the portis
npm package:
$ npm install portis
CDN
You can also include the bundled portis.js file hosted on jsdelivr's CDN:
<script src="https://cdn.jsdelivr.net/npm/portis/dist/bundle.min.js"></script>
Bower
We also provide a way to deploy Portis via bower. Useful if you want serve your own scripts (instead of depending on our CDN) and maintain a bower.json
with a list of dependencies and versions (adding the --save
flag would automatically add it to bower.json
).
$ bower install portis --save
<script src="/bower_components/portis/dist/bundle.min.js"></script>
Import
Portis should be imported into the same part of the code where you initialize web3
CommonJS
To use Portis with CommonJS imports:
var PortisProvider = require('portis').PortisProvider;
Typescript / ES2015 (ES6)
To use Portis with Typescript / ES2015 imports:
import { PortisProvider } from 'portis';
CDN
To use Portis from CDN:
var PortisProvider = window.Portis.PortisProvider;
Registration
Register your dApp on the Portis platform - https://app.portis.io/dashboard.
In this page, you will be able to manage all of your dApps which are powered by Portis.
Inside your dApp's info page you will see your API Key. You will need to provide that key when initializing Portis as your Web Provider
.
The API Key is not secret (as it is being sent from the client), its goal is to verify that the dApp using Portis has been registered and is approved.
Initialization
Once Portis has been imported, you should set it up as your fallback Web3 Provider
:
// Check if Web3 has been injected by the browser (Mist/MetaMask)
if (typeof web3 !== 'undefined') {
// Use Mist/MetaMask's provider
web3js = new Web3(web3.currentProvider);
} else {
// Fallback - use Portis
web3js = new Web3(new PortisProvider({
apiKey: 'YOUR_DAPP_API_KEY'
}));
}
// Now you can start your app & access web3 freely:
startApp();
This will set Portis as the fallback for when Mist/MetaMask or any other pre-installed web3 providers are not available.
If the Portis provider was injected properly, then isPortis
will return true
web3.currentProvider.isPortis
Usage
Here is an example. (Hit "Run" if you don't see anything, and make sure you either disable MetaMask or use private mode on your browser)
Getting the user's address
If you need the user's address, perhaps to authenticate them into your website, you would use the regular web3.eth.getAccounts
method. Nothing special here:
// ES7+ async/await
const accounts = await web3.eth.getAccounts()
const [address] = accounts
// ES6 Promise
web3.eth.getAccounts().then(accounts => {
const address = accounts[0]
})
Note that unlike MetaMask, Portis only supports a single wallet per account.
personal_sign
method:
Using a More info on personal_sign
here: https://github.com/ethereum/go-ethereum/wiki/Management-APIs#personal_sign
Again, nothing special here! Use the regular web3.currentProvider.sendAsync
method:
web3.currentProvider.sendAsync(
{
id: 1,
method: 'personal_sign',
from: address,
params: [data, address, password],
},
(err, result) => {
if (err) {
throw new Error(err)
}
authenticateUser(result.result)
},
)
Configuration Options
A configuration options object should be passed along when initializing the Portis provider:
web3js = new Web3(new Portis.PortisProvider({
apiKey: 'YOUR_DAPP_API_KEY',
network: 'ropsten'
}));
apiKey
Type: String
Default Value: null
Required: true
The API Key of your dApp, provided in the Portis dashboard after registering your dApp.
network
Type: String
Default Value: mainnet
Required: false
Determines which Ethereum network all web3 methods will communicate with. You can set Portis to work with any one of the following networks:
- mainnet
- ropsten
- kovan
- rinkeby
- sokol (POA Network)
- core (POA Network)
infuraApiKey
Type: String
Default Value: null
Required: false
The API Key of your Infura account. If provided, Infura will serve as the provider node for all outgoing communication with the Ethereum network.
providerNodeUrl
Type: String
Default Value: null
Required: false
The URL of a custom provider node. If provided, that endpoint will serve as the provider node for all outgoing communication with the Ethereum network.
The valid types are HttpProvider
, WebsocketProvider
and IpcProvider
, as defined in the web3js documentation.
Example:
HttpProvider
:
providerNodeUrl: 'http://localhost:8545'
scope
Type: String[]
Default Value: null
Required: false
When a person logs into your DApp via Portis you can request to access a subset of that person's data stored on Portis using the scope
parameter. Its value is an array of strings of the requested permissions. As of now, the only supported permissions string is email
. The user can either approve or decline the permissions request. If they approve, their email will be returned in the login
event.
Example:
web3js = new Web3(new Portis.PortisProvider({
apiKey: 'YOUR_DAPP_API_KEY',
network: 'ropsten',
scope: ['email']
}));
Methods
changeNetwork(options)
Change the network for all future web3 method calls. The network change will only apply once the user finished signing all pending transactions for the previously set network.
The method accepts an object to set the new network to be used. It should contain one of the three values that can be used during the PortisProvider
initialization: network | infuraApiKey | providerNodeUrl
Example:
web3.currentProvider.changeNetwork({ network: 'kovan' });
setDefaultEmail(email: string, editable: boolean)
If you already know the user's email address, you can use this method to pre-populate the email field in the login and register pages.
When editable
is false, all email inputs will be disabled. The default value of editable
is true
.
Example:
web3.currentProvider.setDefaultEmail('satoshi@portis.io');
showPortis(callback: function)
You may want to show a user their Portis account without necessarily having them carry out an action (e.g. signTransaction). Calling this method will open the Portis window. The provided callback function will be called once the window has been closed explicitly by the user.
Example:
web3.currentProvider.showPortis(() => {
console.log('Portis window was closed by the user');
});
on(eventName: string, callback: function)
The Portis provider emits events using the .on('eventName', callback) scheme.
Example:
web3.currentProvider.on('event-type', result => {
console.log('event-type was thrown');
});
Event types:
login
When a DApp calls any web3 method which requires the user to login (for instance getAccounts), there is no way for the DApp to know if the callback was successful since the user just logged in to Portis successfully, or if they were already logged in, and it was invoked successfully without having to show the login window to the user.
The login
event allow DApps to detect when a user explicitly logged in successfully to their Portis account. The callback method will return an object containing:
provider
: will always have the valueportis
address
: the wallet address of the logged in useremail
: if theemail
permission was requested in the scope, and the user approved sharing it, this value will contain the user's email address
purchase-initiated
When a user initiates an ETH purchase through our third-party provider, the purchase-initiated
event is thrown.
The callback method will return an object containing two values:
provider
: will always have the valueportis
purchaseId
: a unique indentifier which can be used to poll the purchase status, as documented in the dashboard.
Browsers support
For security reasons, Portis supports "evergreen" browsers - the last versions of browsers that automatically update themselves.
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
---|---|---|---|---|---|
last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions | last 2 versions |