Solana
The Solana part carries out the practice using @solana/web3.js. Please prepare by installing the package.
Create Signed transaction
For a signed transaction, there are three essential steps.
- Create a raw transaction first.
- Make a raw transaction signature.
- Convert a raw transaction into a signed transaction by adding a signature.
1. getSolanaTx
Transaction and signature are needed. We first develop a getSolanaTx function to generate raw transaction because it is necessary to have a raw transaction to receive a signature via kms.
import { Solana } from '@dsrv/kms';
import { Account, CHAIN } from '@dsrv/kms/src/types';
import {
  Connection,
  SystemProgram,
  PublicKey,
  LAMPORTS_PER_SOL,
  Transaction,
  Keypair,
} from '@solana/web3.js';
import { base58 } from 'ethers/lib/utils';
interface RawTransaction {
  unSignedTx: Transaction;
  serializedTx: string;
}
export const getSolanaTx = async (mnemonic: string): Promise<RawTransaction> => {
  /* 1. get signer */
  const privateKey = Solana.getPrivateKey({
    mnemonic,
    path: { type: CHAIN.SOLANA, account: 0, index: 0 },
  });
  const signer = Keypair.fromSecretKey(base58.decode(privateKey));
  /* 2. make raw transaction */
  const connection = new Connection('https://api.devnet.solana.com', 'confirmed'); //allthatnode
  const toAccountPubKey = new PublicKey('BnBydTNPrTwDz4ZSkhJiGiSZwakPQFVeN8rgdAS2Yc7F'); //allthatnode
  const RecentBlockHash = await connection.getLatestBlockhash();
  const transaction = new Transaction({
    /* new blockHash */
    blockhash: RecentBlockHash.blockhash,
    lastValidBlockHeight: RecentBlockHash.lastValidBlockHeight,
    feePayer: signer.publicKey,
  });
  transaction.add(
    SystemProgram.transfer({
      fromPubkey: signer.publicKey,
      lamports: Number(0.1) * LAMPORTS_PER_SOL,
      toPubkey: toAccountPubKey,
    }),
  );
  return {
    serializedTx: `0x${transaction.compileMessage().serialize().toString('hex')}`,
    unSignedTx: transaction,
  };
};
2. getSolanaSignature
We then develop a method called getSolanaSignature that produces a signature by using serializedTx as a factor in order to gain a signature for the transaction.
import { CHAIN } from '@dsrv/kms/lib/types';
import { Solana } from '@dsrv/kms/lib/blockchains/solana';
export const getSolanaSignature = (serializedTx: string): string => {
  const { signature } = Solana.signTx(
    {
      mnemonic,
      path: { type: CHAIN.SOLANA, account: 0, index: 0 },
    },
    serializedTx,
  );
  return signature;
};
3. createSolanaSignedTx
Finally, we develop the createSolanaSignedTx function, which takes an unsignedTx and a signature generated earlier and returns a signed transaction.
import { Transaction } from '@solana/web3.js';
interface createSolanaSignedTxProps {
  unSignedTx: UnsignedTransaction;
  signature: string;
}
/* create singedTx by combining tx and signature */
export const createSolanaSignedTx = ({
  unSignedTx,
  signature,
}: createSolanaSignedTxProps): string => {
  const bufferSig = Buffer.from(signature.replace('0x', ''), 'hex');
  unSignedTx.addSignature(unSignedTx.feePayer, bufferSig);
  const serializedTx = unSignedTx.serialize().toString('hex');
  return serializedTx;
};
Finally, you can construct a getSolanaSignedTx function that returns a signed transaction by combining the functions you made before, getSolanaTx, getSolanaSignature, and createSolanaSignedTx.
export const getSolanaSignedTx = async (mnemonic: string) => {
  /* 1. get rawTransaction */
  const { serializedTx, unSignedTx } = await getSolanaTx(mnemonic);
  /* 2. get signature */
  const solanaSignature = getSolanaSignature(serializedTx);
  /* 3. create singedTx by combining rawTransaction and signature */
  const solanaSignedTx = createSolanaSignedTx({
    unSignedTx,
    signature: solanaSignature,
  });
  return solanaSignedTx;
};
Send Signed transaction
You can transmit the transaction using a signed transaction you've prepared.
import { Transaction } from '@solana/web3.js';
export const sendSolanaTransaction = async (serializedTx: string): Promise<Transaction> => {
  const transaction = Transaction.from(Buffer.from(serializedTx, 'hex'));
  const rpcUrl = 'https://api.devnet.solana.com';
  const result = await fetch(rpcUrl, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      jsonrpc: '2.0',
      method: 'sendTransaction',
      params: [
        transaction.serialize().toString('base64'),
        { preflightCommitment: 'confirmed', encoding: 'base64' },
      ],
      id: 999,
    }),
  });
  const resultJson = await result.json();
  return resultJson.result;
};
const mnemonic = 'sample mnemonic';
const main = async () => {
  const solanaSignedTx = await getSolanaSignedTx(mnemonic);
  const solanaTxResult = await sendSolanaTransaction(solanaSignedTx);
  console.log('solana Tx Result : ', solanaTxResult);
};
main();
Examples
To complete the transaction, follow the steps outlined below. A faucet is required to transmit a transaction. You can request faucet through the FAUCET tab in the wallet.
The loss of all cryptocurrency holdings is possible if mnemonic is revealed. To execute the following example, use a test or development mnemonic.