@blockula/sdk 0.3.0 → 0.5.1

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/dist/tx.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export type KeyRole = {
2
2
  type: "owner";
3
3
  }
4
- /** Transfers only, at most `limit` drops (amount + fee) per `period_blocks`, until block `expires_at`. */
4
+ /** Transfers only, at most `limit` drops (amount + charged fee) per `period_blocks`, until block `expires_at`. */
5
5
  | {
6
6
  type: "session";
7
7
  limit: string;
@@ -15,11 +15,20 @@ export type Action = {
15
15
  } | {
16
16
  type: "register_name";
17
17
  name: string;
18
- } | {
18
+ }
19
+ /**
20
+ * Authorize a key on this account (owner keys only). The added key consents: `public_key` is its
21
+ * hex ML-DSA-65 public key (`key_id` is its BLAKE3) and `pop` its signature over
22
+ * `keyPopMessage(chain_id, genesis_hash, account, key_id)` with context `KEY_POP_CONTEXT`. Build
23
+ * it from a `KeyGrant` (`Wallet.keyGrant`, `addOwnerKey`, `addSessionKey`).
24
+ */
25
+ | {
19
26
  type: "add_key";
20
27
  key_id: string;
21
28
  label: string;
22
29
  role: KeyRole;
30
+ public_key: string;
31
+ pop: string;
23
32
  } | {
24
33
  type: "remove_key";
25
34
  key_id: string;
@@ -83,13 +92,344 @@ export type Action = {
83
92
  type: "register_familiar";
84
93
  key_id: string;
85
94
  label: string;
95
+ }
96
+ /** Season 0 admins: put a repo in the contribution pool (weight 1–100; 0 removes it). */
97
+ | {
98
+ type: "set_repo";
99
+ repo: string;
100
+ weight: number;
101
+ }
102
+ /** Season 0 admins: bootstrap Soul, in milli-Soul (≤ 100 Soul per grant). */
103
+ | {
104
+ type: "grant_soul";
105
+ to: string;
106
+ amount: number;
107
+ reason: string;
108
+ }
109
+ /** Stake 10 FANG on a newcomer `account` being a real, distinct person (needs 10 Soul). */
110
+ | {
111
+ type: "vouch";
112
+ account: string;
113
+ }
114
+ /** The voucher withdraws (after the lock), or the newcomer declines (any time). */
115
+ | {
116
+ type: "unvouch";
117
+ account: string;
118
+ } | {
119
+ type: "flag_sybil";
120
+ account: string;
121
+ reason: string;
122
+ }
123
+ /** Claim a merged PR by your linked GitHub handle. Registered Familiars may sign this. */
124
+ | {
125
+ type: "submit_claim";
126
+ repo: string;
127
+ pr: number;
128
+ familiar_key?: string;
129
+ }
130
+ /** Validators only (nodes do this automatically). */
131
+ | {
132
+ type: "attest_claim";
133
+ claim_id: number;
134
+ ok: boolean;
135
+ merge_sha: string;
136
+ note: string;
137
+ } | {
138
+ type: "reject_claim";
139
+ claim_id: number;
140
+ reason: string;
141
+ } | {
142
+ type: "join_jury";
143
+ bond: string;
144
+ } | {
145
+ type: "leave_jury";
146
+ }
147
+ /**
148
+ * A juror's sealed judgment: `seanceCommitment(...)`, and `seancePairsDigest(...)` of the pairs
149
+ * (and their claims' PRs) the juror compared: other pairs on chain refuse it (audit gap-7-6).
150
+ */
151
+ | {
152
+ type: "commit_votes";
153
+ seance_id: number;
154
+ commitment: string;
155
+ pairs_digest: string;
156
+ }
157
+ /** One of "a", "b", "=" per assigned pair, claim ids flagged as spam, and the salt. */
158
+ | {
159
+ type: "reveal_votes";
160
+ seance_id: number;
161
+ votes: string;
162
+ spam: number[];
163
+ salt: string;
164
+ } | {
165
+ type: "fund_pool";
166
+ amount: string;
167
+ } | {
168
+ type: "withdraw_vested";
169
+ } | {
170
+ type: "clawback";
171
+ account: string;
172
+ reason: string;
173
+ }
174
+ /** Stake `amount` drops in a validator's pool (validators are named by address). */
175
+ | {
176
+ type: "delegate";
177
+ validator: string;
178
+ amount: string;
179
+ }
180
+ /**
181
+ * Start unbonding stake in a pool: exactly `shares`, or (with `shares` "0") the shares worth
182
+ * `amount` drops at the pool's price when the tx runs (rounded up: at least `amount` unbonds).
183
+ * One of the two is set. Naming an amount, a wallet never converts FANG to shares at a price
184
+ * some node reported (audit gap-7-5). `withdraw_unbonded` pays it out after the unbonding period.
185
+ */
186
+ | {
187
+ type: "undelegate";
188
+ validator: string;
189
+ shares: string;
190
+ amount?: string;
191
+ } | {
192
+ type: "redelegate";
193
+ from_validator: string;
194
+ to_validator: string;
195
+ shares: string;
196
+ } | {
197
+ type: "withdraw_unbonded";
198
+ }
199
+ /** A validator's owner: commission (bps) and, when non-empty, new addresses. */
200
+ | {
201
+ type: "update_validator";
202
+ commission_bps: number;
203
+ p2p_addr: string;
204
+ http_addr: string;
205
+ } | {
206
+ type: "unjail";
207
+ validator: string;
208
+ }
209
+ /** Two conflicting signed votes, hex (at most 16 KiB decoded). */
210
+ | {
211
+ type: "report_equivocation";
212
+ evidence: string;
213
+ }
214
+ /** A validator's commitment to its secret for the randomness beacon of `epoch`: `beaconCommitment(...)`. */
215
+ | {
216
+ type: "beacon_commit";
217
+ epoch: number;
218
+ commitment: string;
219
+ } | {
220
+ type: "beacon_reveal";
221
+ epoch: number;
222
+ secret: string;
223
+ }
224
+ /** Put `kind` to a vote, bonding `deposit` drops; `url` (https) links the full text. */
225
+ | {
226
+ type: "propose";
227
+ kind: ProposalKind;
228
+ deposit: string;
229
+ title: string;
230
+ url?: string;
231
+ }
232
+ /** Lock `amount` drops for `conviction` (0–6) lock periods: weight 0.1× with no lock, then 1×–6× for 1, 2, 4, 8, 16, 32 periods. */
233
+ /** `proposal_digest`: `proposalDigest(kind, title, url)` of the proposal the voter was shown; a vote on other content is refused (audit gap-7-6). */
234
+ | {
235
+ type: "vote";
236
+ proposal_id: number;
237
+ aye: boolean;
238
+ amount: string;
239
+ conviction: number;
240
+ proposal_digest: string;
241
+ }
242
+ /** Release expired vote locks. */
243
+ | {
244
+ type: "unlock";
245
+ }
246
+ /** Make this account an M-of-N multisig of its owner keys (key ids). */
247
+ | {
248
+ type: "multisig_create";
249
+ owners: string[];
250
+ threshold: number;
251
+ }
252
+ /** Propose an action for a multisig account (never another multisig proposal or approval). */
253
+ | {
254
+ type: "multisig_propose";
255
+ action: Action;
256
+ }
257
+ /** `action_digest`: `actionDigest(action)` of the action the approver was shown; approving anything else is refused (audit gap-7-6). */
258
+ | {
259
+ type: "multisig_approve";
260
+ id: number;
261
+ action_digest: string;
262
+ } | {
263
+ type: "renew_name";
264
+ name: string;
265
+ years: number;
266
+ } | {
267
+ type: "transfer_name";
268
+ name: string;
269
+ to: string;
270
+ } | {
271
+ type: "release_name";
272
+ name: string;
273
+ }
274
+ /** `proof`: hex 32-byte hashes from the leaf (distribution_id, address, amount) to the distribution's Merkle root. */
275
+ | {
276
+ type: "claim_distribution";
277
+ distribution_id: number;
278
+ amount: string;
279
+ proof: string[];
280
+ }
281
+ /** Validators: a matured claim's PR was reverted by commit `revert_sha` (40 hex). */
282
+ | {
283
+ type: "attest_revert";
284
+ claim_id: number;
285
+ revert_sha: string;
286
+ }
287
+ /** Move `amount` drops into the shielded pool as the bundle's output notes. Signed; also burns the chain's `ghost_verify_fee`. */
288
+ | {
289
+ type: "shield";
290
+ amount: string;
291
+ bundle: GhostBundle;
292
+ }
293
+ /** Unsigned (the proof authorizes it): send it with `from`, `memo`, `public_key`, `signature` empty and `nonce` 0. Its `fee` leaves the pool. */
294
+ | {
295
+ type: "private_transfer";
296
+ bundle: GhostBundle;
297
+ }
298
+ /** Unsigned: pay `amount` drops out of the pool to `to` (address or name), plus the fee. */
299
+ | {
300
+ type: "unshield";
301
+ to: string;
302
+ amount: string;
303
+ bundle: GhostBundle;
304
+ }
305
+ /** Publish this account's 1,216-byte Ghost Mode address (hex) so wallets find it under the account's names. */
306
+ | {
307
+ type: "set_ghost_address";
308
+ address: string;
309
+ }
310
+ /** Validators: vote to pause Ghost Mode (it pauses once f + 1 of the epoch's validators have). */
311
+ | {
312
+ type: "ghost_pause";
313
+ }
314
+ /** A candidate's consensus key: its node is running, in the last tenth of `epoch` (the epoch the tx lands in). Changes nothing but the readiness record; refused until the members admitted it. Nodes send it themselves. */
315
+ | {
316
+ type: "validator_ready";
317
+ epoch: number;
318
+ }
319
+ /** An active member's consensus key admits candidate `validator` (an address) into the set at the end of `epoch` (the epoch the tx lands in): its operator's decision, once an epoch. */
320
+ | {
321
+ type: "admit_validator";
322
+ validator: string;
323
+ epoch: number;
324
+ };
325
+ /**
326
+ * What a ghost action carries (node/src/types.rs `GhostBundle`), every field lowercase hex: the
327
+ * chain `instance` (from `/api/ghost`), the `anchor` root, two 32-byte `nullifiers` and
328
+ * `commitments`, two note ciphertexts `enc` (1,401 bytes each) and outgoing ciphertexts `out`
329
+ * (80 bytes each), and the Action `proof`. Proofs come from the `blockula-ghost` prover; this SDK
330
+ * only encodes.
331
+ */
332
+ export interface GhostBundle {
333
+ instance: string;
334
+ anchor: string;
335
+ nullifiers: [string, string];
336
+ commitments: [string, string];
337
+ enc: [string, string];
338
+ out: [string, string];
339
+ proof: string;
340
+ }
341
+ /** What a `propose` asks for (node/src/types.rs `ProposalKind`): every former admin lever, parameters, spending, upgrades and features. */
342
+ export type ProposalKind =
343
+ /** Set a governance parameter (a key of node/src/params.rs `ChainParams`, e.g. "max_validators"), within its bounds. */
344
+ {
345
+ type: "param_change";
346
+ key: string;
347
+ value: string;
348
+ } | {
349
+ type: "treasury_spend";
350
+ to: string;
351
+ amount: string;
352
+ }
353
+ /** Open a community distribution of `total` drops, claimable with Merkle proofs until block `claim_until`. `distribution_id` is the id its tree was built for, one no distribution has yet (the node's `next_distribution_id`; at most its `max_distribution_id`). */
354
+ | {
355
+ type: "distribution";
356
+ distribution_id: number;
357
+ merkle_root: string;
358
+ total: string;
359
+ claim_until: number;
360
+ } | {
361
+ type: "set_repo";
362
+ repo: string;
363
+ weight: number;
364
+ }
365
+ /** milli-Soul, at most 100 Soul. */
366
+ | {
367
+ type: "grant_soul";
368
+ to: string;
369
+ amount: number;
370
+ reason: string;
371
+ } | {
372
+ type: "flag_sybil";
373
+ account: string;
374
+ reason: string;
375
+ } | {
376
+ type: "reject_claim";
377
+ claim_id: number;
378
+ reason: string;
379
+ } | {
380
+ type: "clawback";
381
+ account: string;
382
+ reason: string;
383
+ } | {
384
+ type: "unlink_github";
385
+ handle: string;
386
+ } | {
387
+ type: "refund_hunt";
388
+ hunt_id: number;
389
+ } | {
390
+ type: "schedule_upgrade";
391
+ version: number;
392
+ activation_height: number;
393
+ } | {
394
+ type: "activate_feature";
395
+ feature: string;
396
+ } | {
397
+ type: "deactivate_feature";
398
+ feature: string;
399
+ }
400
+ /** No on-chain effect: a signal. */
401
+ | {
402
+ type: "text";
403
+ }
404
+ /** Lift a sybil flag (`flag_sybil`'s appeal path): the account can earn again; nothing the flag took comes back. */
405
+ | {
406
+ type: "unflag_sybil";
407
+ account: string;
408
+ reason: string;
409
+ }
410
+ /** Withdraw the upgrade to `version` scheduled at `activation_height` (and any after it) before it activates (a supermajority, no timelock). Tag 15. */
411
+ | {
412
+ type: "cancel_upgrade";
413
+ version: number;
414
+ activation_height: number;
86
415
  };
87
416
  export interface UnsignedTx {
88
417
  chain_id: string;
418
+ /**
419
+ * The chain instance the tx is for: hex BLAKE3 digest of its genesis block (`genesis_hash` in
420
+ * `/api/status`). Signed right after `chain_id`, so the tx can't replay on another chain that
421
+ * reuses the id (e.g. a relaunched testnet). `Wallet.build` fills it in; offline signers pass it.
422
+ */
423
+ genesis_hash: string;
89
424
  /** The account acting; the signing key must be authorized on it. */
90
425
  from: string;
91
426
  nonce: number;
427
+ /** The most the sender will pay, in drops. The tx is charged its block's base fee + `tip` (see `txCharge`). */
92
428
  fee: string;
429
+ /** Drops paid to the block's proposer on top of the burned base fee (default "0"). Blocks take the highest tip per byte first. */
430
+ tip?: string;
431
+ /** Last block height at which the tx may execute (at most an hour of blocks ahead). After it, the tx can never execute. */
432
+ valid_until: number;
93
433
  action: Action;
94
434
  memo: string;
95
435
  }
@@ -99,14 +439,129 @@ export interface Tx extends UnsignedTx {
99
439
  }
100
440
  export declare const PUBLIC_KEY_LEN = 1952;
101
441
  export declare const SIGNATURE_LEN = 3309;
442
+ /** Domain of the unsigned ghost wire form (`private_transfer`, `unshield`). */
443
+ export declare const GHOST_TX_DOMAIN = "BLOCKULA_GHOST_V1";
444
+ export declare const GHOST_ENC_BYTES = 1401;
445
+ export declare const GHOST_OUT_BYTES = 80;
446
+ export declare const GHOST_ADDRESS_BYTES = 1216;
447
+ /** The Action circuit the node verifies proofs against (blockula-ghost `CIRCUIT_ID`). */
448
+ export declare const GHOST_CIRCUIT_ID = 1;
102
449
  export declare const DROPS_PER_FANG = 1000000000n;
450
+ /**
451
+ * The largest value of a whole-number field a tx carries as a JSON number, not a string (ids,
452
+ * heights, PR numbers, the nonce): 2^53 − 1, what a JavaScript number holds exactly
453
+ * (node/src/types.rs `MAX_JSON_INT`). The chain refuses larger ones, so every stored proposal
454
+ * kind and multisig action reads back exactly here, and its digest can be computed.
455
+ */
456
+ export declare const MAX_JSON_INT: bigint;
457
+ /**
458
+ * An unsigned integer field as the node reads it from JSON (node/src/types.rs: a JSON number,
459
+ * or for amounts a decimal string), checked to be in `0 ..= max`. Anything the node's JSON
460
+ * parser would refuse is refused here, so `signingBytes`/`txBytes` never encode a value other
461
+ * than the one in the tx object (no wrapping of negative or oversized numbers).
462
+ */
463
+ export declare function uintField(v: unknown, max: bigint, what?: string): bigint;
464
+ /** A u64 field (`uintField` up to 2^64 − 1). */
465
+ export declare const u64Field: (v: unknown, what?: string) => bigint;
466
+ /** A chain's genesis hash as its 32 bytes (`/api/status` `genesis_hash`, lowercase hex). */
467
+ export declare function genesisHashBytes(genesisHash: string): Uint8Array;
468
+ /** Unsigned ghost txs (`private_transfer`, `unshield`): no key signs them, their proof authorizes them. */
469
+ export declare function isUnsignedAction(a: Action): boolean;
470
+ /**
471
+ * The bytes a key signs (node/src/types.rs `Tx::signing_bytes`). For an unsigned ghost tx this is
472
+ * its whole wire form instead: `BLOCKULA_GHOST_V1 ‖ chain_id ‖ genesis hash ‖ fee ‖ tip ‖ valid_until ‖ action`.
473
+ */
103
474
  export declare function signingBytes(tx: UnsignedTx): Uint8Array;
475
+ /**
476
+ * What a ghost tx's Action proof is bound to (node/src/types.rs `Tx::ghost_sighash`):
477
+ * BLAKE3-KDF("blockula ghost v1 tx sighash", chain_id ‖ genesis hash ‖ tag ‖ valid_until ‖ fee ‖
478
+ * tip ‖ the tag's own fields (shield: from, nonce, amount; unshield: to, amount) ‖ the bundle
479
+ * without its proof ‖ circuit id). A wallet proves with this as the witness's sighash, then fills
480
+ * in the proof.
481
+ */
482
+ export declare function ghostSighash(tx: UnsignedTx): Uint8Array;
483
+ /**
484
+ * What a Séance juror seals before revealing (node/src/types.rs `seance_commitment`): hex
485
+ * BLAKE3 of the Séance id, the juror's account, the votes, spam flags and a secret salt.
486
+ */
487
+ export declare function seanceCommitment(seanceId: number, juror: string, votes: string, spam: number[], salt: string): string;
488
+ /**
489
+ * A validator's randomness-beacon commitment (node/src/beacon.rs `commitment`): hex BLAKE3 in
490
+ * derive-key mode ("blockula beacon commitment v1") over the chain id, the target epoch, the
491
+ * validator's address and its 32-byte hex secret. Strings are u64-length-prefixed, integers
492
+ * u64 little-endian.
493
+ */
494
+ export declare function beaconCommitment(chainId: string, epoch: number, validator: string, secret: string): string;
495
+ /** "2.5" Soul → 2500 milli-Soul. */
496
+ export declare function parseSoul(soul: string | number): number;
497
+ /**
498
+ * What a `multisig_approve` binds (node/src/types.rs `action_digest`): BLAKE3 (derive-key mode,
499
+ * context "blockula multisig action v1") of the action's encoding, as inside the signing bytes.
500
+ * Compute it from the action you show the approver (`client.multisig(account)` `pending[].action`).
501
+ */
502
+ export declare function actionDigest(action: Action): string;
503
+ /**
504
+ * What a `vote` binds (node/src/types.rs `proposal_digest`): the proposal's kind (accounts as
505
+ * stored, resolved), title and link. Compute it from the proposal you show the voter.
506
+ */
507
+ export declare function proposalDigest(kind: ProposalKind, title: string, url?: string): string;
508
+ /** One claim of a Séance pair, as the juror judged it. */
509
+ export interface SeanceClaimRef {
510
+ id: number;
511
+ repo: string;
512
+ pr: number;
513
+ }
514
+ /**
515
+ * What a `commit_votes` binds (node/src/types.rs `seance_pairs_digest`): the Séance, the juror and,
516
+ * per assigned pair in order, both claims' ids, repos and PR numbers.
517
+ */
518
+ export declare function seancePairsDigest(seanceId: number, juror: string, pairs: [SeanceClaimRef, SeanceClaimRef][]): string;
519
+ /** FIPS 204 context string for a key's proof of possession in `add_key` (node/src/types.rs `KEY_POP_CONTEXT`). */
520
+ export declare const KEY_POP_CONTEXT: Uint8Array<ArrayBuffer>;
521
+ /**
522
+ * What a key signs to consent to being added to `account` (node/src/types.rs `key_pop_message`):
523
+ * the chain instance, the account and the key's own id (audit gap-7-2).
524
+ */
525
+ export declare function keyPopMessage(chainId: string, genesisHash: string, account: string, keyId: string): Uint8Array;
104
526
  /** FIPS 204 context string for validator proofs of possession (node/src/types.rs `POP_CONTEXT`). */
105
527
  export declare const POP_CONTEXT: Uint8Array<ArrayBuffer>;
106
528
  /** What a validator's consensus key signs to register (node/src/types.rs `pop_message`). */
107
529
  export declare function popMessage(chainId: string, owner: string, p2pAddr: string, httpAddr: string): Uint8Array;
108
- /** Mirrors `min_fee` in node/src/types.rs: base fee is priced per byte and burned. */
530
+ /** Wire size in bytes (node/src/types.rs `Tx::size`): signing bytes plus the key and signature (none for an unsigned ghost tx). Fees are priced on it. */
531
+ export declare function txSize(tx: UnsignedTx): number;
532
+ /**
533
+ * A block's base fee (node/src/econ.rs `FeeSlot`): `flat` drops per tx plus `rate` milli-drops per
534
+ * byte. It moves with block fullness and is fixed 17 blocks ahead; `/api/fees` serves the upcoming
535
+ * ones and `suggested`, the highest of them (what `Wallet.build` prices txs at).
536
+ */
537
+ export interface BaseFee {
538
+ flat: string | bigint;
539
+ rate: string | bigint;
540
+ }
541
+ /** The base fee at its genesis floor: 10,000 drops + 10 per byte (`min_fee`). */
542
+ export declare const FLOOR_BASE_FEE: BaseFee;
543
+ /** Mirrors `FeeSlot::fee` in node/src/econ.rs: `flat + rate × size / 1000`, rounded down. Burned. */
544
+ export declare function baseFee(tx: UnsignedTx, fee?: BaseFee): bigint;
545
+ /** Mirrors `min_fee` in node/src/types.rs: the base fee at its floor (an idle chain's). */
109
546
  export declare function minFee(tx: UnsignedTx): bigint;
547
+ /** The chain's default `tip_cap_multiple` (node/src/params.rs): a tip may be at most this many times the base fee of the block that includes it. */
548
+ export declare const DEFAULT_TIP_CAP_MULTIPLE = 20;
549
+ /**
550
+ * The most this tx may tip in a block with this base fee (node/src/econ.rs `max_tip`): `multiple` × its base fee. Nodes refuse
551
+ * a bigger tip. `/api/fees` serves the chain's `tip_cap_multiple` and `lowest`, the base fee a tip fits under in any upcoming block.
552
+ * Tips are also paid only from transferable FANG (locks hold them), and a multisig's owner keys or a validator's consensus key
553
+ * acting for its owner can't tip at all.
554
+ */
555
+ export declare function maxTip(tx: UnsignedTx, fee?: BaseFee, multiple?: number | bigint): bigint;
556
+ /** What the tx is charged in a block with this base fee (node/src/econ.rs `charge`): base fee + tip. Its `fee` must cover it; nothing more is debited. */
557
+ export declare function txCharge(tx: UnsignedTx, fee?: BaseFee): bigint;
558
+ /**
559
+ * Wire form (node/src/types.rs `Tx::to_bytes`): signing bytes ‖ public key (1,952 B) ‖ signature (3,309 B), or just the
560
+ * unsigned form for an unsigned ghost tx. Blocks and gossip carry this; `POST /api/tx` takes it as `application/octet-stream`.
561
+ */
562
+ export declare function txBytes(tx: Tx): Uint8Array;
563
+ /** A tx's id (node/src/types.rs `Tx::id`): hex BLAKE3 of the signing bytes and the signature. Known before submitting. */
564
+ export declare function txId(tx: Tx): string;
110
565
  /** "1.5" → 1500000000n drops. Accepts numbers, decimal strings or bigint drops. */
111
566
  export declare function parseFang(amount: string | number | bigint): bigint;
112
567
  export declare function formatFang(drops: bigint | string): string;