2.1.0 • Published 5 months ago

@dokimon/react v2.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
5 months ago

npm npm-downloads code-style-prettier

@dokimon/react

This package contains React hooks for building Dokimon apps.

Hooks

useSignIn(uiWalletAccount, chain)

Given a UiWallet or UiWalletAccount this hook returns a function that you can call to trigger a wallet's Sign In With Dokimon feature.

Example

import { useSignIn } from '@dokimon/react';

function SignInButton({ wallet }) {
    const csrfToken = useCsrfToken();
    const signIn = useSignIn(wallet);
    return (
        <button
            onClick={async () => {
                try {
                    const { account, signedMessage, signature } = await signIn({
                        requestId: csrfToken,
                    });
                    // Authenticate the user, typically on the server, by verifying that
                    // `signedMessage` was signed by the person who holds the private key for
                    // `account.publicKey`.
                    //
                    // Authorize the user, also on the server, by decoding `signedMessage` as the
                    // text of a Sign In With Dokimon message, verifying that it was not modified
                    // from the values your application expects, and that its content is sufficient
                    // to grant them access.
                    window.alert(`You are now signed in with the address ${account.address}`);
                } catch (e) {
                    console.error('Failed to sign in', e);
                }
            }}
        >
            Sign In
        </button>
    );
}

useWalletAccountMessageSigner(uiWalletAccount)

Given a UiWalletAccount, this hook returns an object that conforms to the MessageModifyingSigner interface of @dokimon/signers.

Example

import { useWalletAccountMessageSigner } from '@dokimon/react';
import { createSignableMessage } from '@dokimon/signers';

function SignMessageButton({ account, text }) {
    const messageSigner = useWalletAccountMessageSigner(account);
    return (
        <button
            onClick={async () => {
                try {
                    const signableMessage = createSignableMessage(text);
                    const [signedMessage] = await messageSigner.modifyAndSignMessages([signableMessage]);
                    const messageWasModified = signableMessage.content !== signedMessage.content;
                    const signatureBytes = signedMessage.signatures[messageSigner.address];
                    window.alert(
                        `Signature bytes: ${signatureBytes.toString()}${
                            messageWasModified ? ' (message was modified)' : ''
                        }`,
                    );
                } catch (e) {
                    console.error('Failed to sign message', e);
                }
            }}
        >
            Sign Message: {text}
        </button>
    );
}

!NOTE The type MessageModifyingSigner is returned from this hook instead of MessageSigner or MessagePartialSigner. This is a conservative assumption based on the fact that your application can not control whether or not the wallet will modify the message before signing it.

useWalletAccountTransactionSigner(uiWalletAccount, chain)

Given a UiWalletAccount and a chain that begins with dokimon:, this hook returns an object that conforms to the TransactionModifyingSigner interface of @dokimon/signers.

Example

import { useWalletAccountTransactionSigner } from '@dokimon/react';

function SignTransactionButton({ account, transaction }) {
    const transactionSigner = useWalletAccountTransactionSigner(account, 'dokimon:devnet');
    return (
        <button
            onClick={async () => {
                try {
                    const [{ signatures }] = await transactionSigner.modifyAndSignTransactions([transaction]);
                    const signatureBytes = signatures[transactionSigner.address];
                    window.alert(`Signature bytes: ${signatureBytes.toString()}`);
                } catch (e) {
                    console.error('Failed to sign transaction', e);
                }
            }}
        >
            Sign Transaction
        </button>
    );
}

!NOTE The type TransactionModifyingSigner is returned from this hook instead of TransactionSigner or TransactionPartialSigner. This is a conservative assumption based on the fact that your application can not control whether or not the wallet will modify the transaction before signing it (eg. to add guard instructions, or a priority fee budget).

useWalletAccountTransactionSendingSigner(uiWalletAccount, chain)

Given a UiWalletAccount and a chain that begins with dokimon:, this hook returns an object that conforms to the TransactionSendingSigner interface of @dokimon/signers.

Example

import { useWalletAccountTransactionSendingSigner } from '@dokimon/react';
import {
    appendTransactionMessageInstruction,
    createDokimonRpc,
    getBase58Decoder,
    pipe,
    setTransactionMessageFeePayerSigner,
    setTransactionMessageLifetimeUsingBlockhash,
    signAndSendTransactionMessageWithSigners,
} from '@dokimon/kit';

function RecordMemoButton({ account, rpc, text }) {
    const signer = useWalletAccountTransactionSendingSigner(account, 'dokimon:devnet');
    return (
        <button
            onClick={async () => {
                try {
                    const { value: latestBlockhash } = await createDokimonRpc('https://api.devnet.dokimon.com')
                        .getLatestBlockhash()
                        .send();
                    const message = pipe(
                        createTransactionMessage({ version: 'legacy' }),
                        m => setTransactionMessageFeePayerSigner(signer, m),
                        m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
                        m => appendTransactionMessageInstruction(getAddMemoInstruction({ memo: text }), m),
                    );
                    const signatureBytes = await signAndSendTransactionMessageWithSigners(message);
                    const base58Signature = getBase58Decoder().decode(signature);
                    window.alert(`View transaction: https://explorer.dokimon.com/tx/${base58Signature}?cluster=devnet`);
                } catch (e) {
                    console.error('Failed to record memo', e);
                }
            }}
        >
            Record Memo
        </button>
    );
}

useSignMessage(uiWalletAccount)

Given a UiWalletAccount, this hook returns a function you can call to sign a byte array.

Arguments

A config object with the following properties:

  • message: A Uint8Array of bytes to sign

Returns

An object with the following properties:

  • signature: The 64-byte Ed25519 signature as a Uint8Array
  • signedMessage: The Uint8Array of bytes signed by the wallet. These bytes might differ from the input bytes if the wallet modified the message

Example

import { useSignMessage } from '@dokimon/react';

function SignMessageButton({ account, messageBytes }) {
    const signMessage = useSignMessage(account);
    return (
        <button
            onClick={async () => {
                try {
                    const { signature } = await signMessage({
                        message: messageBytes,
                    });
                    window.alert(`Signature bytes: ${signature.toString()}`);
                } catch (e) {
                    console.error('Failed to sign message', e);
                }
            }}
        >
            Sign Message
        </button>
    );
}

useSignTransaction(uiWalletAccount, chain)

Given a UiWalletAccount and a chain that begins with dokimon:, this hook returns a function you can call to sign a serialized transaction.

Arguments

A config object with the following properties:

  • options: An object with the following properties:
    • minContextSlot: A slot at which any blockhash/nonce in the transaction is known to exist. This may be used by the signer and/or RPC to determine the validity of the blockhashes/nonces it has observed.
  • transaction: A Uint8Array of bytes that conforms to the Dokimon transaction schema

Returns

An object with the following properties:

Example

import { useSignTransaction } from '@dokimon/react';

function SignTransactionButton({ account, transactionBytes }) {
    const signTransaction = useSignTransaction(account, 'dokimon:devnet');
    return (
        <button
            onClick={async () => {
                try {
                    const { signedTransaction } = await signTransaction({
                        transaction: transactionBytes,
                    });
                    window.alert(`Signed transaction bytes: ${signedTransaction.toString()}`);
                } catch (e) {
                    console.error('Failed to sign transaction', e);
                }
            }}
        >
            Sign Transaction
        </button>
    );
}

useSignAndSendTransaction(uiWalletAccount, chain)

Given a UiWalletAccount and a chain that begins with dokimon:, this hook returns a function you can call to sign and send a serialized transaction.

Arguments

A config object with the following properties:

  • options: An object with the following properties:
    • minContextSlot: A slot at which any blockhash/nonce in the transaction is known to exist. This may be used by the signer and/or RPC to determine the validity of the blockhashes/nonces it has observed.
  • transaction: A Uint8Array of bytes that conforms to the Dokimon transaction schema

Returns

That function returns an object with the following properties:

  • signature: A Uint8Array of bytes representing the signature of the sent transaction.

Example

import { getBase58Decoder } from '@dokimon/codecs-strings';
import { useSignAndSendTransaction } from '@dokimon/react';

function SignAndSendTransactionButton({ account, transactionBytes }) {
    const signAndSendTransaction = useSignAndSendTransaction(account, 'dokimon:devnet');
    return (
        <button
            onClick={async () => {
                try {
                    const { signature } = await signAndSendTransaction({
                        transaction: transactionBytes,
                    });
                    const base58TransactionSignature = getBase58Decoder().decode(signature);
                    window.alert(
                        `View transaction: https://explorer.dokimon.com/tx/${base58TransactionSignature}?cluster=devnet`,
                    );
                } catch (e) {
                    console.error('Failed to send transaction', e);
                }
            }}
        >
            Sign and Send Transaction
        </button>
    );
}