@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/README.md +105 -5
- package/dist/describe.d.ts +50 -0
- package/dist/describe.js +350 -0
- package/dist/distribution.d.ts +26 -0
- package/dist/distribution.js +110 -0
- package/dist/index.d.ts +874 -28
- package/dist/index.js +1332 -68
- package/dist/proof.d.ts +126 -0
- package/dist/proof.js +255 -0
- package/dist/release.d.ts +15 -0
- package/dist/release.js +41 -0
- package/dist/tx.d.ts +458 -3
- package/dist/tx.js +653 -26
- package/package.json +7 -5
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
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
38
|
-
|
|
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
|
-
/**
|
|
47
|
-
|
|
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
|
-
*
|
|
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(
|
|
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
|
-
*
|
|
60
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
-
|
|
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
|
}
|