Pontem Provider
When a user has Pontem Wallet installed (be it as an extension or a mobile app), a special object called Provider is embedded on each page. Its purpose is to enable dApp developers to interact with our wallet.
This object is located in the global variable window
. You can access it using a window.pontem
call
Below we'll provide sample code and logic for getting information about a user, including their address / public key, as well as send requests to send transactions and sign your messages.
You can find more examples of the Provider object's methods on the API Reference page.
Detect the Provider
The first step is to check the availability of the pPovider. Since the insertion of the pontem
provider into the window
does not happen immediately when a page is loaded, you should wait for a bit and subscribe to a special event #pontemWalletInjected
, which the Provider generates when it is placed in the window
.
function detectProvider (timeout = 3000) {
return new Promise((resolve, reject) => {
if (typeof window.pontem === 'undefined') {
const timer = setTimeout(reject, timeout)
window.addEventListener('#pontemWalletInjected', (e) => {
clearTimeout(timer)
resolve(e.detail)
}, { once: true })
} else {
resolve(window.pontem)
}
})
}
detectProvider()
.then(provider => console.log('Pontem Wallet Detected'))
.catch(() => console.log('Pontem Wallet not found'))
Now you know how to get a Provider in your dApp application.
Let's take a closer look at how to interact with it.
Interacting with Provider
Versioning
You should pay attention to the version of Pontem Wallet that the user has installed.
The Aptos ecosystem is still very young, and wallet features may differ considerably from version to version. In the API guide, you can always see in which version a certain method appeared, as well as changes in the method signature.
INFO
The Pontem team is working to minimize future changes to the wallet API and ensure backward compatibility. You can see all the changes introduced in each version in our changelog.
To get the current version of the installed Provider, you need to use the provider.version
property. We version according to the semver standard.
detectProvider()
.then(provider => {
console.log(provider.version) // 2.6.1
})
Check connection status
First of all, when a Provider object is found, we need to check the status of the wallet connection to the site. To do this, you can use the provider.isConnected
method, which will return a boolean
value
detectProvider()
.then(async provider => {
const status = await provider.isConnected(); // true or false
})
After that, you can query the current account
detectProvider()
.then(async provider => {
const status = await provider.isConnected()
if(status) {
const account = await provider.account(); // will return the address of the current account
}
})
If you query an account when the user has not given permission for the site to access the wallet, an error will be returned as an exception in Promise.
detectProvider()
.then(async provider => {
try {
const account = await provider.account();
} catch (e) {
console.log(e); // { code: 401, message: 'Access denied' }
}
})
Request to Connect
When a user first interacts your dApp, they will need to allow access to it in their wallet. To initialize this process, you need to call the provider.connect
method, which will open an extension window (or mobile application) with a confirmation request.
TIP
If the connect method has already been called before and the user has already granted access, you will receive the following structure in the response, and a UI confirmation window for a join request will not be displayed.
detectProvider()
.then(async provider => {
try {
const account = await provider.connect();
console.log(account);
/*
{
address: "0x797b0209c...15e63e",
publicKey: "0xf7498703...1ee4e4"
}
*/
} catch (e) {
console.log(e); // { code: 403, message: 'Rejected by user' }
}
})
If the user allows access to the wallet account, you will receive an account structure that contains address
and publicKey
.
TIP
You can also obtain the account's public key later using the provider.publicKey method.
Subscribe to Account change
It can be useful to subscribe to changes in the account's status of connection to the site. For example, a user can switch the account or manually remove the dApp from the list of allowed sites. To properly handle such events, use the provider.onChangeAccount
method.
detectProvider()
.then(async provider => {
const unsubscribe = provider.onChangeAccount((account) => {
console.log(account); // undefined or address
})
})
If the user switches to an account that hasn't yet been granted access to the site, or disables access manually, you will receive undefined
in response.
Subscribe to Network change
The same can be done for network change events. When a user switches to a different network, you will also receive a notification. To properly handle such events, use the provider.onChangeNetwork
method.
This method will call callback every time the network is changed. The network object stores information about its name
, chainId
and api
address to the node.
detectProvider()
.then(async provider => {
const unsubscribe = provider.onChangeNetwork((network) => {
console.log(network);
// { name: 'Aptos testnet', api: 'https://fullnode.testnet.aptoslabs.com/v1/', chainId: '2' }
})
})
TIP
You can also get the current network later using the provider.network method.
Request to Sign Transaction
Now you can proceed to the most interesting part: signing and sending transactions. To send a transaction, you need to prepare all its data and pass it on to the provider.signAndSubmit
method
detectProvider()
.then(async provider => {
const tx = {
function: '0x1::coin::transfer',
type_arguments: ['0x1::aptos_coin::AptosCoin'],
arguments: [
'0xeb442855143ce3e26babc6152ad98e9da7db7f0820f08be3d006535b663a6292',
'100'
]
}
try {
const result = await provider.signAndSubmit(tx)
} catch (e) {
console.log(e);
}
})
⚡️ TypedArray support
You can also pass TypedArray objects such as Uint8Array, Int8Array objects as arguments.
const typedArgument = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05])
const result = await provider.signAndSubmit({
function: '0x1::coin::transfer',
type_arguments: ['0x1::aptos_coin::AptosCoin'],
arguments: [
typedArgument,
'100'
]
})
Request to Disconnect
You can disconnect the wallet from your dApp at any time by calling the provider.disconnect
method. This will not remove the entry about the site from the user's wallet, as only the user can remove a site from the allowed list through the UI interface. The provider.disconnect
method will disconnect the wallet, and you will receive a false
response to provider.isConnected
requests.
detectProvider()
.then(async provider => {
await provider.disconnect();
})
TIP
To connect the wallet back you need to call the provider.connect
method. This will not trigger a UI confirmation for the user.