Local Connector

Connect to Tonhub when your app is running as extension

TonhubLocalConnector allows you to connect get information about a wallet and request transactions and signatures when running as an extension.

Check if app is running as extension

Before trying to work with a wallet it is useful to check if web app is running as extension.

let isExtension: boolean = TonhubLocalConnector.isAvailable();

Create connector

After you checked that connector is available it is possible to create one:

let connector = new TonhubLocalConnector('sandbox'); // change to 'mainnet' for mainnet

Get Wallet and App Information

connector has config field with useful fields about the current environment and wallet.

let config: { 
  version: number;
  network: 'sandbox' | 'mainnet';
  address: string;
  publicKey: string;
  walletConfig: string;
  walletType: string;
  signature: string;
  time: number;
  subkey: {
    domain: string;
    publicKey: string;
    time: number;
    signature: string;
	};
} = connector.config;

Verify wallet on backend

You can check signed wallet config on backend using TonhubLocalConnector.verifyWalletConfig. config is cryptographically signed and you can safely use it as authentication proof without the need to sign something.

// NOTE: Not every field from config present here, you can safely ignore the rest of a config for validation purposes.
config: { 
	address: string;
  walletConfig: string;
  walletType: string;
  time: number;
  signature: string;
  subkey: {
  	domain: string;
    publicKey: string;
    time: number;
    signature: string;
  };
} = connector.config;

const valid = TonhubLocalConnector.verifyWalletConfig(config);

Requesting a transaction

To request a transaction you can call requestTransaction:

const request: TonhubLocalTransactionRequest = {
    to: 'EQCkR1cGmnsE45N4K0otPl5EnxnRakmGqeJUNua5fkWhales', // Destination
    value: '10000000000', // Amount in nano-tons
    stateInit: '....', // Optional serialized to base64 string state_init cell
    text: 'Hello world', // Optional comment. If no payload specified - sends actual content, if payload is provided this text is used as UI-only hint
    payload: '....' // Optional serialized to base64 string payload cell
};
const response: TonhubLocalTransactionResponse = await connector.requestTransaction(request);
if (response.type === 'rejected') {
    // Handle rejection
} else if (response.type === 'success') {
    // Handle successful transaction
    const externalMessage = response.response; // Signed body of external message that was sent to the network
} else {
    throw new Error('Impossible');
}

Requesting a signature

const payloadToSign = Buffer.concat([Buffer.from([0, 0, 0, 0]), Buffer.from('Some random string')]);
const payload = beginCell()
    .storeBuffer(payloadToSign)
    .endCell()
    .toBoc({idx:false})
    .toString('base64');
const text = 'Please, sign our terms or service and privacy policy';

// Request body
const request: TonhubLocalSignRequest = {
    text: 'Hello world', // Text to sign, presented to the user.
    payload: payload // Optional serialized to base64 string payload cell
};
const response: TonhubLocalSignResponse = await connector.requestSign(request);
if (response.type === 'rejected') {
    // Handle rejection
} else if (response.type === 'success') {
    // Handle successful transaction
    const signature = response.signature;

    // You can check signature on the backend with TonhubConnector.verifySignatureResponse
    let correctSignature = TonhubConnector.verifySignatureResponse({ signature: signature, config: walletConfig });
} else {
    throw new Error('Impossible');
}