@palliora.org/chainsdk 0.3.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,45 +1,93 @@
1
+ > **Building a compute application? Read [CHAIN-RULES.md](CHAIN-RULES.md) first.**
2
+ > This README covers *which function to call*. CHAIN-RULES.md covers what the chain does
3
+ > with the call — the fee floor, guardian rate thresholds, contract lifecycles, guardian
4
+ > groups, and why a correctly-shaped transaction still gets rejected. None of that is
5
+ > visible from the TypeScript signatures.
6
+
1
7
  ## What this SDK provides
2
8
 
3
9
  - API initialization helpers for Palliora.
4
10
  - Keyring helpers for regular signing keys and encryption-oriented keys.
5
11
  - Wrapper functions for Palliora-specific RPC calls and extrinsics, especially in `guardian/`, `da/`, `compute/`, and `stake/`.
12
+ - **Indexer client** (`src/indexer/`) — typed read-only REST wrappers for `@statescan/indexer` (blocks, contracts, artefacts, extrinsics, transfers, guardians, and UI flow helpers).
6
13
  - Utility helpers for token formatting.
7
14
  - Crypto helpers for threshold-encryption-adjacent and hybrid encryption workflows.
8
15
 
9
16
  ## Install
10
17
 
11
18
  ```bash
12
- pnpm add @palliora/chainsdk
19
+ pnpm add @palliora.org/chainsdk
13
20
  ```
14
21
 
15
22
  Node.js 18+ is expected.
16
23
 
24
+ ## Releases
25
+
26
+ Merging a pull request into `main` publishes a new npm version through GitHub
27
+ Actions using npm trusted publishing (OIDC); it does not use an npm token. Add
28
+ exactly one of these labels to the merged pull request to select the version:
29
+ `patch`, `minor`, `major`, or `version:x.y.z`. The **Publish package to npm**
30
+ workflow can also be run manually from `main`, with a patch, minor, major, or
31
+ custom version.
32
+
33
+ Before the first release, configure npm's trusted publisher for
34
+ `@palliora.org/chainsdk` with GitHub organization `palliora-org`, repository
35
+ `palliora-sdk`, and workflow filename `publish-npm.yml` (not its path). Permit
36
+ the trusted publisher to run `npm publish` directly.
37
+
17
38
  ## Configuration
18
39
 
19
- The SDK reads these environment variables:
40
+ The SDK reads no environment variables. Call `init()` once, before any other SDK
41
+ function, and pass every value your application needs:
20
42
 
21
- - `PALLIORA_WS`: WebSocket endpoint for the chain. Defaults to `wss://manas-rpc.palliora.org`.
22
- - `DEBUG=true`: Enables debug logging in wrapper helpers.
23
- - `TX_WAIT_FINALIZATION=true`: Wait for finalization instead of returning once the tx is in-block.
43
+ ```ts
44
+ import { init } from "@palliora.org/chainsdk";
24
45
 
25
- Example:
46
+ init({
47
+ pallioraWs: "wss://manas-rpc.palliora.org",
48
+ debug: true,
49
+ });
50
+ ```
26
51
 
27
- ```bash
28
- export PALLIORA_WS=wss://manas-rpc.palliora.org
29
- export DEBUG=true
52
+ Where those values come from — `process.env`, `import.meta.env`, a config file, a
53
+ secrets manager — is the host application's decision.
54
+
55
+ | Option | Required | Purpose |
56
+ |---|---|---|
57
+ | `pallioraWs` | yes | WebSocket endpoint for the chain API connection |
58
+ | `pallioraRpcUrl` | yes | RPC endpoint, when it differs from `pallioraWs` |
59
+ | `costEstimatorUrl` | yes | Base URL of the cost-estimation service |
60
+ | `authServiceUrl` | yes | Base URL of the auth service issuing S3 pre-signed URLs |
61
+ | `awsRegion` | yes | AWS region of the artifact storage bucket |
62
+ | `awsS3Bucket` | yes | Name of the artifact storage bucket |
63
+ | `debug` | no (`false`) | Enables debug logging in wrapper helpers |
64
+ | `txWaitFinalization` | no (`false`) | Waits for finalization instead of returning once the tx is in-block |
65
+
66
+ Required options are required *lazily*: each one throws only when something
67
+ actually reads it. An application that never touches off-chain storage does not
68
+ need to pass the AWS options, but reading an unset option always throws rather
69
+ than silently falling back to a default.
70
+
71
+ ```ts
72
+ init({ pallioraWs: "wss://manas-rpc.palliora.org" });
73
+ await getApi(); // fine
74
+ await uploadContract(); // throws: config "authServiceUrl" is not set
30
75
  ```
31
76
 
77
+ `init()` merges on repeat calls, so configuration can be supplied in stages.
78
+
32
79
  ## Quick start
33
80
 
34
81
  The most common flow is:
35
82
 
36
- 1. Initialize the API.
83
+ 1. Call `init()` with your configuration.
37
84
  2. Load or create a signing account from the keyring.
38
85
  3. Fetch token metadata once.
39
86
  4. Call the wrapper functions you need.
40
87
 
41
88
  ```ts
42
89
  import {
90
+ init,
43
91
  getKeyring,
44
92
  fetchTokenProperties,
45
93
  formatBalanceWithTokenProperties,
@@ -47,9 +95,11 @@ import {
47
95
  submitData,
48
96
  newStake,
49
97
  transfer,
50
- } from "@palliora/chainsdk";
98
+ } from "@palliora.org/chainsdk";
51
99
 
52
100
  async function main() {
101
+ init({ pallioraWs: "wss://manas-rpc.palliora.org" });
102
+
53
103
  const keyring = await getKeyring();
54
104
  const amount = BigInt("1000000000000000000000"); // 1000 PALI
55
105
 
@@ -81,7 +131,9 @@ Use these when you want a broader integration and may combine SDK wrappers with
81
131
  ### Default initialization
82
132
 
83
133
  ```ts
84
- import { getApi, getKeyring } from "@palliora/chainsdk";
134
+ import { init, getApi, getKeyring } from "@palliora.org/chainsdk";
135
+
136
+ init({ pallioraWs: "wss://manas-rpc.palliora.org" });
85
137
 
86
138
  const api = await getApi();
87
139
  const keyring = await getKeyring();
@@ -89,8 +141,11 @@ const keyring = await getKeyring();
89
141
  const signer = keyring.addFromUri("//Alice");
90
142
  ```
91
143
 
92
- - `getApi()` returns the shared `ApiPromise` instance.
93
- - `getKeyring()` returns the shared `sr25519` keyring for signing.
144
+ - `init(options)` configures the SDK. Nothing else works until it has run.
145
+ - `getApi()` returns the shared `ApiPromise` instance. It throws if `init()` was
146
+ never called or was called without `pallioraWs`.
147
+ - `getKeyring()` returns the shared `sr25519` keyring for signing. It needs no
148
+ configuration.
94
149
 
95
150
  ## Wrapper calls
96
151
 
@@ -103,7 +158,7 @@ import {
103
158
  getGuardianList,
104
159
  createGuardianGroup,
105
160
  joinGuardian,
106
- } from "@palliora/chainsdk";
161
+ } from "@palliora.org/chainsdk";
107
162
 
108
163
  const guardians = await getGuardianList();
109
164
 
@@ -113,6 +168,10 @@ await joinGuardian(account, {
113
168
  standard: true,
114
169
  verifier: true,
115
170
  compute: "trusted,tee",
171
+ // Minimum rate to take work at, in atomic units. A single amount prices every
172
+ // compute type above; pass a record to price them separately. Omit to accept
173
+ // any rate.
174
+ fee: { trusted: 1_000_000_000_000_000_000n, tee: 2_500_000_000_000_000_000n },
116
175
  });
117
176
  ```
118
177
 
@@ -125,7 +184,7 @@ Main guardian exports:
125
184
  ### Data availability
126
185
 
127
186
  ```ts
128
- import { submitData } from "@palliora/chainsdk";
187
+ import { submitData } from "@palliora.org/chainsdk";
129
188
 
130
189
  await submitData(account, "payload to store on Palliora DA");
131
190
  ```
@@ -136,18 +195,51 @@ Main DA export:
136
195
 
137
196
  ### Compute
138
197
 
139
- ```ts
140
- import { createAgreement, getGuardianParticipants } from "@palliora/chainsdk";
141
-
142
- await createAgreement();
198
+ Before offering a fee, check the floor the chain enforces — see
199
+ [CHAIN-RULES.md §2](CHAIN-RULES.md) for what the components mean.
143
200
 
144
- const participants = await getGuardianParticipants();
145
- console.log(participants);
201
+ ```ts
202
+ import {
203
+ createAgreement,
204
+ estimateMinFee,
205
+ buildFee,
206
+ fromAtomicPaliAmount,
207
+ getGuardianList,
208
+ } from "@palliora.org/chainsdk";
209
+
210
+ const guardians = (await getGuardianList()).slice(0, 3);
211
+ const computeRate = "0.000000001";
212
+
213
+ // The smallest `fees` this contract may offer. Offer more to buy more compute time.
214
+ const { minFee } = await estimateMinFee({ computeRate });
215
+
216
+ await createAgreement(
217
+ {
218
+ contractType: "Active",
219
+ guardians,
220
+ compute: {
221
+ cipher: "Plaintext",
222
+ computerIndices: guardians.map((_, i) => i),
223
+ ...buildFee({ amount: fromAtomicPaliAmount(minFee), computeRate }),
224
+ deadline: 0,
225
+ confidentiality: { Trusted: 0 },
226
+ feeFunction: null,
227
+ input: { Inline: { data: [...new TextEncoder().encode("hello")] } },
228
+ program: { NativeExecute: "Inference" },
229
+ },
230
+ resultCipher: "Plaintext",
231
+ },
232
+ account,
233
+ );
146
234
  ```
147
235
 
148
236
  Main compute exports:
149
237
 
150
- - `createAgreement()`
238
+ - `createAgreement(contract, account, oracleQuoteId?)`
239
+ - `invokeAgreement(agreementId, input, account, opts?)` — `Subscription` contracts only
240
+ - `estimateMinFee({ computeRate, inputContractId? })` — the fee floor plus its breakdown
241
+ - `getFeeParams()` — the four live chain parameters the floor derives from
242
+ - `inferenceCompute`, `simpleCompute`, `dataContract`, `encryptedInferenceCompute`
151
243
 
152
244
  ### Stake
153
245
 
@@ -160,7 +252,7 @@ import {
160
252
  removeStake,
161
253
  withdrawStake,
162
254
  tokenToBigint,
163
- } from "@palliora/chainsdk";
255
+ } from "@palliora.org/chainsdk";
164
256
 
165
257
  const amount = tokenToBigint(100);
166
258
 
@@ -185,7 +277,7 @@ Main stake exports:
185
277
  ### Token
186
278
 
187
279
  ```ts
188
- import { fundAccount, transfer, tokenToBigint } from "@palliora/chainsdk";
280
+ import { fundAccount, transfer, tokenToBigint } from "@palliora.org/chainsdk";
189
281
 
190
282
  await fundAccount(account, tokenToBigint(50));
191
283
  await transfer(account, tokenToBigint(10), "5F3sa2TJAWMqDhXG6jhV4N8ko9qQ7x7T9nM8uA8V2sR8hF4M");
@@ -222,7 +314,7 @@ import {
222
314
  gen_stretched_key,
223
315
  encrypt,
224
316
  decrypt,
225
- } from "@palliora/chainsdk";
317
+ } from "@palliora.org/chainsdk";
226
318
 
227
319
  const shared = gen_shared_key(mySecretKeyBytes, peerPublicKeyBytes);
228
320
  const key = gen_stretched_key(shared);
@@ -240,6 +332,49 @@ Main crypto exports:
240
332
  - `decrypt(ciphertext, key, nonce)`
241
333
  - `generateRandomBytes(length?)`
242
334
 
335
+ ## Indexer (read-only chain data)
336
+
337
+ For explorer/UI reads against the `@statescan/indexer` REST API (default `http://localhost:5020`):
338
+
339
+ ```ts
340
+ import {
341
+ IndexerClient,
342
+ getBlocks,
343
+ getModels,
344
+ getAgents,
345
+ getExtrinsics,
346
+ getResults,
347
+ getContractFlow,
348
+ getArtefactContracts,
349
+ } from "@palliora.org/chainsdk";
350
+
351
+ const client = new IndexerClient({ baseUrl: "http://localhost:5020" });
352
+ // Do not put /api in baseUrl — paths already include /api/...
353
+
354
+ const { data: blocks } = await getBlocks(client, { page: 0, page_size: 5 });
355
+ console.log(blocks.blocks, blocks.stats);
356
+
357
+ const { data: models } = await getModels(client); // storeType === "Model"
358
+ const { data: agents } = await getAgents(client); // storeType === "Agent"
359
+
360
+ const { data: txs } = await getExtrinsics(client, { signed_only: true });
361
+ const { data: results } = await getResults(client, { contractId: "0x..." });
362
+ const { data: flow } = await getContractFlow(client, "0xcontractId...");
363
+ // flow.computes, flow.results, flow.phases (phase-1 … phase-5)
364
+
365
+ const { data: usages } = await getArtefactContracts(client, "0xartefactId...");
366
+ ```
367
+
368
+ Full API, response shapes, and agent integration notes:
369
+
370
+ - [`src/indexer/README.md`](src/indexer/README.md) — overview + complete function tables
371
+ - [`src/indexer/AGENTS.md`](src/indexer/AGENTS.md) — detailed integration guide for AI agents
372
+
373
+ ```bash
374
+ pnpm test # unit tests
375
+ pnpm test:integration # live HTTP against local indexer
376
+ ```
377
+
243
378
  ## Choosing between raw API and wrappers
244
379
 
245
380
  Use the wrappers when: