Skip to content
This repository has been archived by the owner on Jan 24, 2025. It is now read-only.

[cookbook] create pda with web3js v2 #626

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/label-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ solved:
# Close the discussion
close: true
# Set a close reason
close-reason: 'resolved'
close-reason: "resolved"
# Lock the discussion
lock: true
lock: true
161 changes: 98 additions & 63 deletions content/cookbook/accounts/create-pda-account.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,31 @@ Accounts found at Program Derived Addresses (PDAs) can only be created on-chain.
The accounts have addresses that have an associated off-curve public key, but no
secret key.

To generate a PDA, use `findProgramAddressSync` with your required seeds.
## Generating a PDA

<Tabs groupId="language" items={['web3.js v2', 'web3.js v1']}>

To generate a PDA, use `getProgramDerivedAddress` with your required seeds.
Generating with the same seeds will always generate the same PDA.

## Generating a PDA
<Tab value="web3.js v2">

```typescript filename="generate-pda.ts"
import { getProgramDerivedAddress, address } from "@solana/web3.js";

const [pda, bump] = await getProgramDerivedAddress({
programAddress: address("G1DCNUQTSGHehwdLCAmRyAG8hf51eCHrLNUqkgGKYASj"),
seeds: ["test"],
});
console.log(`bump: ${bump}, address: ${pda}`);
```

</Tab>

<Tab value="web3.js v1">

To generate a PDA, use `findProgramAddressSync` with your required seeds.
Generating with the same seeds will always generate the same PDA.

```typescript filename="generate-pda.ts"
import { PublicKey } from "@solana/web3.js";
Expand All @@ -25,14 +46,16 @@ let [pda, bump] = PublicKey.findProgramAddressSync(
[Buffer.from("test")],
programId,
);
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`);
console.log(`bump: ${bump}, address: ${pda.toBase58()}`);
// you will find the result is different from `createProgramAddress`.
// It is expected because the real seed we used to calculate is ["test" + bump]
```

## Create an Account at a PDA
</Tab>

### Program
</Tabs>

## Create a PDA Account in a Program (via CPI)

```rust filename="create-pda.rs" {24-37}
use solana_program::{
Expand Down Expand Up @@ -77,7 +100,19 @@ fn process_instruction(
}
```

## Client
## Create a PDA Account in a Client

<Tabs groupId="language" items={['web3.js v2', 'web3.js v1']}>

<Tab value="web3.js v2">

```typescript filename="create-pda.ts"

```

</Tab>

<Tab value="web3.js v1">

```typescript filename="create-pda.ts"
import {
Expand All @@ -92,61 +127,61 @@ import {
SYSVAR_RENT_PUBKEY,
} from "@solana/web3.js";

(async () => {
// program id
const programId = new PublicKey(
"7ZP42kRwUQ2zgbqXoaXzAFaiQnDyp6swNktTSv8mNQGN",
);

// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

// setup fee payer
const feePayer = Keypair.generate();
const feePayerAirdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
LAMPORTS_PER_SOL,
);
await connection.confirmTransaction(feePayerAirdropSignature);

// setup pda
let [pda, bump] = await PublicKey.findProgramAddress(
[feePayer.publicKey.toBuffer()],
programId,
);
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`);

const data_size = 0;

let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: feePayer.publicKey,
isSigner: true,
isWritable: true,
},
{
pubkey: pda,
isSigner: false,
isWritable: true,
},
{
pubkey: SYSVAR_RENT_PUBKEY,
isSigner: false,
isWritable: false,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([data_size, bump])),
programId: programId,
}),
);

console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
})();
// program id
const programId = new PublicKey("7ZP42kRwUQ2zgbqXoaXzAFaiQnDyp6swNktTSv8mNQGN");

// connection
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");

// setup fee payer
const feePayer = Keypair.generate();
const feePayerAirdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
LAMPORTS_PER_SOL,
);
await connection.confirmTransaction(feePayerAirdropSignature);

// setup pda
let [pda, bump] = await PublicKey.findProgramAddress(
[feePayer.publicKey.toBuffer()],
programId,
);
console.log(`bump: ${bump}, pubkey: ${pda.toBase58()}`);

const data_size = 0;

let tx = new Transaction().add(
new TransactionInstruction({
keys: [
{
pubkey: feePayer.publicKey,
isSigner: true,
isWritable: true,
},
{
pubkey: pda,
isSigner: false,
isWritable: true,
},
{
pubkey: SYSVAR_RENT_PUBKEY,
isSigner: false,
isWritable: false,
},
{
pubkey: SystemProgram.programId,
isSigner: false,
isWritable: false,
},
],
data: Buffer.from(new Uint8Array([data_size, bump])),
programId: programId,
}),
);

console.log(`txhash: ${await connection.sendTransaction(tx, [feePayer])}`);
```

</Tab>

</Tabs>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
"ignore": "^5.3.1",
"lint-staged": "^15.2.7",
"mdast": "^3.0.0",
"prettier": "^3.2.4",
"prettier": "3.3.3",
"remark": "^15.0.1",
"remark-frontmatter": "^5.0.0",
"remark-parse": "^11.0.0",
Expand Down
12 changes: 6 additions & 6 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,20 @@
"paths": {
"contentlayer/generated": ["./.contentlayer/generated"],
"@/*": ["./src/*"],
"@@/*": ["./*"],
"@@/*": ["./*"]
},
"plugins": [
{
"name": "next",
},
],
"name": "next"
}
]
},
"include": [
".contentlayer/generated",
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/types/**/*.ts"
],
"exclude": ["node_modules", "code"],
"exclude": ["node_modules", "code"]
}