-
Notifications
You must be signed in to change notification settings - Fork 10
Chrome Extension Wallet Integration for Aptos
Crypto.com | Wallet Extension now support the Aptos blockchain. Crypto.com | Wallet Extension is a free web application. Using Crypto.com | Wallet Extension, a user can store and transfer assets, and interact with the decentralized applications (dApps), all on the Aptos blockchain.
This developer documentation describes how to integrate Wallet into your dApp and enable your user to connect their Wallet to the Aptos blockchain.
NOTE: Crypto.com | Wallet Extension is currently available as a browser extension on Google Chrome.
The rest of the documentation describes in detail the following steps for your dApp integration:
- Checking for Crypto.com | Wallet Extension.
- Connecting to Crypto.com | Wallet Extension.
- Getting a user to sign, and optionally, send, a transaction to the Aptos blockchain.
- Getting a user to sign a message.
- Handling event updates from the wallet.
- Error messages.
import type { Types } from 'aptos'
enum Network {
Testnet = 'Testnet',
Mainnet = 'Mainnet',
Devnet = 'Devnet',
'Aptos Testnet' = 'Testnet',
Aptos = 'Mainnet',
'Aptos Devnet' = 'Devnet',
}
type Networks = keyof typeof Network
interface NetworkConfig {
name: string
chainType: 'aptos'
chainId: string
rpcUrl: string
symbol: string
explorer?: string
}
interface IAccount {
publicKey: MaybeHexString | undefined
address: MaybeHexString | undefined
method?: string
status: number
}
interface IOptions {
sender?: MaybeHexString
sequence_number?: any
max_gas_amount?: string,
gas_unit_price?: string,
gas_currency_code?: string,
expiration_timestamp_secs?: string,
}
interface SignMessagePayload {
address?: boolean // Should we include the address of the account in the message
application?: boolean // Should we include the domain of the dapp
chainId?: boolean // Should we include the current chain id the wallet is connected to
message: string // The message to be signed and displayed to the user
nonce: string // A nonce the dapp should generate
}
interface SignMessageResponse {
address: string
application: string
chainId: number
fullMessage: string // The message that was generated to sign
message: string // The message passed in by the user
nonce: string
prefix: string // Should always be APTOS
signature: string // The signed full message
}
interface IDeficonnectAptos {
connect: (network?: NetworkConfig) => Promise<IAccount>;
account: () => Promise<IAccount>;
isConnected: () => Promise<boolean>;
signAndSubmitTransaction(
transaction: Types.TransactionPayload,
options?: IOptions
): Promise<Types.Transaction>;
signTransaction(transaction: Types.TransactionPayload, options?: IOptions): Promise<Uint8Array>;
signMessage(message: SignMessagePayload): Promise<SignMessageResponse>;
disconnect(): Promise<void>;
network(): Promise<Networks>;
onAccountChange: (listener: (newAddress: IAccount) => void) => void;
onNetworkChange: (listener: (network: { networkName: Networks }) => void) => void;
}
To use Crypto.com | Wallet Extension with your dApp, your user must first install Crypto.com | Wallet Extension on their Chrome browser. Crypto.com | Wallet Extension injects an aptos
object inside the deficonnect
object of window on any web app the user visits.
To check if the user has installed Crypto.com | Wallet Extension, perform the below check:
const isInstalled = window.deficonnect.aptos
If Crypto.com | Wallet Extension is not installed, you can prompt the user to first install Crypto.com | Wallet Extension and provide the below installation instructions. For example, see below:
const getWallet = () => {
if (window.deficonnect && window.deficonnect.aptos) {
return window.deficonnect.aptos;
} else {
window.open('https://crypto.com/defi-wallet#wallet_extension', `_blank`);
}
}
To install Crypto.com | Wallet Extension on your Chrome browser, you can download it from the chrome store.
After confirming that the web app has the deficonnect.aptos
object, we can connect to Wallet by calling deficonnect.aptos.connect()
.
When you call deficonnect.aptos.connect()
, it prompts the user to allow your web app to make additional calls to the Wallet, and obtains from the user basic information like the address and public key. It also exposes a convenience isConnected.
See the example code below:
await window.deficonnect.aptos.connect(); // { address: string, publicKey: string }
await window.deficonnect.aptos.isConnected(); // true
NOTE: After a web application connects to the wallet for the first time, it becomes whitelisted session. Once whitelisted, it's possible for the application to automatically connect to the wallet on subsequent visits or page refreshes.
Crypto.com | Wallet Extension also support switch network, you can pass networkConfig
parameter into connect()
, and it will trigger network switch confirmation popup.
See the example code below:
interface AptosNetworkConfig {
name: string
chainType: 'aptos'
chainId: string
rpcUrl: string
symbol: string
explorer?: string
}
const networkConfig: AptosNetworkConfig = {
chainId: '2',
chainType: 'aptos',
name: 'Testnet',
rpcUrl: 'https://fullnode.testnet.aptoslabs.com/v1',
symbol: 'APT',
}
await window.deficonnect.aptos.connect(networkConfig); // { address: string, publicKey: string }
When you want the web app to forget about the connection status with the Wallet, you can do this by calling window.deficonnect.aptos.disconnect()
in your web app. See below:
await window.deficonnect.aptos.disconnect()
NOTE: After disconnecting, the web app must reconnect to the Wallet if user want to make requests again.
After the web app is connected to the Wallet, the web app can prompt the user to sign and send transactions to the Aptos blockchain.
Crypto.com | Wallet Extension API handles the transactions in the following two ways:
- Sign a transaction and submit it to the Aptos blockchain. Return a pending transaction to the web app.
- Sign a transaction but do not submit the transaction to the Aptos blockchain. Return the signed transaction to the web app, for the web app to submit the transaction.
See the below examples for both the options.
For more on Aptos transactions, see the Aptos Typescript SDK and Transactions guide from Aptos .
The below code example shows how to use the signAndSubmitTransaction()
API to sign the transaction and send it to the Aptos blockchain.
interface IResponse {
hash: string
sender?: string
sequence_number?: string
max_gas_amount?: string
gas_unit_price?: string
expiration_timestamp_secs?: string
payload?: TransactionPayload
signature?: AccountSignature
}
const wallet = window.deficonnect.aptos.connect(); // see "Connecting"
// Example Transaction, following an [EntryFunctionPayload](https://github.com/aptos-labs/aptos-core/blob/main/ecosystem/typescript/sdk/src/generated/models/EntryFunctionPayload.ts#L8-L21)
const transaction = {
arguments: [wallet.address, '717'],
function: '0x1::coin::transfer',
type: 'entry_function_payload',
type_arguments: ['0x1::aptos_coin::TestCoin'],
};
try {
const pendingTransaction: IResponse = await window.deficonnect.aptos.signAndSubmitTransaction(transaction);
// In most cases a dApp will want to wait for the transaction, in these cases you can use the typescript sdk
const client = new AptosClient('https://testnet.aptoslabs.com');
client.waitForTransaction(pendingTransaction.hash);
} catch (error) {
// see "Errors"
}
The below code example shows how to use the signTransaction()
API to only sign the transaction, without submitting it to the Aptos blockchain.
const wallet = window.deficonnect.aptos.connect(); // see "Connecting"
// Example Transaction
const transaction = {
arguments: [wallet.address, '717'],
function: '0x1::coin::transfer',
type: 'entry_function_payload',
type_arguments: ['0x1::aptos_coin::TestCoin'],
};
try {
const signTransaction = await window.deficonnect.aptos.signTransaction(transaction)
} catch (error) {
// see "Errors"
}
A web app can also request the user to sign a message, by using API window.deficonnect.aptos.signMessage(payload: SignMessagePayload)
.
Web apps can write their own message, then send it to the Wallet. The user will be prompted to sign that message, and then the signed message will be returned to the web app. The following is provided for additional security.
-
signMessage(payload: SignMessagePayload)
prompts the user with thepayload.message
to be signed- returns
Promise<SignMessageResponse>
- returns
Types:
export interface SignMessagePayload {
address?: boolean; // Should we include the address of the account in the message
application?: boolean; // Should we include the domain of the dapp
chainId?: boolean; // Should we include the current chain id the wallet is connected to
message: string; // The message to be signed and displayed to the user
nonce: string; // A nonce the dapp should generate
}
export interface SignMessageResponse {
address: string;
application: string;
chainId: number;
fullMessage: string; // The message that was generated to sign
message: string; // The message passed in by the user
nonce: string,
prefix: string, // Should always be APTOS
signature: string; // The signed full message
}
import nacl from 'tweetnacl';
const message = "hello";
const nonce = "random_string"
try {
const response = await window.deficonnect.aptos.signMessage({
message,
nonce,
});
const { publicKey } = await window.deficonnect.aptos.account();
// Remove the 0x prefix
const key = publicKey!.slice(2, 66);
const verified = nacl.sign.detached.verify(Buffer.from(response.fullMessage),
Buffer.from(response.signature, 'hex'),
Buffer.from(key, 'hex'));
console.log(verified);
} catch (error) {
console.error(error);
}
A dApp may want to make sure that a user is on the right network. In this case you will need to check what network the wallet is using.
Default networks provided by the wallet:
// default networks in the wallet
enum Network {
Testnet = 'Testnet',
Mainnet = 'Mainnet',
Devnet = 'Devnet'
}
// Current network
let network = await window.deficonnect.aptos.network();
// event listener for network changing
window.deficonnect.aptos.onNetworkChange((newNetwork) => {
network = newNetwork.networkName;
});
In the Wallet a user may change accounts while interacting with your app. To check for these events you can listen for them with onAccountChange
// get current account
let currentAccount = await window.aptos.account();
// event listener for disconnecting
window.deficonnect.aptos.onAccountChange((newAccount) => {
// If the new account has already connected to your app then the newAccount will be returned
if (newAccount) {
currentAccount = newAccount;
} else {
// Otherwise you will need to ask to connect to the new account
currentAccount = window.deficonnect.aptos.connect();
}
});
A user may choose to disconnect from your dApp. In that case you will want to update your state.
// get current connection status
let connectionStatus = await window.deficonnect.aptos.isConnected();
// event listener for disconnecting
window.deficonnect.aptos.onDisconnect(() => {
connectionStatus = false;
});
When making requests to Petra Wallet API, you may receive an error. The following is a partial list of the possible errors and their corresponding codes:
- Code: 4000
- Name: No Accounts
- Message: No accounts found.
- Code: 4001
- Name: User rejection
- Message: The user rejected the request.
- Code: 4100
- Name: Unauthorized
- Message: The requested method and/or account has not been authorized by the user.
© 2022 Crypto.com. All Rights Reserved.