@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/index.d.ts CHANGED
@@ -1,10 +1,236 @@
1
- import { type Action, type Tx, type UnsignedTx } from "./tx.js";
1
+ import { type SeanceClaimRef, type Action, type BaseFee, type ProposalKind, type Tx, type UnsignedTx } from "./tx.js";
2
+ import { type ProofResponse, type ProvenRecord } from "./proof.js";
2
3
  export * from "./tx.js";
4
+ export * from "./proof.js";
5
+ export * from "./distribution.js";
6
+ export * from "./release.js";
7
+ export * from "./describe.js";
3
8
  export declare const DEFAULT_RPC = "http://localhost:7070";
4
- export declare function addressFromPublicKey(publicKey: Uint8Array): string;
9
+ /** Address prefixes: `boo` on mainnet (and dev chains), `tboo` on public testnets. */
10
+ export declare const KNOWN_PREFIXES: readonly ["boo", "tboo"];
11
+ export declare const DEFAULT_PREFIX = "boo";
12
+ /** Mainnet's chain id (node/src/chain.rs `MAINNET_CHAIN_ID`). */
13
+ export declare const MAINNET_CHAIN_ID = "blockula-1";
14
+ /** How long a transaction stays valid by default: 600 blocks (10 minutes at 1 s blocks). */
15
+ export declare const DEFAULT_VALID_FOR_BLOCKS = 600;
16
+ /** The address of a public key: bech32m(prefix, BLAKE3(public key)). */
17
+ export declare function addressFromPublicKey(publicKey: Uint8Array, prefix?: string): string;
5
18
  /** A key's id: BLAKE3(public key) as hex. Same 32 bytes as inside the `boo1…` address it derives. */
6
19
  export declare function keyId(publicKey: Uint8Array): string;
7
- export declare function isAddress(s: string): boolean;
20
+ /** The prefix of a canonical address (`boo`, `tboo`), or `undefined` if `s` isn't one. */
21
+ export declare function addressPrefix(s: string): string | undefined;
22
+ /** Whether `s` is an address: with any known prefix, or exactly `prefix` when given. */
23
+ export declare function isAddress(s: string, prefix?: string): boolean;
24
+ /** An amount of FANG: a decimal string ("1.5"), a number, or bigint drops. */
25
+ export type Amount = string | number | bigint;
26
+ /** A `.boo` name as the chain stores it (node/src/types.rs `normalize_name`): lowercase, without the suffix. */
27
+ export declare function bareName(name: string): string;
28
+ /**
29
+ * The most `Wallet.propose` bonds by default without being told (audit gap-7-5): mainnet's genesis
30
+ * `proposal_deposit` (node/src/params.rs). A node reporting more is refused; pass `deposit`.
31
+ */
32
+ export declare const DEFAULT_MAX_PROPOSAL_DEPOSIT: bigint;
33
+ /** Highest vote conviction (node/src/params.rs `MAX_CONVICTION`). */
34
+ export declare const MAX_CONVICTION = 6;
35
+ /** Lock periods a vote at each conviction locks its amount for (params.rs `CONVICTION_PERIODS`) … */
36
+ export declare const CONVICTION_PERIODS: readonly [0, 1, 2, 4, 8, 16, 32];
37
+ /** … and its weight in tenths of the amount (`CONVICTION_TENTHS`): 0.1× with no lock, then 1×–6×. */
38
+ export declare const CONVICTION_TENTHS: readonly [1, 10, 20, 30, 40, 50, 60];
39
+ /** A vote's weight in drops: `amount` × the conviction multiplier (params.rs `vote_weight`). */
40
+ export declare function convictionWeight(amount: Amount, conviction: number): bigint;
41
+ /**
42
+ * Builders for `Wallet.propose` kinds (node/src/types.rs `ProposalKind`). Amounts are FANG (or
43
+ * bigint drops), Soul is in Soul ("2.5"); names in `to`/`account` are resolved when proposing.
44
+ */
45
+ export declare const proposal: {
46
+ /** Set a governance parameter (a key of `/api/params`, e.g. "max_validators") to a raw value (drops, blocks, bps …), within its bounds. */
47
+ paramChange(key: string, value: bigint | number | string): ProposalKind;
48
+ /** Pay from the treasury (spends above a share of the treasury need a supermajority). */
49
+ treasurySpend(to: string, amount: Amount): ProposalKind;
50
+ /**
51
+ * Open a community distribution of `total`, claimable with Merkle proofs against `merkleRoot` until block `claimUntil`.
52
+ * `distributionId` is the id the tree was built for (`buildDistribution(id, …)`): one no distribution has yet,
53
+ * at most 1,000 past the next proposal id (`client.proposals()`'s `next_distribution_id` is free, and
54
+ * `max_distribution_id` is the largest allowed; the range only grows). Other proposals landing first don't change
55
+ * it, so a multisig can take its time approving; if a distribution with that id opens first, the node refuses this
56
+ * one (nothing is escrowed), or it fails when it runs. Claims close at most 730 days after the proposal's vote ends.
57
+ */
58
+ distribution(distributionId: number, merkleRoot: string, total: Amount, claimUntil: number): ProposalKind;
59
+ /** Put a repo in the contribution pool (weight 1–100; 0 removes it). */
60
+ setRepo(repo: string, weight: number): ProposalKind;
61
+ /** Grant Soul (in Soul, "2.5"; at most 100 per grant). */
62
+ grantSoul(to: string, soul: string | number, reason: string): ProposalKind;
63
+ flagSybil(account: string, reason: string): ProposalKind;
64
+ /** Lift a sybil flag: the appeal path for `flagSybil` (nothing the flag took comes back). */
65
+ unflagSybil(account: string, reason: string): ProposalKind;
66
+ rejectClaim(claimId: number, reason: string): ProposalKind;
67
+ clawback(account: string, reason: string): ProposalKind;
68
+ unlinkGithub(handle: string): ProposalKind;
69
+ /** Refund every funder of a hunt (escrow can be refunded, never redirected). */
70
+ refundHunt(huntId: number): ProposalKind;
71
+ /**
72
+ * Switch to protocol `version` at block `activationHeight` (needs a supermajority). The version is newer than
73
+ * every one scheduled or withdrawn (`client.upgrade()`'s `withdrawn.highest_version`) and at most 16 past the
74
+ * newest scheduled, withdrawn or superseded (`next_version` is the number to use); the activation is at most
75
+ * 365 days after the proposal's vote ends.
76
+ */
77
+ scheduleUpgrade(version: number, activationHeight: number): ProposalKind;
78
+ /**
79
+ * Withdraw the upgrade to protocol `version` scheduled at block `activationHeight` (see
80
+ * `client.upgrade()`), and any scheduled after it, before it activates. Needs a supermajority;
81
+ * there's no timelock (it runs the block after its vote), and it must run at least 64 blocks
82
+ * before the activation height, so propose it at least `voting_blocks + 65` blocks ahead.
83
+ */
84
+ cancelUpgrade(version: number, activationHeight: number): ProposalKind;
85
+ /** Turn on a feature flag (e.g. "ghost"). */
86
+ activateFeature(feature: string): ProposalKind;
87
+ deactivateFeature(feature: string): ProposalKind;
88
+ /** A signal with no on-chain effect. */
89
+ text(): ProposalKind;
90
+ };
91
+ /** One pool an account has stake in (`/api/staking/{account}` `delegations[]`). */
92
+ export interface StakeDelegation {
93
+ validator: string;
94
+ validator_name: string | null;
95
+ /** Pool shares held (what `undelegate` takes). */
96
+ shares: string;
97
+ /** Their current value, in drops. */
98
+ value: string;
99
+ /** What went in, less what sales and slashes took (value above it is earnings). */
100
+ principal: string;
101
+ /** This is the validator's owner's self-bond. */
102
+ self_bond: boolean;
103
+ }
104
+ /** Stake on its way out (`entries[]` of type `unbonding`): paid out by `withdrawUnbonded` from `completes_at`. */
105
+ export interface StakeUnbonding {
106
+ id: number;
107
+ validator: string;
108
+ amount: string;
109
+ started_at: number;
110
+ completes_at: number;
111
+ ready: boolean;
112
+ }
113
+ /** Stake moved between pools (`entries[]` of type `redelegation`): slashable by `from` until `completes_at`. */
114
+ export interface StakeRedelegation {
115
+ id: number;
116
+ from: string;
117
+ to: string;
118
+ amount: string;
119
+ completes_at: number;
120
+ }
121
+ /** An account's stake, from `/api/staking/{account}`. */
122
+ export interface StakeSummary {
123
+ delegations: StakeDelegation[];
124
+ unbonding: StakeUnbonding[];
125
+ redelegations: StakeRedelegation[];
126
+ /** Total value staked, in drops. */
127
+ bonded: string;
128
+ /** Total unbonding, in drops. */
129
+ unbonding_total: string;
130
+ /** Unbonding that has finished (what `withdrawUnbonded` pays now), in drops. */
131
+ withdrawable: string;
132
+ /** The node's plain-English summary. */
133
+ summary: string;
134
+ }
135
+ export declare function stakeSummary(raw: unknown): StakeSummary;
136
+ /**
137
+ * Shares worth about `value` drops in a delegation (rounded down, at most all of them), at the
138
+ * value the delegation reports. That's a node's word: to unbond an amount, pass
139
+ * `wallet.undelegate(validator, { amount })`, which the chain converts itself (audit gap-7-5).
140
+ */
141
+ export declare function sharesFor(d: StakeDelegation, value: Amount): bigint;
142
+ /** `/api/params`' governance parameters as a key → value map (values as strings: amounts can exceed 2^53). */
143
+ export declare function paramsOf(raw: unknown): Record<string, string>;
144
+ /** A proposal, from `/api/proposals` (`proposals[]`) or `/api/proposal/{id}`. Amounts are in drops. */
145
+ export interface ProposalSummary {
146
+ id: number;
147
+ title: string;
148
+ url: string;
149
+ /**
150
+ * The node's own summary text. No digest covers it, so a lying node can make it say anything
151
+ * (audit gap-7-6): show `does` instead, and never present this as what the proposal does.
152
+ */
153
+ summary: string;
154
+ /** What it does, rendered here from `kind` (`describeKind`): what a vote on it binds. */
155
+ does: string;
156
+ kind: ProposalKind | null;
157
+ /**
158
+ * `proposalDigest(kind, title, url)`: what a vote binds. `null` when this client can't compute
159
+ * it exactly (`digest_error` says why, e.g. a number past 2^53): it can't vote on it either.
160
+ */
161
+ digest: string | null;
162
+ digest_error?: string;
163
+ proposer: string | null;
164
+ proposer_name: string | null;
165
+ /** `voting`, `queued`, `rejected`, `executed` or `failed`. */
166
+ status: string;
167
+ deposit: string;
168
+ /** Conviction-weighted ayes and nays (what the majority counts) … */
169
+ aye: string;
170
+ nay: string;
171
+ /** … and the raw FANG behind them (what quorum counts). */
172
+ aye_amount: string;
173
+ nay_amount: string;
174
+ /** aye_amount + nay_amount. */
175
+ turnout: string;
176
+ voters: number;
177
+ /** The quorum it had to reach and whether it did: known once voting closed. */
178
+ quorum?: string;
179
+ quorum_reached?: boolean;
180
+ /** Bootstrap-council votes so far (one per validator); `of` is the set's size at the close. */
181
+ council: {
182
+ ayes: number;
183
+ nays: number;
184
+ of?: number;
185
+ };
186
+ /** Whether it needs `supermajority_bps` of the weight (upgrades, feature activations, issuance parameters, large spends). */
187
+ supermajority: boolean;
188
+ /** Last block votes count in, and when a passed proposal runs (after the timelock). */
189
+ voting_ends_at: number;
190
+ executes_at?: number;
191
+ /** Why it was rejected or failed, or what it did. */
192
+ outcome: string;
193
+ /** With `rules` (`/api/proposals`' `params`): the share of the weight its ayes need, in basis points. */
194
+ threshold_bps?: number;
195
+ }
196
+ export declare function proposalSummary(raw: unknown, rules?: {
197
+ supermajority_bps?: number;
198
+ }): ProposalSummary;
199
+ /** Per-transaction options. */
200
+ export interface TxOptions {
201
+ /** Paid to the block's proposer on top of the base fee: FANG ("0.001") or bigint drops. Default: the wallet's `tip` (0). At most `tip_cap_multiple` (20) × the base fee (`maxTip`), from transferable FANG. */
202
+ tip?: string | number | bigint;
203
+ /** Blocks from now the tx stays valid (at most the chain's `max_tx_validity_blocks`, an hour of blocks). Default: the wallet's `validForBlocks` (600). */
204
+ validForBlocks?: number;
205
+ }
206
+ /** `Wallet.build`'s options: a tx's, plus the resolutions of names it carries as addresses. */
207
+ export interface BuildOptions extends TxOptions {
208
+ /** `Client.resolution`s of names in `action`'s address fields (refused on mainnet unless proven). */
209
+ resolutions?: Resolution[];
210
+ }
211
+ /**
212
+ * A key's consent to being added to one account (audit gap-7-2): its public key and its
213
+ * signature over `keyPopMessage(chain_id, genesis_hash, account, key_id)` (context
214
+ * `KEY_POP_CONTEXT`). The key's holder makes it (`Wallet.keyGrant`) and hands it to the account's
215
+ * owner (`encodeKeyGrant`: a grant code to paste), who adds the key with it (`addOwnerKey`,
216
+ * `addSessionKey`). Nobody can put a key on an account without it, so `/api/key` lists only
217
+ * accounts the key agreed to.
218
+ */
219
+ export interface KeyGrant {
220
+ /** The account the key agrees to join. */
221
+ account: string;
222
+ key_id: string;
223
+ /** Hex ML-DSA-65 public key. */
224
+ public_key: string;
225
+ /** Hex proof of possession. */
226
+ pop: string;
227
+ }
228
+ /** A grant as one pasteable string: `bkgrant1.<account>.<base64url(public key ‖ pop)>`. */
229
+ export declare function encodeKeyGrant(g: KeyGrant): string;
230
+ /** Parses a grant code (`encodeKeyGrant`). Whitespace is ignored, so a wrapped paste works. */
231
+ export declare function decodeKeyGrant(code: string): KeyGrant;
232
+ /** Whether `g` is a valid consent by its key to join `g.account` on the chain `(chainId, genesisHash)`. */
233
+ export declare function verifyKeyGrant(g: KeyGrant, chainId: string, genesisHash: string): boolean;
8
234
  /**
9
235
  * Wallet = one ML-DSA-65 key (from a 32-byte seed, FIPS 204 ξ) acting for one account.
10
236
  * By default the account is the key's own address. Call `actAs(account)` to use a key that
@@ -14,16 +240,30 @@ export declare class Wallet {
14
240
  readonly seed: Uint8Array;
15
241
  client: Client;
16
242
  readonly publicKey: Uint8Array;
17
- /** This key's own address. */
18
- readonly address: string;
19
- /** The account this wallet acts for (defaults to `address`). */
20
- account: string;
21
243
  /** WebAuthn credential id, when the wallet was unlocked by a passkey. Not secret. */
22
244
  credentialId?: Uint8Array;
245
+ /** Default tip (drops) for this wallet's transactions. */
246
+ tip: bigint;
247
+ /** Default validity (blocks from now) for this wallet's transactions. */
248
+ validForBlocks: number;
23
249
  private readonly secretKey;
250
+ private acting?;
251
+ /** How `actAs` found the account, when that was one node's unproven word (checked when signing on mainnet). */
252
+ private actingUnproven?;
24
253
  private constructor();
254
+ /** This key's own address, with the chain's prefix once the client knows it (`await client.addressPrefix()`). */
255
+ get address(): string;
256
+ /** The account this wallet acts for (defaults to `address`). */
257
+ get account(): string;
258
+ set account(account: string);
25
259
  get keyId(): string;
26
- /** Act for another account this key has been authorized on. Accepts a name or address. */
260
+ /**
261
+ * Act for another account this key has been authorized on. Accepts a name or address. A name
262
+ * needs an address here (every tx names the account it acts for), so it's resolved: proven with
263
+ * the client's witnesses. Without them it's one node's word, and on mainnet nothing is signed
264
+ * for an account found that way (`UnprovenNameError`): check the address and pass it instead
265
+ * (audit gap-7-1).
266
+ */
27
267
  actAs(account: string): Promise<this>;
28
268
  static generate(client?: Client): Wallet;
29
269
  static fromSeed(seed: string | Uint8Array, client?: Client): Wallet;
@@ -34,30 +274,88 @@ export declare class Wallet {
34
274
  static fromPasskeyPrf(prfOutput: Uint8Array, client?: Client): Wallet;
35
275
  get seedHex(): string;
36
276
  sign(tx: UnsignedTx): Tx;
37
- build(action: Action, memo?: string): Promise<Tx>;
38
- /** Send FANG to a `.boo` name or `boo1…` address. `amount` is in FANG ("1.5") or bigint drops. */
277
+ /**
278
+ * This key's consent to being added to `account` (an address, or a name resolved by the
279
+ * client: proven when it has witnesses; on mainnet an unproven name is refused, pass the address)
280
+ * on the client's chain: hand `encodeKeyGrant(grant)` to the account's owner, who adds the key
281
+ * with it. Pass `chain` to sign offline.
282
+ */
283
+ keyGrant(account: string | Resolution, chain?: {
284
+ chainId: string;
285
+ genesisHash: string;
286
+ }): Promise<KeyGrant>;
287
+ /**
288
+ * The `add_key` action for a grant (an object or its code): it must be for this account and
289
+ * verify on the client's chain, so a wrong or damaged code fails here, before anything is signed.
290
+ */
291
+ private grantAction;
292
+ /**
293
+ * Builds and signs a tx: `fee` = the highest base fee already fixed for the next blocks
294
+ * (`/api/fees` `suggested`) + `tip`, `valid_until` = the current height + `validForBlocks`, and
295
+ * the chain's id and genesis hash from `/api/status`. Only the base fee of the block that
296
+ * includes it (+ the tip) is charged. A tip above `tip_cap_multiple` × the lowest upcoming base
297
+ * fee (`/api/fees` `lowest`, see `maxTip`) is refused here, as nodes would refuse it. To sign
298
+ * offline, build an `UnsignedTx` yourself (with the chain's `genesis_hash`) and `sign` it.
299
+ *
300
+ * `action` may be a function of the height `valid_until` is counted from, for actions that
301
+ * carry an absolute block height of their own (a session key's or a hunt's expiry): computed
302
+ * from the same status read, a node that lies about the height can stretch them by at most
303
+ * `max_tx_validity_blocks`, since validators refuse a `valid_until` further ahead than that
304
+ * (audit gap-7-3).
305
+ *
306
+ * That height is checked first (`Client.checkSigningHeight`: against the witnesses' heads and,
307
+ * when the client knows its genesis clock, the clock), since a node reporting one the chain
308
+ * hasn't reached gets a tx it can hold and release later.
309
+ *
310
+ * `opts.resolutions`: how names in fields that need an address got into `action` (their
311
+ * `Client.resolution`s). On mainnet a tx carrying one that only one node vouched for isn't
312
+ * signed (`UnprovenNameError`), checked against the very status the tx is signed for, as the
313
+ * helpers do (audit gap-7-1). Fields the chain resolves itself take `Client.recipient(x).signed`.
314
+ */
315
+ build(action: Action | ((height: number) => Action), memo?: string, opts?: BuildOptions): Promise<Tx>;
316
+ /**
317
+ * `build`, refusing on mainnet a tx that carries an address only one node vouched for: `unproven`
318
+ * (the helpers' resolutions of names in fields that need an address) or the account `actAs`
319
+ * found that way (audit gap-7-1). Checked against the very status the tx is signed for.
320
+ */
321
+ private buildChecked;
322
+ /**
323
+ * Send FANG to a `.boo` name or an address. `amount` is in FANG ("1.5") or bigint drops. A name
324
+ * is signed as its proven owner's address when the client has witnesses (who you checked is who
325
+ * gets paid, even if the name changes hands before the tx runs), and as the name itself when it
326
+ * doesn't: the chain then pays whoever owns it when the tx runs. A lying node can't point it at
327
+ * another account now, but it can hold the signed tx until its validity window, which counts
328
+ * from the height the node reported, and release it later, by when the name may have lapsed
329
+ * and been registered again (audit gap-7-1, review-r3-clients-2). See `Client.recipient`.
330
+ */
39
331
  send(to: string, amount: string | number | bigint, opts?: {
40
332
  memo?: string;
41
333
  wait?: boolean;
42
- }): Promise<any>;
334
+ } & TxOptions): Promise<any>;
43
335
  registerName(name: string, opts?: {
44
336
  wait?: boolean;
45
- }): Promise<any>;
46
- /** Authorize another device's key (e.g. a second passkey) with full control. */
47
- addOwnerKey(keyIdHex: string, label: string): Promise<any>;
337
+ } & TxOptions): Promise<any>;
338
+ /**
339
+ * Authorize another device's key (e.g. a second passkey) with full control. `grant` is the
340
+ * key's consent to this account (`keyGrant` on that device, or its grant code).
341
+ */
342
+ addOwnerKey(grant: KeyGrant | string, label: string): Promise<any>;
48
343
  /**
49
- * Let an agent/app key spend from this account, transfers only, within a limit.
50
- * Example: `addSessionKey(agentKeyId, "claude", { limit: "10", periodBlocks: 86_400, expiresInBlocks: 30 * 86_400 })`.
344
+ * Let an agent/app key spend from this account, transfers only, within a limit. `grant` is the
345
+ * key's consent to this account (the agent's grant code).
346
+ * Example: `addSessionKey(grantCode, "claude", { limit: "10", periodBlocks: 86_400, expiresInBlocks: 30 * 86_400 })`.
51
347
  */
52
- addSessionKey(keyIdHex: string, label: string, opts: {
348
+ addSessionKey(grant: KeyGrant | string, label: string, opts: {
53
349
  limit: string | number | bigint;
54
350
  periodBlocks: number;
55
351
  expiresInBlocks: number;
56
352
  }): Promise<any>;
57
353
  removeKey(keyIdHex: string): Promise<any>;
58
354
  /**
59
- * Offer a validator: bonds `bond` FANG from this account. `consensusKeyHex` is the validator
60
- * node's ML-DSA-65 public key (see `blockula validator init`). Pending until an admin approves.
355
+ * Register a validator owned by this account, self-bonding `bond` FANG into its stake pool (at
356
+ * least the chain's `min_self_bond`). `consensusKey` is the validator node's ML-DSA-65 public
357
+ * key and `pop` its proof of possession (see `blockula validator init`). It's a candidate: at
358
+ * each epoch boundary the top `max_validators` pools by stake form the next active set.
61
359
  */
62
360
  registerValidator(opts: {
63
361
  consensusKey: string;
@@ -66,9 +364,9 @@ export declare class Wallet {
66
364
  bond: string | number | bigint;
67
365
  pop: string;
68
366
  }): Promise<any>;
69
- /** Season 0 admins only. */
367
+ /** Dev and test chains with admins only: pin a validator into the set ahead of stake. */
70
368
  approveValidator(validator: string): Promise<any>;
71
- /** Season 0 admins only. */
369
+ /** Dev and test chains with admins only: take a validator out of the set for good. */
72
370
  removeValidator(validator: string): Promise<any>;
73
371
  /** Claim a GitHub handle. Verify it by creating a public gist (as that user) containing this account's address. */
74
372
  linkGithub(handle: string, gistId: string): Promise<any>;
@@ -82,13 +380,196 @@ export declare class Wallet {
82
380
  expiresInBlocks: number;
83
381
  }): Promise<any>;
84
382
  fundHunt(huntId: number, amount: string | number | bigint): Promise<any>;
85
- /** Pay a hunt's bounty (creator or admin). `to` may be a .boo name; it's resolved and the address is signed. */
383
+ /** Pay a hunt's bounty (creator or admin). `to` may be a .boo name: signed as `Client.recipient` says (the proven address, or the name for the chain to resolve). */
86
384
  awardHunt(huntId: number, to: string, pr: number, familiarKey?: string): Promise<any>;
87
385
  cancelHunt(huntId: number): Promise<any>;
88
386
  /** Mark one of this account's session keys (an agent) as a Familiar. */
89
387
  registerFamiliar(keyIdHex: string, label: string): Promise<any>;
388
+ /** Claim a merged PR (authored by this account's linked GitHub handle) for the contribution pool. Bonded; validators check it on GitHub. */
389
+ submitClaim(repo: string, pr: number, familiarKey?: string): Promise<any>;
390
+ /** Stake 10 FANG on a newcomer being a real, distinct person (needs 10 Soul). */
391
+ vouch(account: string): Promise<any>;
392
+ /** Withdraw your vouch for `account` (after the lock), or pass your own account to decline one. */
393
+ unvouch(account: string): Promise<any>;
394
+ /** Join (or top up) the Séance juror pool. Needs 5 Soul; owner keys only. */
395
+ joinJury(bond?: string | number | bigint): Promise<any>;
396
+ leaveJury(): Promise<any>;
397
+ /**
398
+ * Seal a Séance judgment: one of "a", "b" or "=" per assigned pair (see `client.seance(id)`),
399
+ * plus claim ids you think are spam. Keep the returned `salt`: `revealVotes` needs it.
400
+ *
401
+ * The judgment binds the pairs it was made on (audit gap-7-6): pass `pairs`, the claims (id,
402
+ * repo, PR) you showed the juror in order, or they're read from the client (`seancePairs`). A
403
+ * node that showed other pairs or PRs makes the commitment fail instead of misdirecting it.
404
+ */
405
+ sealVotes(seanceId: number, votes: string, spam?: number[], salt?: string, opts?: {
406
+ pairs?: [SeanceClaimRef, SeanceClaimRef][];
407
+ }): Promise<{
408
+ tx: any;
409
+ salt: string;
410
+ votes: string;
411
+ spam: number[];
412
+ }>;
413
+ revealVotes(seanceId: number, votes: string, spam: number[], salt: string): Promise<any>;
414
+ fundPool(amount: string | number | bigint): Promise<any>;
415
+ /** Withdraw every contribution reward that has vested so far. */
416
+ withdrawVested(): Promise<any>;
417
+ /** Admins of dev and test chains only (elsewhere: a governance proposal). Weight 1–100; 0 removes the repo. */
418
+ setRepo(repo: string, weight: number): Promise<any>;
419
+ /** Admins of dev and test chains only (elsewhere: a governance proposal). `soul` in Soul ("2.5"), up to 100 per grant. */
420
+ grantSoul(to: string, soul: string | number, reason: string): Promise<any>;
421
+ /** Admins of dev and test chains only (elsewhere: a governance proposal). */
422
+ rejectClaim(claimId: number, reason: string): Promise<any>;
423
+ /** Admins of dev and test chains only (elsewhere: a governance proposal). */
424
+ flagSybil(account: string, reason: string): Promise<any>;
425
+ /** Admins of dev and test chains only (elsewhere: a governance proposal). */
426
+ clawback(account: string, reason: string): Promise<any>;
90
427
  /** Reclaim the bond of a removed validator this account owns. */
91
428
  unbond(validator: string): Promise<any>;
429
+ /** Submits one action (the shared tail of the helpers below); `unproven`: see `buildChecked`. */
430
+ private act;
431
+ /**
432
+ * A validator by address, or by a `.boo` name its account holds. Staking needs the address, so
433
+ * a name is resolved (proven with the client's witnesses); on mainnet a tx with an unproven one
434
+ * isn't signed (audit gap-7-1): pass the validator's address.
435
+ */
436
+ private validatorAddress;
437
+ /** `r`, unless it's an unproven name on mainnet (`UnprovenNameError`); `buildChecked` checks again against the signing status. */
438
+ private addressNeeded;
439
+ /** Stake `amount` (FANG, or bigint drops) in a validator's pool. Your stake earns its share of issuance and is slashed with the pool. */
440
+ delegate(validator: string, amount: Amount, opts?: TxOptions): Promise<any>;
441
+ /**
442
+ * Start unbonding stake in a validator's pool: `{ amount }` (FANG, or bigint drops), `shares`,
443
+ * or `"all"` (every share you hold there, read from `/api/staking`). An amount is signed as an
444
+ * amount and the chain converts it at the pool's price when the tx runs, so no node's report of
445
+ * the stake decides how much unbonds (audit gap-7-5); prefer it to `sharesFor`. It stops
446
+ * earning now and can be withdrawn with `withdrawUnbonded` once the unbonding period (21 days
447
+ * on mainnet) is over.
448
+ */
449
+ undelegate(validator: string, shares: bigint | string | "all" | {
450
+ amount: Amount;
451
+ }, opts?: TxOptions): Promise<any>;
452
+ /** Move `shares` (or `"all"`) from one pool to another without waiting out the unbonding period. */
453
+ redelegate(fromValidator: string, toValidator: string, shares: bigint | string | "all", opts?: TxOptions): Promise<any>;
454
+ /** Pay out every unbonding entry that has finished unbonding. */
455
+ withdrawUnbonded(opts?: TxOptions): Promise<any>;
456
+ /** A validator's owner: set the pool's commission (basis points, 0–10000; it moves a little per epoch at most) and, optionally, new addresses. */
457
+ updateValidator(opts: {
458
+ commissionBps: number;
459
+ p2pAddr?: string;
460
+ httpAddr?: string;
461
+ } & TxOptions): Promise<any>;
462
+ /** Bring a jailed validator back (its owner, after the jail period). */
463
+ unjail(validator: string, opts?: TxOptions): Promise<any>;
464
+ /** Low-level (nodes do this automatically): two conflicting signed votes, hex-encoded as the node's evidence reporter emits them. */
465
+ reportEquivocation(evidenceHex: string, opts?: TxOptions): Promise<any>;
466
+ /** Low-level (validator nodes do this automatically): commit to a beacon secret for `epoch`. */
467
+ beaconCommit(epoch: number, commitmentHex: string, opts?: TxOptions): Promise<any>;
468
+ /** Low-level (validator nodes do this automatically): reveal the beacon secret committed for `epoch`. */
469
+ beaconReveal(epoch: number, secretHex: string, opts?: TxOptions): Promise<any>;
470
+ /**
471
+ * A member of a set of one or two, signing with its consensus key: admit candidate `validator`
472
+ * into the set at the end of `epoch` (default: the epoch the next block is in; the tx fails in
473
+ * any other). The newcomer will be needed for every quorum, so this is the operator's decision,
474
+ * once an epoch per member; it joins once a quorum of the members admitted it and its node
475
+ * showed up (`validatorReady`).
476
+ */
477
+ admitValidator(validator: string, opts?: {
478
+ epoch?: number;
479
+ } & TxOptions): Promise<any>;
480
+ /** Low-level (candidate nodes do this automatically, in the epoch's last tenth, once a set of one or two admitted them): a candidate's consensus key signals its node is running in `epoch`. */
481
+ validatorReady(epoch: number, opts?: TxOptions): Promise<any>;
482
+ /**
483
+ * Put a proposal to a vote (build `kind` with `proposal.*`). Bonds `deposit` (default: the
484
+ * chain's `proposal_deposit`), refunded once the proposal reaches quorum and burned if it
485
+ * doesn't. Names in the kind (`to`, `account`) are signed as `Client.recipient` says: the proven
486
+ * address with witnesses, else the name, which the chain resolves when the proposal is made
487
+ * (it stores the address, which voters then see and bind).
488
+ *
489
+ * The default deposit is what the node reports, and a node can report anything, so it's
490
+ * bounded (audit gap-7-5): every witness of the client must report the same value, and it may
491
+ * be at most `maxDeposit` (default `DEFAULT_MAX_PROPOSAL_DEPOSIT`, mainnet's 1,000 FANG).
492
+ * Pass `deposit` to bond an amount you checked yourself.
493
+ */
494
+ propose(kind: ProposalKind, opts: {
495
+ title: string;
496
+ url?: string;
497
+ deposit?: Amount;
498
+ maxDeposit?: Amount;
499
+ } & TxOptions): Promise<any>;
500
+ /**
501
+ * Vote on a proposal with `amount` of your unlocked holdings (liquid, staked or unbonding;
502
+ * unvested tokens can't vote). `conviction` 0–6 locks `amount` for 0, 1, 2, 4, 8, 16 or 32 lock
503
+ * periods after the vote ends, for 0.1×, 1×, 2× … 6× the weight (see `convictionWeight`).
504
+ * Voting again replaces your vote. A validator's consensus key or owner voting before the
505
+ * bootstrap council ends also casts that validator's council vote.
506
+ *
507
+ * The vote binds the proposal's content (audit gap-7-6): pass `proposal`, the kind, title and
508
+ * link you showed the voter (e.g. the `client.proposal(id)` object you rendered, described with
509
+ * `describeKind`), or it's read from the client. A node that showed another proposal's content
510
+ * makes the vote fail. If you showed it earlier and only kept its digest
511
+ * (`proposalSummary(raw).digest`), pass `digest`: a proposal that reads differently now is
512
+ * refused before anything is signed.
513
+ */
514
+ vote(proposalId: number, aye: boolean, amount: Amount, conviction?: number, opts?: TxOptions & {
515
+ proposal?: {
516
+ kind: ProposalKind;
517
+ title: string;
518
+ url?: string;
519
+ };
520
+ digest?: string;
521
+ }): Promise<any>;
522
+ /** Release every vote lock that has expired. */
523
+ unlock(opts?: TxOptions): Promise<any>;
524
+ /**
525
+ * Make this account an M-of-N multisig of its owner keys (`ownerKeyIds`): owner-only actions
526
+ * then need `multisigPropose` plus approvals up to `threshold`. Session keys keep working
527
+ * within their limits.
528
+ */
529
+ multisigCreate(ownerKeyIds: string[], threshold: number, opts?: TxOptions): Promise<any>;
530
+ /** Propose an action for this multisig account; it runs once enough owners approve. */
531
+ multisigPropose(action: Action, opts?: TxOptions): Promise<any>;
532
+ /**
533
+ * Approve open multisig proposal `id`. The approval binds the action (audit gap-7-6): pass
534
+ * `action`, the one you showed the approver (decode it and describe it with `describeAction`,
535
+ * don't trust a summary), or it's read from `client.multisig(account)`. A node that showed
536
+ * another action makes the approval fail. `digest`: the `actionDigest` of what you showed, if
537
+ * that's all you kept; an action that reads differently now is refused before anything is signed.
538
+ * A `vote` binds its proposal by digest, not by id: show it with `reviewAction(action, {
539
+ * proposal: await client.proposal(action.proposal_id) })`, which describes the proposal only if
540
+ * its content has that digest, and don't offer the approval unless it's `readable` (gap-7-6).
541
+ * Pass that proposal read as `proposal` here: approving a vote is refused, before anything is
542
+ * signed, unless the proposal shown (else one read now) has exactly the content the vote binds.
543
+ * The approval counts on this wallet's account (`actAs`), which the digest doesn't bind: on
544
+ * mainnet act for an address you checked, not a name one node resolved.
545
+ */
546
+ multisigApprove(id: number, opts?: TxOptions & {
547
+ action?: Action;
548
+ digest?: string;
549
+ proposal?: unknown;
550
+ }): Promise<any>;
551
+ /** Extend a name you own by `years` (1–10), at the chain's renewal price per year. */
552
+ renewName(name: string, years?: number, opts?: TxOptions): Promise<any>;
553
+ /**
554
+ * Offer a name you own to another account (a `.boo` name or address, signed as `Client.recipient` says). It
555
+ * stays yours until they accept it (`acceptName`); offering it again replaces the offer, and
556
+ * `withdrawNameOffer` withdraws it. Nobody can be given a name without saying yes.
557
+ */
558
+ transferName(name: string, to: string, opts?: TxOptions): Promise<any>;
559
+ /** Accept a name offered to the account you act for (`client.name(n).offered_to`): it becomes yours. */
560
+ acceptName(name: string, opts?: TxOptions): Promise<any>;
561
+ /** Withdraw your offer of a name you own (the same tx as `acceptName`: the chain tells them apart by who owns the name). */
562
+ withdrawNameOffer(name: string, opts?: TxOptions): Promise<any>;
563
+ /** Give up a name you own; anyone can register it afterwards. */
564
+ releaseName(name: string, opts?: TxOptions): Promise<any>;
565
+ /** Claim your share of a community distribution with the Merkle proof published alongside it (hex hashes). */
566
+ claimDistribution(distributionId: number, amount: Amount, proof: string[], opts?: TxOptions): Promise<any>;
567
+ /** Low-level (validator nodes do this automatically): a matured claim's PR was reverted by commit `revertSha`. */
568
+ attestRevert(claimId: number, revertSha: string, opts?: TxOptions): Promise<any>;
569
+ /** This account's shares in a validator's pool, for `"all"`; anything else is parsed and checked. */
570
+ private sharesOf;
571
+ /** A proposal kind with its accounts as `Client.recipient` signs them (the chain resolves names when the proposal is made). */
572
+ private resolveKind;
92
573
  balance(): Promise<string>;
93
574
  /** Dev/test chains only: drip 100 FANG to this wallet. */
94
575
  faucet(wait?: boolean): Promise<any>;
@@ -98,35 +579,400 @@ export declare class ApiError extends Error {
98
579
  readonly status: number;
99
580
  constructor(status: number, message: string);
100
581
  }
101
- /** A transaction that was rejected at execution (fee charged) or dropped from the mempool. */
582
+ /**
583
+ * The node reports a transaction as failed. Two different things (audit review-fix-clients-2):
584
+ * - `dropped` false: it executed in block `tx.height` and failed there. Its fee was charged; it
585
+ * can't execute again.
586
+ * - `dropped` true: this node dropped it from its mempool without running it (evicted by a
587
+ * higher tip, replaced, not included, or an earlier tx from the account was dropped). Nothing
588
+ * was charged, but other nodes may still hold it and include it until its `valid_until`
589
+ * (`validUntil`, when known): check `client.tx(id)` before sending it again, or a retry can pay twice.
590
+ */
591
+ /**
592
+ * Whether a `/api/tx` answer of status "failed" is a tx the node dropped from its mempool without
593
+ * running it (nothing charged; another node may still include it until its `valid_until`), not
594
+ * one that ran in a block and failed (its fee was charged). Mempool failures are answered without
595
+ * the tx itself (node/src/api.rs `tx`), and older nodes don't say `dropped`.
596
+ */
597
+ export declare function txDropped(answer: unknown): boolean;
102
598
  export declare class TxFailedError extends Error {
103
599
  readonly id: string;
104
600
  readonly reason: string;
105
601
  readonly tx: any;
106
- constructor(id: string, reason: string, tx: any);
602
+ readonly validUntil?: number | undefined;
603
+ readonly dropped: boolean;
604
+ constructor(id: string, reason: string, tx: any, validUntil?: number | undefined);
605
+ }
606
+ /**
607
+ * The node accepted a transaction, but it wasn't seen finalized (or failed) in time. It may still
608
+ * execute until its `valid_until`: check it with `client.tx(id)` before sending it again, or a
609
+ * retry can pay twice.
610
+ */
611
+ export declare class TxPendingError extends Error {
612
+ readonly id: string;
613
+ readonly waitedMs: number;
614
+ readonly lastError?: unknown;
615
+ constructor(id: string, waitedMs: number, lastError?: unknown);
616
+ }
617
+ /** The node didn't answer within the client's `timeoutMs`. Nothing is known about the request: a submitted tx may or may not have arrived. */
618
+ export declare class RequestTimeoutError extends Error {
619
+ readonly rpc: string;
620
+ readonly path: string;
621
+ readonly timeoutMs: number;
622
+ constructor(rpc: string, path: string, timeoutMs: number);
623
+ }
624
+ /** A proof older than the newest head seen (this node's and every witness's) by more than `maxLagBlocks`. */
625
+ export declare class StaleProofError extends Error {
626
+ readonly height: number;
627
+ readonly head: number;
628
+ readonly maxLagBlocks: number;
629
+ constructor(height: number, head: number, maxLagBlocks: number);
630
+ }
631
+ /**
632
+ * On mainnet, a transaction would carry an address that only one node vouched for: a `.boo` name
633
+ * resolved without witnesses, in a field that needs an address (staking's validator, the account
634
+ * `actAs` acts for, a key grant's account). Nothing was signed (audit gap-7-1). Check
635
+ * `resolution.address` with its owner and pass it instead of the name, or give the client witnesses.
636
+ */
637
+ export declare class UnprovenNameError extends Error {
638
+ readonly resolution: Resolution;
639
+ constructor(resolution: Resolution, rpc: string);
640
+ }
641
+ /**
642
+ * A node reports a height the chain can't have reached (`Client.checkSigningHeight`): a tx signed
643
+ * against it could be held and released later. Nothing was signed.
644
+ */
645
+ export declare class HeightAheadError extends Error {
646
+ readonly rpc: string;
647
+ readonly height: number;
648
+ readonly limit: number;
649
+ constructor(rpc: string, height: number, limit: number, by: string);
650
+ }
651
+ /**
652
+ * How far ahead of the lowest head a client's witnesses report a tx's height may be, by default
653
+ * (`ClientOptions.maxHeadLeadBlocks`): 30 blocks, room for propagation between nodes.
654
+ */
655
+ export declare const DEFAULT_MAX_HEAD_LEAD_BLOCKS = 30;
656
+ /**
657
+ * How far behind the network's clocks this machine's may be before `heightLimit` refuses an honest
658
+ * node: 15 minutes (the CLI uses the same, node/src/cli_net.rs `HEIGHT_CLOCK_TOLERANCE_MS`).
659
+ */
660
+ export declare const HEIGHT_CLOCK_TOLERANCE_MS: number;
661
+ /**
662
+ * The highest height a chain can have reached at `nowMs` (node/src/cli_net.rs `height_limit`):
663
+ * every block's timestamp is at least its parent's plus the block time, and validators refuse one
664
+ * more than a second ahead of their clocks, so block h is stamped no earlier than genesis + h ×
665
+ * block time. A chain that ran slower than its block time is below this by that much, so it
666
+ * refuses only heights the chain can't have, not every lie.
667
+ */
668
+ export declare function heightLimit(createdAtMs: number, blockTimeMs: number, nowMs: number): number;
669
+ /** The node reports a different chain than the client is pinned to (`ClientOptions`). */
670
+ export declare class ChainMismatchError extends Error {
671
+ readonly rpc: string;
672
+ readonly field: "chain_id" | "genesis_hash" | "address_prefix";
673
+ readonly expected: string;
674
+ readonly reported: string | undefined;
675
+ constructor(rpc: string, field: "chain_id" | "genesis_hash" | "address_prefix", expected: string, reported: string | undefined);
676
+ }
677
+ /** What a `Client` requires of the node. Every `/api/status` (including the one `Wallet.build` signs against) is checked. */
678
+ export interface ClientOptions {
679
+ /** The address prefix you expect (`boo` or `tboo`). */
680
+ prefix?: string;
681
+ /** The chain id the node must report (e.g. `blockula-1`). */
682
+ chainId?: string;
683
+ /** The genesis hash (hex) the node must report. */
684
+ genesisHash?: string;
685
+ /** How long one request may take before it fails with `RequestTimeoutError` (default 15 s, at most `MAX_TIMEOUT_MS`). */
686
+ timeoutMs?: number;
687
+ /**
688
+ * Clients for independent nodes of the same chain. With witnesses, every name this client
689
+ * resolves for a signature is a proven read (`provenName`): the record's Merkle proof must check
690
+ * out against a state root each witness reports for that block, and be fresh. Without them
691
+ * (audit gap-7-1):
692
+ * - where the chain resolves names itself (`Wallet.send`, `awardHunt`, `vouch`/`unvouch`,
693
+ * `grantSoul`, `flagSybil`, `clawback`, `transferName`, proposal targets), the name is signed
694
+ * as the name (`recipient`): the chain pays whoever owns it when the tx runs, so a lying node
695
+ * can't point it at another account now, only hold it within its validity window;
696
+ * - where an address is needed (`delegate`/`undelegate`/`redelegate`/`unjail`, `actAs`,
697
+ * `keyGrant`), a name is one node's unproven answer, and on mainnet nothing is signed with it
698
+ * (`UnprovenNameError`): pass the address.
699
+ */
700
+ witnesses?: Client[];
701
+ /** Refuse to resolve a `.boo` name for a signature unless it's proven (needs `witnesses`). */
702
+ requireProvenNames?: boolean;
703
+ /**
704
+ * With witnesses: how far ahead of the lowest head they report the height a tx is signed
705
+ * against may be (default `DEFAULT_MAX_HEAD_LEAD_BLOCKS`). See `Client.checkSigningHeight`.
706
+ */
707
+ maxHeadLeadBlocks?: number;
708
+ /**
709
+ * The chain's genesis time and block time (`created_at_ms` and `block_time_ms` of the
710
+ * genesis.json that hashes to `genesisHash`, as published with it), as pins: with them, a
711
+ * status claiming a height the chain can't have reached by this machine's clock is refused
712
+ * before anything is signed (`Client.checkSigningHeight`). Not the node's word, so don't take
713
+ * them from it.
714
+ */
715
+ genesisClock?: {
716
+ createdAtMs: number;
717
+ blockTimeMs: number;
718
+ };
719
+ }
720
+ /** Where a recipient (a `.boo` name or an address) goes, and how sure that is (`Client.resolution`). */
721
+ export interface Resolution {
722
+ /** What was asked for. */
723
+ input: string;
724
+ /** The address that gets signed. */
725
+ address: string;
726
+ /** The bare name, when `input` was one. */
727
+ name: string | null;
728
+ /** An address as given, or a name proven against the client's witnesses; `false`: one node's word. */
729
+ proven: boolean;
730
+ /** How it was resolved, in plain English (show it with the address before signing). */
731
+ how: string;
732
+ /** The block a proven name was read at. */
733
+ height?: number;
107
734
  }
735
+ /** A recipient in a field the chain resolves itself, as it gets signed (`Client.recipient`). */
736
+ export interface Recipient extends Resolution {
737
+ /**
738
+ * What goes into the action: an address as given, a name's proven owner (with witnesses), or
739
+ * the name itself (`alice.boo`) when nothing proved it.
740
+ */
741
+ signed: string;
742
+ /**
743
+ * `signed` is the name: the chain resolves it to whoever owns it when the tx runs, so no node
744
+ * can point it at another account now (one holding the signed tx can still release it later,
745
+ * by when the name may have changed hands: see `recipient`). `address` is then just the node's
746
+ * current answer, for display.
747
+ */
748
+ byChain: boolean;
749
+ }
750
+ /** Default per-request timeout of a `Client`. */
751
+ export declare const DEFAULT_TIMEOUT_MS = 15000;
752
+ /**
753
+ * The longest timeout a `Client` takes: 2^31 − 1 ms (about 24.8 days). Timers store their delay
754
+ * as a signed 32-bit number, and a longer one fires at once (audit review-fix-clients-1).
755
+ */
756
+ export declare const MAX_TIMEOUT_MS = 2147483647;
757
+ /** `ms` as a timeout: a whole number of milliseconds from 1 to `MAX_TIMEOUT_MS`, or an error naming `what`. */
758
+ export declare function checkTimeoutMs(ms: number, what?: string): number;
759
+ /**
760
+ * How far behind the newest head (the node's own and each witness's `/api/status` height) a
761
+ * proven read's proof may be, by default: 10 blocks (10 s at 1 s blocks), room for propagation
762
+ * between nodes. Older proofs are refused (`StaleProofError`), so a node can't answer with a
763
+ * genuine but outdated record (a name's previous owner, a balance before a spend, a removed key).
764
+ */
765
+ export declare const DEFAULT_MAX_PROOF_LAG_BLOCKS = 10;
766
+ /** Options of the proven reads (`provenRecord`, `provenAccount`, `provenName`). */
767
+ export interface ProvenOptions {
768
+ /** Clients for independent nodes: each must report the same state root for the proof's block, and its head bounds how old the proof may be. */
769
+ witnesses?: Client[];
770
+ /** How long to wait for a witness that hasn't reached the proof's block yet (default 5 s). */
771
+ waitMs?: number;
772
+ /** How many blocks the proof may be behind the newest head seen (default `DEFAULT_MAX_PROOF_LAG_BLOCKS`). */
773
+ maxLagBlocks?: number;
774
+ }
775
+ /** A record proven against a state root, and the newest head height that root was checked against. */
776
+ export type ProvenRead = ProvenRecord & {
777
+ head: number;
778
+ };
108
779
  export declare class Client {
109
780
  readonly rpc: string;
110
- constructor(rpc?: string);
781
+ /** The chain's address prefix: given, learned from `/api/status`, or `boo` until then. */
782
+ prefix: string;
783
+ private prefixKnown;
784
+ private readonly pinnedPrefix?;
785
+ private readonly pinnedChainId?;
786
+ private readonly pinnedGenesis?;
787
+ /** Per-request timeout (ms). */
788
+ readonly timeoutMs: number;
789
+ /** Independent nodes names are proven against (`ClientOptions.witnesses`). */
790
+ readonly witnesses: Client[];
791
+ readonly requireProvenNames: boolean;
792
+ /** See `ClientOptions.maxHeadLeadBlocks`. */
793
+ readonly maxHeadLeadBlocks: number;
794
+ /** See `ClientOptions.genesisClock`. */
795
+ readonly genesisClock?: {
796
+ createdAtMs: number;
797
+ blockTimeMs: number;
798
+ };
799
+ /** `opts` pins the chain: a node reporting another prefix, chain id or genesis hash is refused with `ChainMismatchError`. */
800
+ constructor(rpc?: string, opts?: ClientOptions);
801
+ /**
802
+ * Refuses (`HeightAheadError`, before anything is signed) a height a tx's validity window would
803
+ * count from that this client has reason to think the chain hasn't reached: more than
804
+ * `maxHeadLeadBlocks` past the lowest head its witnesses report, or, with a `genesisClock`, past
805
+ * what the chain can have reached by this machine's clock (`heightLimit`). A node reporting a
806
+ * future height gets a tx it can hold and release later, when the window it picked opens; with
807
+ * a name signed in it, after the name may have changed hands (audit review-r3-clients-2).
808
+ * Every witness must report its height, as every witness must confirm a proof: one honest
809
+ * witness is enough to refuse a height the chain hasn't reached, whatever the others say.
810
+ * Without witnesses or a genesis clock, the height is the node's word.
811
+ */
812
+ checkSigningHeight(height: number): Promise<void>;
813
+ /** The chain's address prefix, asking the node once if it isn't known yet. */
814
+ addressPrefix(): Promise<string>;
815
+ /** One request, bounded by `timeoutMs` (headers and body): a node that never answers fails with `RequestTimeoutError` instead of hanging. */
111
816
  private call;
112
817
  status(): Promise<any>;
113
818
  blocks(limit?: number): Promise<any>;
114
819
  block(heightOrHash: number | string): Promise<any>;
115
820
  tx(id: string): Promise<any>;
116
821
  account(addressOrName: string): Promise<any>;
822
+ /** A name: `status` (`active`, `grace` (expired; only its owner can renew it), `reserved` or `available`), owner, `expires_at`, `offered_to` (if its owner offered it to an account: theirs once they accept), prices. */
117
823
  name(name: string): Promise<any>;
824
+ /** The base fee: each upcoming block's (`slots`) and `suggested`, which covers any of the next 17 blocks. */
825
+ fees(): Promise<{
826
+ height: number;
827
+ lag: number;
828
+ slots: ({
829
+ height: number;
830
+ max_block_bytes: number;
831
+ } & BaseFee)[];
832
+ suggested: BaseFee;
833
+ lowest?: BaseFee;
834
+ tip_cap_multiple?: number;
835
+ account_creation_fee: string;
836
+ [k: string]: unknown;
837
+ }>;
838
+ /** The governance parameters (node/src/params.rs `ChainParams`; amounts as strings) under `params`, genesis constants under `genesis`, and the issuance year. `paramsOf` flattens it. */
839
+ params(): Promise<any>;
840
+ /** The chain's genesis.json as this node serves it: the node's word (nothing here checks it against the genesis hash). */
841
+ genesis(): Promise<any>;
842
+ /** Upgrades: the protocol version in force, what the node's binary supports, the `schedule` (`[{ version, activation_height, active }]`, what `proposal.cancelUpgrade` names), halts and each validator's readiness signal. */
843
+ upgrade(): Promise<any>;
118
844
  /** Accounts a key is authorized on (its own address, plus any it was added to). */
119
- keyAccounts(keyIdHex: string): Promise<any>;
845
+ /**
846
+ * Accounts a key is on (`{ key_id, accounts, next }`), a page at a time: pass the previous page's
847
+ * `next` as `after`. Only accounts the key agreed to join (its grant) can list it (audit gap-7-2).
848
+ */
849
+ keyAccounts(keyIdHex: string, page?: {
850
+ after?: string;
851
+ limit?: number;
852
+ }): Promise<any>;
120
853
  search(q: string): Promise<any>;
121
- /** Active set for the current epoch, pending/approved validators, next-epoch set, epoch timing. */
854
+ /** The validator set: `active` this epoch, `next_epoch` (with `joining`/`leaving`), `candidates`, `jailed`, `tombstoned` and `removed`, each with stake, self-bond, commission, jail and liveness; epoch timing; the churn limit and slashing parameters. */
122
855
  validators(): Promise<any>;
123
856
  /** Hunts (bounties on GitHub issues), biggest first. */
124
857
  hunts(status?: "open" | "awarded" | "cancelled" | "expired"): Promise<any>;
125
858
  hunt(id: number): Promise<any>;
126
859
  /** Off-chain check of a GitHub link (gist owned by the handle containing the address). */
127
860
  github(handle: string): Promise<any>;
861
+ /** The contribution pool: balance, repos, rules, the open Séance and recent results. */
862
+ contributions(): Promise<any>;
863
+ claims(opts?: {
864
+ status?: "pending" | "verified" | "in_seance" | "scored" | "spam" | "rejected";
865
+ account?: string;
866
+ }): Promise<any>;
867
+ claim(id: number): Promise<any>;
868
+ /** A Séance, with each juror's assigned pairs (what they must judge). */
869
+ seance(id: number): Promise<any>;
870
+ /** A juror's assigned pairs in Séance `id`, in order, with each claim's repo and PR (what `sealVotes` binds). */
871
+ seancePairs(id: number, juror: string): Promise<[SeanceClaimRef, SeanceClaimRef][]>;
872
+ /** Soul leaderboard. */
873
+ souls(limit?: number): Promise<any>;
874
+ /** An account's stake: `delegations` (shares, value, principal), `entries` (unbonding and redelegations, with `release_at`), `bonded`, `unbonding` and `withdrawable` totals, the `validators` it runs, a `summary`. */
875
+ staking(account: string): Promise<any>;
876
+ /** Governance proposals, newest first (`status`: `voting`, `queued`, `rejected`, `executed`, `failed`), the rules (`params`), treasury and community balances. */
877
+ proposals(opts?: {
878
+ status?: string;
879
+ limit?: number;
880
+ }): Promise<any>;
881
+ /** One proposal with its votes. */
882
+ proposal(id: number): Promise<any>;
883
+ /** A community distribution: Merkle root, total, claimed so far, claim deadline. */
884
+ distribution(id: number): Promise<any>;
885
+ /** A multisig account: owners, threshold, open proposals and their approvals. */
886
+ multisig(account: string): Promise<any>;
887
+ /** `/api/proof/{namespace}/{key}`, unchecked. Prefer `provenRecord`. */
888
+ proof(namespace: number, key: string | Uint8Array): Promise<ProofResponse>;
889
+ /**
890
+ * A record with its Merkle proof checked against the state root the node reports. On its own
891
+ * that only shows the node is consistent; `witnesses` (clients for independent nodes) must
892
+ * each report the same state root for that block, so a single lying node can't fake balances,
893
+ * names or keys. A witness that hasn't reached the block yet is retried for `waitMs`.
894
+ *
895
+ * The proof must also be fresh: its block may be at most `maxLagBlocks` behind the newest head
896
+ * this node and the witnesses report (`StaleProofError` otherwise). Witnesses confirm any
897
+ * genuine root, old ones included, so without this a lying node could serve a real but outdated
898
+ * record (a name's previous owner, a balance before a spend, a key since removed). `head` is
899
+ * the newest head seen. Without witnesses only this node's own head is compared, which a lying
900
+ * node controls: pass witnesses for anything that matters.
901
+ */
902
+ provenRecord(namespace: number, key: string | Uint8Array, opts?: ProvenOptions): Promise<ProvenRead>;
903
+ /** Throws unless this node's block `height` has state root `root` (waiting up to `waitMs` for it to get there). */
904
+ confirmStateRoot(height: number, root: string, waitMs?: number): Promise<void>;
905
+ /** An address's balance, nonce and keys, proven and fresh (see `provenRecord`). `null` if the account provably doesn't exist. */
906
+ provenAccount(address: string, opts?: ProvenOptions): Promise<{
907
+ balance: bigint;
908
+ nonce: number;
909
+ keys: import("./proof.js").ProvenKey[];
910
+ address: string;
911
+ height: number;
912
+ root: string;
913
+ head: number;
914
+ } | null>;
915
+ /**
916
+ * Who a `.boo` name resolves to, proven and fresh (see `provenRecord`). `null` if it provably
917
+ * doesn't resolve: never registered, or expired (`expires_at` passed; in its grace period only
918
+ * the owner can renew it, and after that anyone can register it). `includeExpired` returns an
919
+ * expired record too, with `active: false`: never pay its `owner`.
920
+ */
921
+ provenName(name: string, opts?: ProvenOptions & {
922
+ includeExpired?: boolean;
923
+ }): Promise<{
924
+ name: string;
925
+ owner: string;
926
+ registered_at: number;
927
+ expires_at: number;
928
+ offered_to?: string;
929
+ grace_blocks?: number;
930
+ active: boolean;
931
+ height: number;
932
+ root: string;
933
+ head: number;
934
+ } | null>;
935
+ /**
936
+ * The address a name or address resolves to, for fields that need an address (see
937
+ * `resolution`): proven with witnesses, else one node's word. Where the chain resolves names
938
+ * itself (payments, vouches, name offers…), use `recipient` instead, which signs the name.
939
+ */
128
940
  resolve(nameOrAddress: string): Promise<string>;
941
+ /**
942
+ * How to sign a recipient in a field the chain resolves itself (`transfer.to`, `award_hunt.to`,
943
+ * `vouch`/`unvouch`/`flag_sybil`/`clawback.account`, `grant_soul.to`, `transfer_name.to`, and
944
+ * proposal targets): an address as given; with witnesses a name's proven owner; without them
945
+ * the name itself, which the chain resolves to its owner when the tx runs, so a lying node
946
+ * can't point it at another account now (audit gap-7-1). It can still hold the signed tx and
947
+ * release it later within its validity window, which counts from the height that node reported
948
+ * (bounded by `checkSigningHeight` only with witnesses or a `genesisClock`): whoever owns the
949
+ * name then is paid, so a name that lapses in between pays its next owner (review-r3-clients-2).
950
+ * Show `how` before signing.
951
+ */
952
+ recipient(nameOrAddress: string): Promise<Recipient>;
953
+ /**
954
+ * Where a recipient goes and how sure that is: show `address` and `how` before signing. With the
955
+ * client's `witnesses` a name is a proven, fresh read (`provenName`), so a lying node can't
956
+ * point it elsewhere; without them it's this node's answer alone (`proven: false`), which a
957
+ * lying node controls (audit gap-7-1).
958
+ */
959
+ resolution(nameOrAddress: string): Promise<Resolution>;
960
+ /**
961
+ * Submits a signed tx, then (with `wait`) waits for it. What a failure means:
962
+ * - `ApiError`: the node refused the tx; it wasn't admitted.
963
+ * - `RequestTimeoutError` or a network error: unknown; the tx may have arrived.
964
+ * - `TxFailedError`: it executed and failed (`dropped` false: its fee was charged), or this node
965
+ * dropped it unrun (`dropped` true: nothing charged, but it may still execute elsewhere until
966
+ * its `valid_until`).
967
+ * - `TxPendingError`: it was admitted and may still execute. Don't send it again blindly.
968
+ */
129
969
  submit(tx: Tx, wait?: boolean): Promise<any>;
130
970
  faucet(to: string, wait?: boolean): Promise<any>;
131
- waitForTx(id: string, timeoutMs?: number): Promise<any>;
971
+ /**
972
+ * Polls a tx until it's finalized (returns it) or failed (`TxFailedError`, which says whether it
973
+ * executed or was dropped unrun). A poll that fails (rate limited, a node error, a timeout, not
974
+ * visible yet) is retried; after `timeoutMs` it throws `TxPendingError`, since the tx may still
975
+ * execute. `validUntil` (the tx's, when the caller has it) goes into a dropped tx's error.
976
+ */
977
+ waitForTx(id: string, timeoutMs?: number, validUntil?: number): Promise<any>;
132
978
  }