The following program initialises a pda on chain through a CPI

Ref - https://github.com/100xdevs-cohort-3/cpis-on-pdas/blob/main/contract/src/lib.rs

use solana_program::{
    account_info::{next_account_info, AccountInfo},
    entrypoint,
    entrypoint::ProgramResult,
    msg,
    program::invoke_signed,
    pubkey::Pubkey,
    system_instruction::create_account,
    system_program::ID as SYSTEM_PROGRAM_ID,
};

entrypoint!(process_instruction);

pub fn process_instruction(
    program_id: &Pubkey,
    accounts: &[AccountInfo],
    _instruction_data: &[u8],
) -> ProgramResult {
    let iter = &mut accounts.iter();
    let payer_account = next_account_info(iter)?;
    let pda_account = next_account_info(iter)?;
    let payer_pubkey = payer_account.key;
    let system_program = next_account_info(iter)?;

    let (pda, bump) = Pubkey::find_program_address(
        &[b"client1", payer_pubkey.as_ref()],
        &program_id,
    );

    let ix = create_account(
        &payer_account.key,
        &pda,
        1000000000,
        4,
        &program_id,
    );
    let signer_seeds = &[b"client1", payer_pubkey.as_ref(), &[bump]];

    invoke_signed(&ix, accounts, &[signer_seeds])?;

    Ok(())
}

Tests

Ref - https://github.com/100xdevs-cohort-3/cpis-on-pdas/blob/main/contract/client/index.test.ts

import { test, expect, beforeAll, describe } from "bun:test";
import { LiteSVM } from "litesvm";
import { Keypair, PublicKey, SystemProgram, Transaction, TransactionInstruction, } from "@solana/web3.js";

describe("Create pda from client", () => {
  let liveSvm: LiteSVM;
  let pda: PublicKey;
  let bump: number;
  let programId: PublicKey;
  let payer: Keypair;

  beforeAll(() => {
    liveSvm = new LiteSVM();
    programId = PublicKey.unique();
    payer = Keypair.generate();
    liveSvm.addProgramFromFile(programId, "./contract.so");
    liveSvm.airdrop(payer.publicKey, BigInt(100000000000));
    [pda, bump] = PublicKey.findProgramAddressSync([Buffer.from("client1"), payer.publicKey.toBuffer()], programId);
    
    let ix = new TransactionInstruction({
      keys: [
        {
          pubkey: payer.publicKey,
          isSigner: true,
          isWritable: true,
        },
        {
          pubkey: pda,
          isSigner: false,
          isWritable: true,
        },
        {
          pubkey: SystemProgram.programId,
          isSigner: false,
          isWritable: false,
        }
      ],
      programId,
      data: Buffer.from("")
    });

    const tx = new Transaction().add(ix);
    tx.feePayer = payer.publicKey;
    tx.recentBlockhash = liveSvm.latestBlockhash();
    tx.sign(payer);
    let res = liveSvm.sendTransaction(tx);
    console.log(res.toString())
  });

  test("should create pda", () => {
    const balance = liveSvm.getBalance(pda);
    console.log(balance)
    expect(Number(balance)).toBeGreaterThan(0);
    expect(Number(balance)).toBe(1000000000);
  });
  
});