# Aptos
To use Bitget Wallet with your dApp, your users must first install the Bitget Wallet Chrome extension in their browser. Bitget Wallet injects an bitkeep.aptos
object into the window (opens new window) of any web app the user visits.
This feature is supported by the following versions of Bitget Wallet.
Platform | Version | Description |
---|---|---|
Chrome Extension | >=v1.3.8 | |
App(IOS) | >=v7.2.5 | |
App(Android) | >=v7.2.5 |
# npm package
# Installed or not
To check if the user has installed Bitget Wallet, perform the below check:
const isBitKeepInstalled = window.bitkeep && window.bitkeep.aptos;
# Detecting the Aptos provider
If Bitget Wallet is not installed, you can prompt the user to first install Bitget Wallet and provide the below installation instructions. For example, see below:
function getAptosWallet() {
const provider = window.bitkeep && window.bitkeep.aptos;
if (!provider) {
window.open('https://web3.bitget.com/en/wallet-download?type=2');
throw 'Please go to https://web3.bitget.com/en/wallet-download?type=2 to download!!';
}
return provider;
}
2
3
4
5
6
7
8
# Connecting to Bitget Wallet
After confirming that the web app has the bitkeep.aptos
object, we can connect to Bitget Wallet by calling wallet.connect()
.
When you call wallet.connect()
, it prompts the user to allow your web app to make additional calls to Bitget Wallet, and obtains from the user basic information such as the address and public key.
Note:
After the user has approved the connnection for the first time, the web app's domain will be remembered for the future sessions.
See the example code below:
const wallet = getAptosWallet();
try {
const response = await wallet.connect();
console.log(response); // { address: string, address: string }
const account = await wallet.account();
console.log(account); // { address: string, address: string }
} catch (error) {
// { code: 4001, message: "User rejected the request."}
}
2
3
4
5
6
7
8
9
10
# Sending a Transaction
After your web app is connected to Bitget Wallet, the web app can prompt the user to sign and send transactions to the Aptos blockchain.
Bitget Wallet API handles the transactions in 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.
Note:
For more on Aptos transactions, see the Aptos SDKs (opens new window) and Transactions guide from Aptos (opens new window).
# Sign and submit
The below code example shows how to use the signAndSubmitTransaction() API to sign the transaction and send it to the Aptos blockchain.
const wallet = getAptosWallet(); // 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: [address, '717'],
function: '0x1::coin::transfer',
type: 'entry_function_payload',
type_arguments: ['0x1::aptos_coin::TestCoin'],
};
/**
* Custom gas fee
* default {
"gas_unit_price":"100",
"max_gas_amount":"10000"
}
*/
const options = {
gas_unit_price:100,
max_gas_amount:10000
}
try {
const pendingTransaction = await window.bitkeep.aptos.signAndSubmitTransaction(transaction);
// const pendingTransaction = await window.bitkeep.aptos.signAndSubmitTransaction(transaction, options);
// 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"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Sign only
IMPORTANT: We don't recommend using this because in most cases you don't need it, and it isn't super safe for users. They will receive an extra warning for this.
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 = getAptosWallet(); // see "Connecting"
// Example Transaction
const transaction = {
arguments: [address, '717'],
function: '0x1::coin::transfer',
type: 'entry_function_payload',
type_arguments: ['0x1::aptos_coin::TestCoin'],
};
/** Custom gas fee
* default {
"gas_unit_price":"100",
"max_gas_amount":"10000"
}
*/
const options = {
gas_unit_price: 100,
max_gas_amount:10000
}
try {
const signTransaction = await window.bitkeep.aptos.signTransaction(transaction)
// const signTransaction = await window.bitkeep.aptos.signTransaction(transaction, options)
} catch (error) {
// see "Errors"
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# Signing Messages
A web app can also request the user to sign a message, by using Bitget Wallet API: wallet.signMessage(payload: SignMessagePayload)
signMessage(payload: SignMessagePayload)
prompts the user with the payload.message to be signed- returns
Promise<SignMessageResponse>
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
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Example message
signMessage({nonce: 1234034, message: "Welcome to dapp!" }) This would generate the fullMessage to be signed and returned as the signature:
APTOS
nonce: 1234034
message: Welcome to dapp!
2
3
# Verifying
The most common use case for signing a message is to verify ownership of a private resource.
import nacl from 'tweetnacl';
const message = "hello";
const nonce = "random_string"
try {
const response = await window.bitkeep.aptos.signMessage({
message,
nonce,
});
const { publicKey } = await window.bitkeep.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);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Event Listening
# onNetworkChange() and network()
A DApp may want to make sure a user is on the right network. In this case, you will need to check what network the wallet is using.
network
We support network:
Mainnet
| Devnet
'Testnet' has been modified to 'Mainnet'`
Default networks provided by the Bitget Wallet:
// default networks in the wallet
enum Network {
Mainnet = 'Mainnet'
Devnet = 'Devnet'
}
// Current network
let network = await window.bitkeep.aptos.network();
// event listener for network changing
window.bitkeep.aptos.onNetworkChange((newNetwork) => {
network = newNetwork; // { networkName: 'Mainnet' }
});
2
3
4
5
6
7
8
9
10
11
12
13
# onAccountChange()
In Bitget Wallet, a user may change accounts while interacting with your app. To check for these events, listen to them with: onAccountChange.
// get current account
let currentAccount = await window.bitkeep.aptos.account();
// event listener for disconnecting
window.bitkeep.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.bitkeep.aptos.connect();
}
});
2
3
4
5
6
7
8
9
10
11
12
13
# Errors
When making requests to Bitget Wallet API, you may receive an error. The following is a partial list of the possible errors and their corresponding codes:
{
code: 4100,
message:"The requested method and/or account has not been authorized by the user."
}
2
3
4
- 4100 The requested method and/or account has not been authorized by the user.
- 4000 No accounts found.
- 4001 The user rejected the request
# npm package
# Use Aptos Wallet Adapter (opens new window)
#
Note:
This is a single repository consisting of the wallet adapter and a simple Web application
Check the official demo (opens new window)
# Install
Install npm package
yarn add @manahippo/aptos-wallet-adapter
Then initialize in the application
import React, { useMemo, useState } from 'react';
import {
WalletProvider,
BitkeepWalletAdapter,
} from '@manahippo/aptos-wallet-adapter';
import MainPage from './MainPage';
const App = () => {
const [auto, setAuto] = useState(false);
const wallets = useMemo(
() => [
new BitkeepWalletAdapter(),
],
[]
);
return (
<WalletProvider
wallets={wallets}
autoConnect={auto}
onError={(error) => {
console.log('wallet errors: ', error);
}}>
{ /* Your app's components go here, nested within the context providers. */}
</WalletProvider>
);
};
export default App;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Sign message
import { useMemo, useState } from 'react';
import { useWallet } from '@manahippo/aptos-wallet-adapter';
const MainPage = () => {
const {
connect,
account,
wallets,
connecting,
connected,
disconnecting,
wallet: currentWallet,
signMessage,
} = useWallet();
const messageToSign = useMemo(
() =>
`Hello from account ${Array.isArray(account?.publicKey)
? JSON.stringify(account.publicKey, null, 2)
: account?.publicKey?.toString() || account?.address?.toString() || ''
}`,
[account]
);
const [signature, setSignature] = useState('');
const handleSign = async () => {
const signedMessage = await signMessage({
message: messageToSign,
nonce: 'random_string'
});
setSignature(signedMessage.signature)
}
const renderWalletConnectorGroup = () => {
return wallets.map((wallet) => {
const option = wallet.adapter;
return (
<button
onClick={() => {
connect(option.name);
}}
id={option.name.split(' ').join('_')}
key={option.name}>
{option.name}
</button>
);
});
};
const renderContent = () => {
if (connecting || disconnecting) {
return 'loading...'
}
if (connected && account) {
return (
<div >
<div>Wallet: {currentWallet?.adapter.name}</div>
<div>Address: {account?.address?.toString()}</div>
<div>signdMessage: {signature}</div>
<button onClick={() => handleSign()} >Sign Message</button>
</div>
);
} else {
return <div >{renderWalletConnectorGroup()}</div>;
}
};
return (
<div>
<div>{renderContent()}</div>
</div>
);
}
export default MainPage;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74