Skip to content

Commit 956ed3d

Browse files
author
Matthias Zimmermann
committed
docs: add getting started docs
1 parent a1bea9f commit 956ed3d

File tree

2 files changed

+328
-0
lines changed

2 files changed

+328
-0
lines changed

docs/ARKIV_SDK_JS.md

Lines changed: 255 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
# Arkiv SDK for Typescript / JS
2+
3+
## Commands
4+
5+
### Run voating-board.ts
6+
7+
```shell
8+
npm start
9+
```
10+
11+
### Update SDK
12+
13+
```shell
14+
npm update arkiv-sdk
15+
```
16+
17+
## Files
18+
19+
### package.json
20+
21+
```json
22+
{
23+
"type": "module",
24+
"scripts": {
25+
"start": "tsx voting-board.ts",
26+
"build": "tsc",
27+
"dev": "tsx watch voting-board.ts"
28+
},
29+
"dependencies": {
30+
"@arkiv-network/sdk": "^0.4.4",
31+
"dotenv": "^16.4.5",
32+
"tslib": "^2.8.1",
33+
"ethers": "^6.13.4"
34+
},
35+
"devDependencies": {
36+
"tsx": "^4.19.2",
37+
"typescript": "^5.6.3"
38+
}
39+
}
40+
```
41+
42+
### tsconfig.json
43+
44+
```json
45+
{
46+
"compilerOptions": {
47+
"target": "ES2022",
48+
"module": "ESNext",
49+
"moduleResolution": "Bundler",
50+
"strict": true,
51+
"esModuleInterop": true,
52+
"skipLibCheck": true
53+
},
54+
"include": ["*.ts"]
55+
}
56+
```
57+
58+
### voting-board.ts
59+
60+
```ts
61+
import { createWalletClient, createPublicClient, http } from '@arkiv-network/sdk';
62+
import { mendoza } from '@arkiv-network/sdk/chains';
63+
import { privateKeyToAccount } from '@arkiv-network/sdk/accounts';
64+
import { eq } from '@arkiv-network/sdk/query';
65+
66+
const PRIVATE_KEY = '0x...';
67+
const MENDOZA_RPC = 'https://mendoza.hoodi.arkiv.network/rpc'
68+
69+
// Suppress SDK debug logs
70+
console.debug = () => {};
71+
72+
function createClients() {
73+
const walletClient = createWalletClient({
74+
chain: mendoza,
75+
transport: http(MENDOZA_RPC),
76+
account: privateKeyToAccount(PRIVATE_KEY),
77+
});
78+
79+
const publicClient = createPublicClient({
80+
chain: mendoza,
81+
transport: http(MENDOZA_RPC),
82+
});
83+
84+
return { walletClient, publicClient };
85+
}
86+
87+
async function openProposal(walletClient: any, proposalText: string) {
88+
console.log('Creating proposal entity...');
89+
90+
const enc = new TextEncoder();
91+
const { entityKey: proposalKey } = await walletClient.createEntity({
92+
payload: enc.encode(proposalText),
93+
contentType: 'text/plain',
94+
attributes: [
95+
{ key: 'type', value: 'proposal' },
96+
{ key: 'status', value: 'open' },
97+
{ key: 'version', value: '1' },
98+
],
99+
expiresIn: 200, // seconds
100+
});
101+
102+
console.log('- Proposal key:', proposalKey);
103+
return proposalKey;
104+
}
105+
106+
async function castVote(walletClient: any, proposalKey: string, choice: string, weight: string = '1') {
107+
console.log(`Casting vote "${choice}" for proposal ${proposalKey} ...`);
108+
109+
const enc = new TextEncoder();
110+
const voterAddr = walletClient.account.address;
111+
112+
await walletClient.mutateEntities({
113+
creates: [
114+
{
115+
payload: enc.encode(`vote: ${choice}`),
116+
contentType: 'text/plain',
117+
attributes: [
118+
{ key: 'type', value: 'vote' },
119+
{ key: 'proposalKey', value: proposalKey },
120+
{ key: 'voter', value: voterAddr },
121+
{ key: 'choice', value: choice },
122+
{ key: 'weight', value: weight },
123+
],
124+
expiresIn: 200,
125+
},
126+
],
127+
});
128+
129+
console.log('- Vote cast');
130+
}
131+
132+
async function castVotesBatch(walletClient: any, proposalKey: string, choice: string, count: number) {
133+
console.log(`Casting ${count} batch votes "${choice}" for proposal ${proposalKey} ...`);
134+
135+
const enc = new TextEncoder();
136+
const voterAddr = walletClient.account.address;
137+
138+
const creates = Array.from({ length: count }, (_, i) => ({
139+
payload: enc.encode(`vote: ${choice} #${i + 1}`),
140+
contentType: 'text/plain',
141+
attributes: [
142+
{ key: 'type', value: 'vote' },
143+
{ key: 'proposalKey', value: proposalKey },
144+
{ key: 'voter', value: `${voterAddr}-bot${i}` },
145+
{ key: 'choice', value: choice },
146+
{ key: 'weight', value: '1' },
147+
],
148+
expiresIn: 200,
149+
}));
150+
151+
await walletClient.mutateEntities({ creates });
152+
console.log(`- Batch created: ${creates.length} votes`);
153+
}
154+
155+
async function tallyVotes(publicClient: any, proposalKey: string) {
156+
console.log(`Tallying votes for proposal ${proposalKey} ...`);
157+
158+
const yes = await publicClient
159+
.buildQuery()
160+
.where([eq("type", "vote"), eq("proposalKey", proposalKey), eq("choice", "yes")])
161+
.fetch();
162+
163+
const no = await publicClient
164+
.buildQuery()
165+
.where([eq("type", "vote"), eq("proposalKey", proposalKey), eq("choice", "no")])
166+
.fetch();
167+
168+
console.log(`- Tallies - YES: ${yes.entities.length}, NO: ${no.entities.length}`);
169+
return { yes: yes.entities.length, no: no.entities.length };
170+
}
171+
172+
async function helloWorld() {
173+
console.log('Doing the hello world ...');
174+
175+
// 1) Connect your account to Arkiv
176+
const { walletClient, publicClient } = createClients();
177+
178+
// 2) Write one small record on-chain
179+
const enc = new TextEncoder();
180+
const { entityKey, txHash } = await walletClient.createEntity({
181+
payload: enc.encode('Hello, Arkiv!'),
182+
contentType: 'text/plain',
183+
attributes: [{ key: 'type', value: 'hello' }],
184+
expiresIn: 120,
185+
});
186+
187+
// 3) Read it back and decode to string
188+
const entity = await publicClient.getEntity(entityKey);
189+
const data = new TextDecoder().decode(entity.payload);
190+
191+
// 4) Display results
192+
console.log('- Key:', entityKey);
193+
console.log('- Data:', data);
194+
console.log('- Tx:', txHash);
195+
}
196+
197+
async function main() {
198+
await helloWorld();
199+
200+
const { walletClient, publicClient } = createClients();
201+
const dec = new TextDecoder();
202+
203+
const stop = await publicClient.subscribeEntityEvents({
204+
onEntityCreated: async (e) => {
205+
try {
206+
const ent = await publicClient.getEntity(e.entityKey);
207+
const attrs = Object.fromEntries(
208+
ent.attributes.map(a => [a.key, a.value])
209+
);
210+
const text = dec.decode(ent.payload);
211+
212+
if (attrs.type === 'vote') {
213+
console.log('[Vote created]', text, 'key=', e.entityKey);
214+
} else if (attrs.type === 'proposal') {
215+
console.log('[Proposal created]', text, 'key=', e.entityKey);
216+
}
217+
} catch (err) {
218+
console.error('[onEntityCreated] error:', err);
219+
}
220+
},
221+
222+
onEntityExpiresInExtended: (e) => {
223+
console.log('[Extended]', e.entityKey, '', e.newExpirationBlock);
224+
},
225+
226+
onError: (err) => console.error('[subscribeEntityEvents] error:', err),
227+
});
228+
229+
console.log('Watching for proposal/vote creations and extensions…');
230+
231+
const proposalKey = await openProposal(
232+
walletClient,
233+
'Proposal: Switch stand-up to 9:30?',
234+
);
235+
236+
await castVote(
237+
walletClient,
238+
proposalKey,
239+
'no',
240+
);
241+
242+
const numberOfVotes = 5;
243+
await castVotesBatch(
244+
walletClient,
245+
proposalKey,
246+
'yes',
247+
numberOfVotes,
248+
);
249+
250+
await tallyVotes(publicClient, proposalKey);
251+
}
252+
253+
// Run the main function
254+
main().catch(console.error);
255+
```

docs/ARKIV_SDK_PYTHON.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Arkiv SDK for Python
2+
3+
## Requirements
4+
5+
- Python: >= 3.10
6+
- UV or pip
7+
8+
## Commands
9+
10+
### Setup Project (PIP)
11+
12+
```shell
13+
python3 -m venv .venv
14+
source .venv/bin/activate
15+
```
16+
17+
### Install Arkiv SDK and Packages
18+
19+
```shell
20+
pip install arkiv-sdk==1.0.0a8
21+
pip install testcontainers websockets
22+
```
23+
24+
### Setup Project (UV)
25+
26+
```shell
27+
uv init voting-board
28+
```
29+
30+
### Install SDK and Packages
31+
32+
```shell
33+
uv add arkiv-sdk --prerelease=allow
34+
uv add testcontainers websockets
35+
```
36+
37+
### Run Application
38+
39+
```
40+
uv run main.py
41+
```
42+
43+
### Update SDK
44+
45+
```shell
46+
npm update arkiv-sdk
47+
```
48+
49+
## Files
50+
51+
### .python-version
52+
53+
```
54+
3.14
55+
```
56+
57+
Versions 3.10, 3.11, 3.12, 3.13 are supported too
58+
59+
### pyproject.toml
60+
61+
```
62+
[project]
63+
name = "app"
64+
version = "0.1.0"
65+
description = "Add your description here"
66+
readme = "README.md"
67+
requires-python = ">=3.14"
68+
dependencies = [
69+
"arkiv-sdk>=1.0.0a8",
70+
"testcontainers>=4.13.3",
71+
"websockets>=15.0.1",
72+
]
73+
```

0 commit comments

Comments
 (0)