Aptos dApp Integration

Install CLV Wallet

To use CLV Wallet for your Aptos dApp, your users need to install CLV Wallet Chrome extension in their browser. CLV Wallet injects an clover_aptos object into the window of any dApp that the user visits.

To check whether the user has installed CLV Wallet, please use the following check:

const isCLVInstalled = window.clover_aptos

If CLV Wallet is not installed, you can navigate user to install CLV Wallet first. For example

const getCLVWallet = () => {
    if ('clover_aptos' in window) {
        return window.clover_aptos;
    } else {
        window.open('https://clv.org/?type=wallet', `_blank`);
    }
}

Connect to CLV Wallet

After clover_aptos object is injected into the dApp, we can connect to CLV Wallet by calling wallet.connect(). When this function is called, it will prompt user a dialog to approve or reject the interactions between your web app and CLV Wallet. Once connection is approved, you can easily get user's current wallet address. Sample code:

const wallet = getCLVWallet();
try {
    const response = await wallet.connect();
    console.log(response); // { address: string, publicKey: string }

    const account = await wallet.account();
    console.log(account); // { address: string, publicKey: string }
} catch (error) {
    // { code: 500, message: "The request was cancelled."}
}

Disconnect CLV Wallet

If you want the dApp to disconnect from CLV Wallet, you should just call wallet.disconnect().

await wallet.disconnect();

Transaction Signing

Once your dApp is connected with CLV Wallet, it can prompt to user to sign and send transactions to the Aptos blockchain.

Case 1: Sign and Submit

const wallet = getCLVWallet();

const transaction = {
    arguments: [address, '1'],
    function: '0x1::coin::transfer',
    type: 'entry_function_payload',
    type_arguments: ['0x1::aptos_coin::MyCoin'],
};

try {
    const tx = await wallet.signAndSubmitTransaction(transaction);
    console.log(tx.hash); // this is the transaction hash
    
    return tx;
} catch (error) {
    // see "Errors"
}

Case 2: Sign only

const wallet = getAptosWallet(); // see "Connecting"

// Example Transaction
const transaction = {
    arguments: [address, '1'],
    function: '0x1::coin::transfer',
    type: 'entry_function_payload',
    type_arguments: ['0x1::aptos_coin::MyCoin'],
};

try {
    const signTransaction = await wallet.signTransaction(transaction);
    console.log(signTransaction); // Uint8Arry for signed transaction
} catch (error) {
    // see "Errors"
}

Message Signing

A dApp can call wallet.signMessage(payload: SignMessagePayload) to sign a message using CLV Wallet.

The above function call will return Promise<SignMessageResponse>. Types info are:

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
}

Example message and response

signMessage({nonce: 1234, message: "Welcome to CLV Wallet!" });

The above would generate a full message to be signed and returned as the signature:

APTOS
nonce: 1234
message: Welcome to CLV Wallet!

Signature Verifying

import nacl from 'tweetnacl';

const message = "hello";
const nonce = "random_string"

try {
  const response = await window.clover_aptos.signMessage({
    message,
    nonce,
  });
  const { publicKey } = await window.clover_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);
}

Last updated