Skip to content

Commit

Permalink
✅ done
Browse files Browse the repository at this point in the history
  • Loading branch information
AlaaZorkane committed Jan 7, 2025
0 parents commit 1258114
Show file tree
Hide file tree
Showing 12 changed files with 546 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/target
Cargo.lock
/keys
node_modules
26 changes: 26 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"editor.defaultFormatter": "biomejs.biome",
"editor.formatOnSave": true,
"[html]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[javascript]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[jsonc]": {
"editor.defaultFormatter": "biomejs.biome"
},
"[typescript]": {
"editor.codeActionsOnSave": {
"source.fixAll.biome": "explicit"
},
"editor.defaultFormatter": "biomejs.biome"
},
"[ignore]": {
"editor.defaultFormatter": "foxundermoon.shell-format"
},
"typescript.tsdk": "node_modules/typescript/lib"
}
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]

members = [
"programs/pinoccio",
]
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# pinoccio-challenge

To install dependencies:

```bash
bun install
```

To run:

```bash
bun run main.ts
```

This project was created using `bun init` in bun v1.1.38. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.
46 changes: 46 additions & 0 deletions biome.jsonc
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.3/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false,
"ignore": []
},
"formatter": {
"enabled": true,
"indentStyle": "space"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"all": true,
"correctness": {
"noUndeclaredDependencies": "off"
},
"style": {
"noNamespaceImport": "off"
},
"performance": {
"noBarrelFile": "off",
"noReExportAll": "off"
},
"suspicious": {
"noConsole": "off",
"noConsoleLog": "off"
}
}
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"indentStyle": "space"
},
"globals": ["Deno"]
}
}
Binary file added bun.lockb
Binary file not shown.
165 changes: 165 additions & 0 deletions main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import {
AccountRole,
setTransactionMessageLifetimeUsingBlockhash,
address,
type IInstruction,
signTransactionMessageWithSigners,
sendAndConfirmTransactionFactory,
appendTransactionMessageInstruction,
setTransactionMessageFeePayerSigner,
airdropFactory,
createSolanaRpc,
createSolanaRpcSubscriptions,
createTransactionMessage,
devnet,
generateKeyPairSigner,
lamports,
pipe,
getSignatureFromTransaction,
createAddressWithSeed,
getU64Codec,
} from "@solana/web3.js";
import {
getCreateAccountWithSeedInstruction,
SYSTEM_PROGRAM_ADDRESS,
isSystemError,
getSystemErrorMessage,
} from "@solana-program/system";
import { createLogger, printHonestJohn } from "./utils.ts";

printHonestJohn();
const log = createLogger("honest");

const rpc = createSolanaRpc(devnet("http://localhost:8899"));
const rpcSubscriptions = createSolanaRpcSubscriptions(
devnet("ws://localhost:8900"),
);
const sendAndConfirm = sendAndConfirmTransactionFactory({
rpc,
rpcSubscriptions,
});

const PINOCCIO_PROGRAM_ID = address(
"pinF7d2a3wfBtq5cmys6nq8F8KCKVwd7EGdZxF51P6z",
);

const HONEST_JOHN = address("honEst1111111111111111111111111111111111111");
const signer = await generateKeyPairSigner();
const signerPk = signer.address;

log.info("signer: %s", signerPk);

// Airdrop
const airdrop = airdropFactory({ rpc, rpcSubscriptions });
const airdroptx = await airdrop({
commitment: "confirmed",
recipientAddress: signerPk,
lamports: lamports(100_000_000_000n),
});
log.info("airdrop tx: %s", airdroptx);

// Create a transaction
const { value: latestBlockhash } = await rpc
.getLatestBlockhash({
commitment: "confirmed",
})
.send();
log.info("latestBlockhash: %s", latestBlockhash.blockhash);

const codec = getU64Codec();
// check excalidraw to know where 1293 came from
log.info("answer: %d", 1293);
const answer = codec.encode(1293) as Uint8Array;

const seed = "rating";
const space = 11n * 8n + 1n;
const pda = await createAddressWithSeed({
baseAddress: signerPk,
programAddress: PINOCCIO_PROGRAM_ID,
seed,
});

log.info("pda: %s", pda);

const minPdaExempt = await rpc.getMinimumBalanceForRentExemption(space).send();

const createPdaInstruction = getCreateAccountWithSeedInstruction({
base: signerPk,
seed,
space,
newAccount: pda,
amount: minPdaExempt,
baseAccount: signer,
payer: signer,
programAddress: PINOCCIO_PROGRAM_ID,
});

/**
* account[0] = program account
* account[1] = honest john
* account[2] = system program
* account[3] = signer/receiver
*/
const pinoInstruction: IInstruction = {
programAddress: PINOCCIO_PROGRAM_ID,
data: answer,
accounts: [
{
address: pda,
role: AccountRole.WRITABLE,
},
{
address: HONEST_JOHN,
role: AccountRole.WRITABLE,
},
{
address: address(SYSTEM_PROGRAM_ADDRESS),
role: AccountRole.READONLY,
},
{
address: signerPk,
role: AccountRole.WRITABLE_SIGNER,
},
],
};

const txMsg = pipe(
createTransactionMessage({
version: 0,
}),
(tx) => {
log.info("[1] setting transaction fee payer signer");
return setTransactionMessageFeePayerSigner(signer, tx);
},
(tx) => {
log.info("[2] setting transaction lifetime using blockhash");
return setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx);
},
(tx) => {
log.info("[3] appending create pda instruction");
return appendTransactionMessageInstruction(createPdaInstruction, tx);
},
(tx) => {
log.info("[4] appending pinocchio instruction");
return appendTransactionMessageInstruction(pinoInstruction, tx);
},
);

const signedTx = await signTransactionMessageWithSigners(txMsg);

try {
const tx = getSignatureFromTransaction(signedTx);
log.info("pinocchio tx: %s", tx);
await sendAndConfirm(signedTx, {
commitment: "confirmed",
skipPreflight: true,
});
log.info("done!");
} catch (error) {
if (isSystemError(error, txMsg)) {
const msg = getSystemErrorMessage(error.context.code);
log.error(msg, "error:");
} else {
log.error(error, "unknown error:");
}
}
26 changes: 26 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@alaazorkane/honestjohn",
"module": "main.ts",
"type": "module",
"scripts": {
"start": "bun run main.ts",
"tsc": "tsc"
},
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.6.3"
},
"dependencies": {
"@inquirer/core": "^10.1.2",
"@solana-program/system": "0.6.2",
"@solana/web3.js": "^2.0.0",
"pino": "^9.6.0",
"pino-pretty": "^13.0.0",
"yoctocolors": "^2.1.1"
},
"exports": {
".": "./app/main.ts"
}
}
12 changes: 12 additions & 0 deletions programs/pinoccio/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "challenge"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib", "lib"]

[dependencies]
pinocchio = "0.6.0"
pinocchio-pubkey = "0.2.1"
pinocchio-system = "0.2.0"
Loading

0 comments on commit 1258114

Please sign in to comment.