Skip to content
Open
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
6 changes: 6 additions & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import nextra from "nextra";
import codeImport from "@proto-kit/remark-code-import";

const withNextra = nextra({
theme: "nextra-theme-docs",
themeConfig: "./theme.config.tsx",
latex: true,
search: { codeblocks: false },
mdxOptions: {
remarkPlugins: [
codeImport
]
}
});

const isProd = process.env.NODE_ENV === "production";
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"scripts": {
"postinstall": "pnpm run typedoc:generate",
"typedoc:generate": "./generate-typedoc.sh",
"typedoc:generate": "echo",
"dev": "next dev",
"build": "next build",
"start": "next start"
Expand Down Expand Up @@ -71,6 +71,7 @@
"@types/react": "19.0.8",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.31",
"@proto-kit/remark-code-import": "^1.2.0",
"tailwindcss": "^3.3.3",
"typescript": "^5.2.2"
}
Expand Down
18,133 changes: 14,663 additions & 3,470 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
packages:
- .
- starter-kit-snippets
- starter-kit-snippets/apps/*
- starter-kit-snippets/packages/*
1 change: 0 additions & 1 deletion src/pages/docs/_meta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,4 @@ export default {
title: "Graphql API docs",
href: "https://graphql.protokit.dev/"
},
reference: "Reference",
};
34 changes: 4 additions & 30 deletions src/pages/docs/advanced/protocol.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,8 @@ They work similar to the runtime `@state(){:ts}` state and emit StateTransitions
To define state in ProtocolModules, you will have to use the `@protocolState(){:ts}` decorator instead of `@state(){:ts}`.
The rest, like the `State` and `StateMap` classes, stays the same.

```ts {2,5,7} showLineNumbers filename="ProtocolStateModule" copy
export class ProtocolStateModule extends ProvableTransactionHook {
@protocolState() public accountState = StateMap.from(PublicKey, AccountState);

public onTransaction(): void {
const accountState = this.accountState.get(this.transaction.sender.value)

this.accountState.set(this.transaction.sender, someAccountState);
...
}
}
```ts {12,17,19} showLineNumbers filename="ProtocolStateModule" copy file=<rootDir>/starter-kit-snippets/packages/chain/src/runtime/hooks/transactionHook.ts
// Example transaction hook with state
```

### Calling runtime modules
Expand All @@ -67,25 +58,8 @@ Let's assume we have a runtime module called `Balances` that keeps track of toke

This can be implemented very easily:

```ts {5,8,12-15} showLineNumbers filename="TransactionFeeModule" copy
export class SimpleTransactionFeeModule extends ProvableTransactionHook {
private balances: Balances;

public constructor(
@inject("Runtime") runtime: Runtime<RuntimeModulesRecord>
) {
super();
this.balances = runtime.resolveOrFail("Balances", Balances);
}

public onTransaction({ transaction }: BlockProverExecutionData): void {
this.balances.transfer(
transaction.sender,
PublicKey.empty(),
UInt64.from(100)
);
}
}
```ts {16,19,23-28} showLineNumbers filename="TransactionFeeModule" copy file=<rootDir>/starter-kit-snippets/packages/chain/src/runtime/hooks/transactionFeeHook.ts
// Example transaction fee hook
```

> RuntimeModules that are called this was, will be treated as protocol-executed code by the framework.
Expand Down
85 changes: 4 additions & 81 deletions src/pages/docs/quickstart/app-chain.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,8 @@ This runtime module stores a ledger of balances for public keys, and the current

It also defines a single runtime method called _addBalance_, which allows tokens to be minted for a certain address. It looks like this:

```typescript showLineNumbers filename="packages/chain/src/balances.ts"
import { runtimeModule, state, runtimeMethod } from "@proto-kit/module";
import { State, assert } from "@proto-kit/protocol";
import { Balance, Balances as BaseBalances, TokenId } from "@proto-kit/library";
import { PublicKey } from "o1js";

interface BalancesConfig {
totalSupply: Balance;
}

@runtimeModule()
export class Balances extends BaseBalances<BalancesConfig> {
@state() public circulatingSupply = State.from(Balance);

// implicitly inherited from `BaseBalances`
// @state() public balances = StateMap.from(..);

@runtimeMethod()
public addBalance(tokenId: TokenId, address: PublicKey, amount: Balance) {
const circulatingSupply = this.circulatingSupply.get();
const newCirculatingSupply = Balance.from(circulatingSupply.value).add(
amount
);
assert(
newCirculatingSupply.lessThanOrEqual(this.config.totalSupply),
"Circulating supply would be higher than total supply"
);
this.circulatingSupply.set(newCirculatingSupply);
this.mint(tokenId, address, amount);
}
}

```typescript showLineNumbers filename="packages/chain/src/balances.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/runtime/modules/balances.ts
// Example runtime modules Balances with circulatingSupply and addBalance()
```

## Testing the runtime
Expand All @@ -57,55 +27,8 @@ comes with a simple test suite that demonstrates how to do this. The test suite

> The _TestingAppChain_ is a special type of application chain that is designed to be used in tests. It runs an in-memory version of the sequencer as well!

```typescript showLineNumbers filename="packages/chain/test/balances.test.ts"
import { TestingAppChain } from "@proto-kit/sdk";
import { PrivateKey } from "o1js";
import { Balances } from "../src/balances";
import { log } from "@proto-kit/common";
import { BalancesKey, TokenId, UInt64 } from "@proto-kit/library";

log.setLevel("ERROR");

describe("balances", () => {
it("should demonstrate how balances work", async () => {
const appChain = TestingAppChain.fromRuntime({
Balances,
});

appChain.configurePartial({
Runtime: {
Balances: {
totalSupply: UInt64.from(10000),
},
},
});

await appChain.start();

const alicePrivateKey = PrivateKey.random();
const alice = alicePrivateKey.toPublicKey();
const tokenId = TokenId.from(0);

appChain.setSigner(alicePrivateKey);

const balances = appChain.runtime.resolve("Balances");

const tx1 = await appChain.transaction(alice, () => {
balances.addBalance(tokenId, alice, UInt64.from(1000));
});

await tx1.sign();
await tx1.send();

const block = await appChain.produceBlock();

const key = new BalancesKey({ tokenId, address: alice });
const balance = await appChain.query.runtime.Balances.balances.get(key);

expect(block?.transactions[0].status.toBoolean()).toBe(true);
expect(balance?.toBigInt()).toBe(1000n);
}, 1_000_000);
});
```typescript showLineNumbers filename="packages/chain/test/balances.test.ts" file=<rootDir>/starter-kit-snippets/packages/chain/test/runtime/modules/balances.test.ts
// A example jest test suite showing how to test a basic runtime flow
```

### Running the test(s)
Expand Down
88 changes: 6 additions & 82 deletions src/pages/docs/quickstart/client-interaction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,44 +32,9 @@ The code below does the following:
5. Sign and send the transaction to the locally hosted sequencer.


```typescript showLineNumbers {30-35} filename="packages/chain/test/interaction.test.ts"
import { InMemorySigner } from "@proto-kit/sdk";
import { UInt64 } from "@proto-kit/library";
import { client as appChain } from "./../src/client.config";
import { PrivateKey } from "o1js";
import { GuestBook } from "../src/guest-book";

const signer = PrivateKey.random();
const sender = signer.toPublicKey();

describe("interaction", () => {
let guestBook: GuestBook;

beforeAll(async () => {
await appChain.start();

const inMemorySigner = new InMemorySigner();

appChain.registerValue({
Signer: inMemorySigner,
});

const resolvedInMemorySigner = appChain.resolve("Signer") as InMemorySigner;
resolvedInMemorySigner.config = { signer };

guestBook = appChain.runtime.resolve("GuestBook");
});

it("should interact with the app-chain", async () => {
const rating = UInt64.from(3);
const tx = await appChain.transaction(sender, () => {
guestBook.checkIn(rating);
});

await tx.sign();
await tx.send();
});
});
```typescript showLineNumbers {31-36} filename="packages/chain/test/interaction.test.ts" file=<rootDir>/starter-kit-snippets/packages/chain/test/runtime/modules/guestBook.test.ts inline
// group start
// group onlyTransaction
```

You can run the test above with the following command:
Expand All @@ -91,50 +56,9 @@ Here's a breakdown of what happens in the test suite below:
3. Wait for a couple seconds for a block to be produced
4. Query the latest check-in for the sender address, from the GraphQL API of the locally hosted sequencer.

```typescript showLineNumbers {38-40} filename="packages/chain/test/interaction.test.ts"
import { InMemorySigner } from "@proto-kit/sdk";
import { UInt64 } from "@proto-kit/library";
import { client as appChain } from "./../src/client.config";
import { PrivateKey, Provable } from "o1js";
import { GuestBook } from "../src/guest-book";
import { sleep } from "@proto-kit/common";

const signer = PrivateKey.random();
const sender = signer.toPublicKey();

describe("interaction", () => {
let guestBook: GuestBook;

beforeAll(async () => {
await appChain.start();

const inMemorySigner = new InMemorySigner();

appChain.registerValue({
Signer: inMemorySigner,
});

const resolvedInMemorySigner = appChain.resolve("Signer") as InMemorySigner;
resolvedInMemorySigner.config = { signer };

guestBook = appChain.runtime.resolve("GuestBook");
});

it("should interact with the app-chain", async () => {
const rating = UInt64.from(3);
const tx = await appChain.transaction(sender, () => {
guestBook.checkIn(rating);
});

await tx.sign();
await tx.send();

await sleep(8000);

const checkIn = await appChain.query.runtime.GuestBook.checkIns.get(sender);
Provable.log("checkIn", sender, checkIn);
});
});
```typescript showLineNumbers {38, 40} filename="packages/chain/test/interaction.test.ts" file=<rootDir>/starter-kit-snippets/packages/chain/test/runtime/modules/guestBook.test.ts inline
// group start
// group withQuery
```

Don't forget to run your test suite again to see the results 👆
20 changes: 1 addition & 19 deletions src/pages/docs/quickstart/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,7 @@
Your app-chain can be configured at three different levels: _runtime_, _chain_ and _client_. Firstly we start with the
overall runtime configuration, specifying the definition/configuration of your runtime module layout:

```typescript {5-7} showLineNumbers filename="packages/chain/src/runtime.ts"
import { Balance } from "@proto-kit/library";
import { Balances } from "./balances";
import { ModulesConfig } from "@proto-kit/common";

export const modules = {
Balances,
};

export const config: ModulesConfig<typeof modules> = {
Balances: {
totalSupply: Balance.from(10_000),
},
};

export default {
modules,
config,
};
```typescript {6-9} showLineNumbers filename="packages/chain/src/runtime.ts" file=<rootDir>/starter-kit-snippets/packages/chain/src/runtime/index.ts

```

Expand Down
Loading