Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update verifiable randomness functions.md #474

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
d0a7af7
fix: typo with getMaxShredInsertSlot link (#540)
Andross96 Sep 30, 2024
e715eed
Fix a single typo (#516)
shawazi Sep 30, 2024
c45d286
Prettier
mikemaccana Sep 30, 2024
24f3789
Intro to solana content (#472)
krishnendu-2003 Sep 30, 2024
5d9e505
[docs/rpc] fix: required field on `getTokenAccountsByOwner` (#543)
nickfrosty Sep 30, 2024
46d25c8
Program security - Bump seed canonicalization lesson updated (#446)
0xCipherCoder Oct 1, 2024
b7bfff7
Fix inconsistency in intro-to-custom-onchain-programs.md (#544)
Neeraj138 Oct 1, 2024
52fe397
Updated fromPubkey to use PublicKey in the transfer instruction (#542)
husna3249 Oct 1, 2024
632e22f
fix typo (#548)
akuzni2 Oct 2, 2024
553e641
Add sol4k to the client-side development section (#547)
Shpota Oct 2, 2024
9040e11
Fix typo: Change "species" to "specifies" in documentation (#519)
davik20 Oct 2, 2024
08ca666
Prettier
mikemaccana Oct 2, 2024
65c587f
Remove deprecation warnings that are now fixed
mikemaccana Oct 2, 2024
028bb88
Mobile Development: Update the docs + code of Solana Mobile Dapps wit…
XuananLe Oct 2, 2024
4f396bd
Tokens NFTs - Updated Token Program Advanced lesson (#512)
0xCipherCoder Oct 2, 2024
de6aad4
Native onchain development - Updated program security lesson (#452)
0xCipherCoder Oct 2, 2024
503e4f5
Update Lookup Tables (LUTs) course (#476)
darkvallen Oct 2, 2024
0393176
Prettier.
mikemaccana Oct 2, 2024
bbefafd
feat: update compressed-nfts.md to use umi and bubblegum plugin (#510)
jim4067 Oct 3, 2024
74d5046
Fix headline missed in PR
mikemaccana Oct 3, 2024
4759785
Fix minor typos
mikemaccana Oct 3, 2024
c5b6d3b
More minor typos
mikemaccana Oct 3, 2024
0e1322f
Update old links
mikemaccana Oct 3, 2024
f4526e3
Add Anchor section to docs (#428)
ZYJLiu Oct 3, 2024
c4ae2b6
Updated Intro to solana mobile (#478)
dvrvsimi Oct 4, 2024
47aa749
fix basis points comment (#550)
brittcyr Oct 4, 2024
409f2c3
Native onchain development - Updated cross program invocation lesson …
0xCipherCoder Oct 4, 2024
5f05832
onchain-development intro-to-anchor updated (#349)
SAMAD101 Oct 4, 2024
217191a
Program Optimization - Updated Program Architecture lesson (#485)
0xCipherCoder Oct 4, 2024
3124054
Prettier
mikemaccana Oct 4, 2024
b4344da
Add TODO
mikemaccana Oct 4, 2024
fb7fc6b
fix and improve close-mint course (#536)
wuuer Oct 4, 2024
fe8ff3f
Program security - Account data matching lesson updated (#440)
0xCipherCoder Oct 4, 2024
2e20947
Update solana pay content (#345)
DogukanGun Oct 4, 2024
3e489e7
Generalized state compression (#470)
danielAsaboro Oct 4, 2024
dba1f1f
Added argument checks - for better error display. (#475)
mercy-wumi Oct 7, 2024
e64ddc5
Remove remaining hidden lessons as lessons are now updated
mikemaccana Oct 7, 2024
d7c0d94
Fix a typo for the 'delete' instruction (#551)
sepine Oct 7, 2024
25244ea
Update installation.md (#552)
0xmigi Oct 7, 2024
f6ad0e3
fix and improve token-program course (#534)
wuuer Oct 9, 2024
8b9a92d
Fix broken links and terminology in mwa-deep-dive.md (#554)
Mikerniker Oct 10, 2024
00b1aea
Updated Intro to Solana mobile lesson pictures (#549)
dvrvsimi Oct 10, 2024
361ac23
Update intro-to-anchor.md (#553)
1KitCat1 Oct 10, 2024
4c7f302
Docs missing redirects (#556)
nickfrosty Oct 11, 2024
f0dae36
Code Import (#256)
heyAyushh Oct 11, 2024
b368f1a
fix: exclude code dir (#557)
nickfrosty Oct 11, 2024
34b10db
Added styles in interact-with-wallet.md for wallet ui (#559)
shivaji43 Oct 13, 2024
fe1cde0
Fix typo in program-derived-address.md (#558)
sdmg15 Oct 13, 2024
8eec193
Fix broken links in solana-mobile-dapps-with-expo.md (#555)
Mikerniker Oct 13, 2024
ee97678
Remove deprecated reference to nonexistent VSCode Grammarly extension…
shawazi Oct 13, 2024
eb7413f
redundant (#563)
anjor Oct 15, 2024
345f1a3
fixing useMemo and balance in SOL (#562)
shivaji43 Oct 15, 2024
0cf3a0f
Add back lang-rust, limitation, faq pages under programs section (#567)
ZYJLiu Oct 16, 2024
4b74e51
Remove Rust 1.79.0 section from Anchor installation (#568)
acheroncrypto Oct 17, 2024
a37cb2c
Update full-stack-solana-development.md (#566)
0xmigi Oct 17, 2024
3b5b390
Add solana4j (open sourced by LMAX) to the list of client-side java s…
ml-james Oct 17, 2024
577415e
Update fees.md (#564)
merlucy Oct 17, 2024
ac25295
Fix backticks
mikemaccana Oct 17, 2024
cc35c3f
fix:removed dead link
adpthegreat Sep 9, 2024
ef4bdd9
fix:updated dep
adpthegreat Sep 9, 2024
47051c1
- Renamed escrowState to Escrow in the ts tests -
adpthegreat Sep 10, 2024
caa57d5
feat:formatted with prettier
adpthegreat Sep 10, 2024
e407b0a
fix:updated command in Program setup fro anchor keys list to anchor k…
adpthegreat Sep 10, 2024
a5f7f2a
- Updated assertions comparing numbers in tests to use .eq() method i…
adpthegreat Sep 12, 2024
0874b81
fix:prettier
adpthegreat Sep 12, 2024
ea61149
-Changed switchbo…
adpthegreat Sep 12, 2024
5149f9b
- Renamed solana to SOL
adpthegreat Sep 18, 2024
42555e8
ran grammarly , edited language to be clearer
adpthegreat Oct 14, 2024
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
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,12 @@ package-lock.json
# translations are stored in the `i18n` via crowdin
i18n


# code-import
code/node_modules
code/package-lock.json
code/yarn.lock
code/pnpm-lock.yaml

# vscode configuration
.vscode
.vscode
1 change: 1 addition & 0 deletions .husky/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
_
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
55 changes: 51 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ transparent as possible, whether it's:
- publicly displayed via the UI of [solana.com](https://solana.com) (located in
a different repo)
- content translations are supported via Crowdin
- code blocks must use code-import for file snippets (via filesystem)
- code file should be [tests](https://nodejs.org/api/test.html) and should add
code ranges instead of whole test file

## Style guidelines

Expand All @@ -45,9 +48,7 @@ In particular:
and save the person reviewing your PR some time. We recommend
[Grammarly](https://grammarly.com/). In
[your Grammarly dictionary](https://account.grammarly.com/customize), you may
wish to add Solana-specific words like `lamport`, `blockhash`, etc. For VScode
users, there is a
[VScode extension for Grammarly](https://marketplace.visualstudio.com/items?itemName=znck.grammarly).
wish to add Solana-specific words like `lamport`, `blockhash`, etc.
- Use US English rather than British English. Grammarly will catch this for you.
- Use 'onchain' (not on-chain, definitely not smart contract) when referring to
onchain apps. This comes from the Solana Foundation style guide, and is
Expand Down Expand Up @@ -273,6 +274,52 @@ For images, you can use the path starting with `/public` like this:
> links will be automatically adjusted to function on the website. Including
> making the images viewable and removing `.md` file extensions.

### Code Blocks

In addition to standard markdown "fenced" code blocks (i.e. using triple
backticks), the developer content repo requires the use of code-import for file
snippets. This ensures that code examples are always up-to-date with the actual
source files.

#### Using code-import

To use code-import, follow these steps:

Ensure your code file is a test file located in the appropriate directory within
the repo. Use the following syntax to import code snippets:

```javascript file="/path/to/your/file.ts#L1-L10,#L15-L20"

```

This will import lines 1-10 and 15-20 from the specified file.

Always use code ranges instead of importing whole files. This helps keep
examples concise and focused.

#### Code-import Rules

- The file path must start with a forward slash (/).
- You can specify multiple line ranges, separated by commas.
- Line ranges should be in ascending order and not overlap.
- Invalid ranges (e.g., #L4-L3) are not allowed.
- Line numbers start at 1, so #L0 is invalid.
- Trailing commas in the range specification are not allowed.

Example of a valid code-import:

```javascript file="/code/cookbook/wallets/check-public-key.ts#L1-L2,#L3-L18"

```

Example of an invalid code-import:

```javascript file=/code/cookbook/wallets/check-public-key.ts#L1-L2,#L3-L19,#L1-L3

```

This is invalid because the ranges are not in ascending order and overlap.

### Table of contents

When a content page is rendered on solana.com, a table of contents will be
Expand Down Expand Up @@ -519,7 +566,7 @@ a list of available components
content
- [images](#images) - details about how to include images in a piece of content
- [code blocks](#code-blocks) - additional functionality on top of standard
markdown code blocks
markdown code blocks, these support code file import from filesystem
- [blockquote](#blockquote) - additional functionality on top of the standard
HTML `blockquote` element
- [Callout](#callout) - custom component used to render message to the reader in
Expand Down
19 changes: 19 additions & 0 deletions code/cookbook/wallets/check-public-key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { PublicKey } from "@solana/web3.js";

// Note that Keypair.generate() will always give a public key that is valid for users

// Valid public key
const key = new PublicKey("5oNDL3swdJJF1g9DzJiZ4ynHXgszjAEpUkxVYejchzrY");
// Lies on the ed25519 curve and is suitable for users
console.log(PublicKey.isOnCurve(key.toBytes()));

// Valid public key
const offCurveAddress = new PublicKey(
"4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e",
);

// Not on the ed25519 curve, therefore not suitable for users
console.log(PublicKey.isOnCurve(offCurveAddress.toBytes()));

// Not a valid public key
const errorPubkey = new PublicKey("testPubkey");
15 changes: 15 additions & 0 deletions code/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "code",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@solana/web3.js": "^1.95.2"
}
}
222 changes: 222 additions & 0 deletions coder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
import { promises as fs } from "node:fs";
import path from "node:path";
import os from "node:os";
import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkStringify from "remark-stringify";
import remarkFrontmatter from "remark-frontmatter";
import { visit } from "unist-util-visit";
import ignore, { type Ignore } from "ignore";
import importCode from "./src/utils/code-import";
import chokidar from "chokidar";

let debugMode = false;

const debug = (...args: string[]) => {
if (debugMode) {
console.log("[DEBUG]", ...args);
}
};

const hasCodeComponentWithFileMeta = async (
filePath: string,
): Promise<boolean> => {
const content = await fs.readFile(filePath, "utf8");
let hasMatch = false;

const tree = unified().use(remarkParse).use(remarkFrontmatter).parse(content);

visit(tree, "code", node => {
if (node.meta?.includes("file=")) {
hasMatch = true;
return false; // Stop visiting
}
});

return hasMatch;
};

const getIgnore = async (directory: string): Promise<Ignore> => {
const ig = ignore();

try {
const gitignoreContent = await fs.readFile(
path.join(directory, ".gitignore"),
"utf8",
);
ig.add(gitignoreContent);
// ignore all dotfiles
ig.add([".*"]);
// ignore CONTRIBUTING.md because it mentions the code component example
ig.add("CONTRIBUTING.md");
} catch (error) {
// If .gitignore doesn't exist, just continue without it
if ((error as NodeJS.ErrnoException).code !== "ENOENT") {
throw error;
}
}

return ig;
};

const getMarkdownAndMDXFiles = async (directory: string): Promise<string[]> => {
const ig = await getIgnore(directory);

const walkDir = async (dir: string): Promise<string[]> => {
const entries = await fs.readdir(dir, { withFileTypes: true });
const files = await Promise.all(
entries.map(async entry => {
const res = path.resolve(dir, entry.name);
const relativePath = path.relative(directory, res);

if (ig.ignores(relativePath) || entry.name === ".gitignore") {
debug(`Ignoring file: ${relativePath}`);
return [];
}

if (entry.isDirectory()) {
return walkDir(res);
}

if (
entry.isFile() &&
(entry.name.endsWith(".md") || entry.name.endsWith(".mdx"))
) {
if (await hasCodeComponentWithFileMeta(res)) {
debug(`Found file with code component: ${relativePath}`);
return res;
}
debug(
`Skipping file (no code component with file meta): ${relativePath}`,
);
}

return [];
}),
);
return files.flat();
};

return walkDir(directory);
};

const processContent = async (
content: string,
filePath: string,
): Promise<string> => {
try {
const file = await unified()
.use(remarkParse)
.use(remarkFrontmatter)
.use(importCode, {
preserveTrailingNewline: false,
removeRedundantIndentations: true,
rootDir: process.cwd(),
})
.use(remarkStringify, {
bullet: "-",
emphasis: "*",
fences: true,
listItemIndent: "one",
rule: "-",
ruleSpaces: false,
strong: "*",
tightDefinitions: true,
})
.process(content);
return String(file);
} catch (error) {
if ((error as NodeJS.ErrnoException).code === "ENOENT") {
throw new Error(
`File not found: ${(error as NodeJS.ErrnoException).path}`,
);
}
throw error;
}
};

const processFile = async (filePath: string): Promise<void> => {
try {
if (!(await hasCodeComponentWithFileMeta(filePath))) {
debug(`Skipping ${filePath}: No code component with file meta found.`);
return;
}

const originalContent = await fs.readFile(filePath, "utf8");
const processedContent = await processContent(originalContent, filePath);
if (originalContent !== processedContent) {
await fs.writeFile(filePath, processedContent);
console.log(`Updated: ${filePath}`);
} else {
debug(`No changes needed for: ${filePath}`);
}
} catch (error) {
console.error(`Error processing ${filePath}: ${(error as Error).message}`);
}
};

const processInChunks = async <T>(
items: T[],
processItem: (item: T) => Promise<void>,
chunkSize: number,
): Promise<void> => {
for (let i = 0; i < items.length; i += chunkSize) {
const chunk = items.slice(i, i + chunkSize);
await Promise.all(chunk.map(processItem));
}
};

const watchFiles = async (directory: string): Promise<void> => {
const watcher = chokidar.watch(["**/*.md", "**/*.mdx"], {
ignored: [
"**.**",
/(^|[\/\\])\../,
"**/node_modules/**",
"**/.git/**",
".gitignore",
], // ignore dotfiles, node_modules, .git, and .gitignore
persistent: true,
cwd: directory,
});

console.log("Watch mode started. Waiting for file changes...");

watcher
.on("add", filePath => processFile(path.join(directory, filePath)))
.on("change", filePath => processFile(path.join(directory, filePath)))
.on("unlink", filePath => console.log(`File ${filePath} has been removed`));
};

const main = async (): Promise<void> => {
const filePath = process.argv[2];
const watchMode =
process.argv.includes("--watch") || process.argv.includes("-w");
debugMode = process.argv.includes("--debug") || process.argv.includes("-d");

if (debugMode) {
console.log("Debug mode enabled");
}

if (filePath && !watchMode && !debugMode) {
// Process single file
const absolutePath = path.resolve(process.cwd(), filePath);
console.log(`Processing single file: ${absolutePath}`);
await processFile(absolutePath);
} else if (watchMode) {
// Watch mode
await watchFiles(process.cwd());
} else {
// Process all files
const files = await getMarkdownAndMDXFiles(process.cwd());
const chunkSize = Math.max(1, Math.ceil(files.length / os.cpus().length));

console.log(`Processing ${files.length} files...`);
await processInChunks(files, processFile, chunkSize);
}

if (!watchMode) {
console.log("Sync process completed.");
}
};

main().catch(console.error);
2 changes: 1 addition & 1 deletion content/cookbook/wallets/check-publickey.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ have a private key associated with them. You can check this by looking to see if
the public key lies on the ed25519 curve. Only public keys that lie on the curve
can be controlled by users with wallets.

```javascript file="check-public-key.ts"
```javascript file=/code/cookbook/wallets/check-public-key.ts#L1-L2,#L3-L19
import { PublicKey } from "@solana/web3.js";

// Note that Keypair.generate() will always give a public key that is valid for users
Expand Down
3 changes: 0 additions & 3 deletions content/courses/connecting-to-offchain-data/metadata.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,3 @@ lessons:
- oracles
- verifiable-randomness-functions
priority: 20
# Uses out of date repos
# TODO: Superteam to update
isHidden: true
2 changes: 1 addition & 1 deletion content/courses/connecting-to-offchain-data/oracles.md
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ the data feed account does not exist anymore, withdraw the user's escrowed
funds.

A potential solution to this challenge can be found
[in the Github repository on the `challenge-solution` branch](https://github.com/Unboxed-Software/michael-burry-escrow/tree/challenge-solution).
[in the Github repository on the `challenge-solution` branch](https://github.com/solana-developers/burry-escrow/tree/challenge-solution).

<Callout type="success" title="Completed the lab?">

Expand Down
Loading