@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/AGENTS.md +61 -0
- package/CHAIN-RULES.md +760 -0
- package/README.md +161 -26
- package/dist/index.cjs +1422 -136
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1369 -24
- package/dist/index.d.ts +1369 -24
- package/dist/index.js +1391 -105
- package/dist/index.js.map +1 -1
- package/package.json +20 -11
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
|
|
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
|
-
|
|
22
|
-
|
|
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
|
-
|
|
46
|
+
init({
|
|
47
|
+
pallioraWs: "wss://manas-rpc.palliora.org",
|
|
48
|
+
debug: true,
|
|
49
|
+
});
|
|
50
|
+
```
|
|
26
51
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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.
|
|
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
|
-
- `
|
|
93
|
-
- `
|
|
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
|
-
|
|
140
|
-
|
|
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
|
-
|
|
145
|
-
|
|
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:
|