@aibtc/mcp-server 1.66.0 → 1.68.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/legion.d.ts +53 -11
- package/dist/config/legion.js +77 -20
- package/dist/services/legion.service.d.ts +95 -43
- package/dist/services/legion.service.js +224 -104
- package/dist/tools/index.js +1 -1
- package/dist/tools/legion.tools.d.ts +14 -6
- package/dist/tools/legion.tools.js +312 -279
- package/package.json +1 -1
- package/skill/SKILL.md +1 -1
package/dist/config/legion.d.ts
CHANGED
|
@@ -1,24 +1,64 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AIBTC News Legion
|
|
2
|
+
* AIBTC News Legion configuration.
|
|
3
3
|
*
|
|
4
4
|
* Contribution-weighted governance for aibtc.news: agents inscribe a news piece
|
|
5
5
|
* to a Bitcoin ordinal, open ONE proposal naming that inscription, and the
|
|
6
6
|
* contributors vote on whether the piece is worth paying for. A passing piece
|
|
7
7
|
* pays its proposer a fixed slice of the sBTC pool.
|
|
8
8
|
*
|
|
9
|
+
* LIVE ON STACKS MAINNET, WITH REAL sBTC. The legion ran on testnet through
|
|
10
|
+
* v5/v6; those deployments are gone from this file because a testnet chain that
|
|
11
|
+
* has already been reset once is not history worth reading, and because keeping
|
|
12
|
+
* them would mean every read path carried a per-era network. Mainnet generation
|
|
13
|
+
* 1 is the only deployment now, and its proposal ids start at 1.
|
|
14
|
+
*
|
|
15
|
+
* Everything here still moves real value: `legion_contribute` and
|
|
16
|
+
* `legion_sponsor` spend sBTC that cannot be withdrawn, so both meter against
|
|
17
|
+
* the wallet's `sats` spending rail before they sign.
|
|
18
|
+
*
|
|
9
19
|
* NETWORK IS DERIVED FROM THE CONTRACT ADDRESS, NOT FROM `NETWORK`.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* of the server is configured.
|
|
20
|
+
* Every other tool in this server follows the global `NETWORK` env var. Reading
|
|
21
|
+
* that here would let a testnet-configured server sign governance calls against
|
|
22
|
+
* a testnet node while quoting mainnet balances. `LEGION_NETWORK` reads the
|
|
23
|
+
* address prefix instead, so these tools always follow the chain the contracts
|
|
24
|
+
* actually live on.
|
|
16
25
|
*/
|
|
17
26
|
import type { Network } from "./networks.js";
|
|
18
|
-
/**
|
|
19
|
-
export
|
|
20
|
-
/**
|
|
21
|
-
|
|
27
|
+
/** One deployment of the legion: a gov contract and the treasury it pays from. */
|
|
28
|
+
export interface LegionEra {
|
|
29
|
+
/** Full gov contract id. */
|
|
30
|
+
gov: string;
|
|
31
|
+
/** Full treasury id — where `sponsor-in` prints and the pool lives. */
|
|
32
|
+
treasury: string;
|
|
33
|
+
/**
|
|
34
|
+
* Generation number. The mainnet contracts carry no version in their names,
|
|
35
|
+
* so this is declared rather than parsed out of a string that no longer
|
|
36
|
+
* holds it.
|
|
37
|
+
*/
|
|
38
|
+
version: number;
|
|
39
|
+
/** True for the one era still receiving events. Only it accepts writes. */
|
|
40
|
+
live: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Every deployment this server knows, LIVE FIRST.
|
|
44
|
+
*
|
|
45
|
+
* Adding an era is one entry here with `live` moved to it; the old one keeps
|
|
46
|
+
* answering reads. Both contracts of a pair must share a deployer — gov calls
|
|
47
|
+
* its treasury as `(contract-call? .aibtc-news-treasury …)`, which resolves
|
|
48
|
+
* against the DEPLOYER OF THE GOV CONTRACT — and that is asserted below rather
|
|
49
|
+
* than trusted.
|
|
50
|
+
*/
|
|
51
|
+
export declare const LEGION_ERAS: readonly LegionEra[];
|
|
52
|
+
/** The era that accepts writes. */
|
|
53
|
+
export declare const LIVE_ERA: LegionEra;
|
|
54
|
+
/** Look up an era by generation number. */
|
|
55
|
+
export declare function eraByVersion(version: number): LegionEra | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Resolve a caller-supplied era version, defaulting to the live one.
|
|
58
|
+
* An unknown version is an error rather than a silent fallback — reading the
|
|
59
|
+
* wrong era would quietly answer about a different proposal with the same id.
|
|
60
|
+
*/
|
|
61
|
+
export declare function resolveEra(version?: number): LegionEra;
|
|
22
62
|
/**
|
|
23
63
|
* Which chain a Stacks contract id lives on, from its c32 address prefix:
|
|
24
64
|
* SP/SM are mainnet, ST/SN are testnet.
|
|
@@ -42,6 +82,8 @@ export declare const MAX_LINK_LENGTH = 200;
|
|
|
42
82
|
export declare const MAX_TITLE_LENGTH = 128;
|
|
43
83
|
/** `description` is `(string-ascii 512)`. */
|
|
44
84
|
export declare const MAX_DESCRIPTION_LENGTH = 512;
|
|
85
|
+
/** `vote` `rationale` is `(string-ascii 256)` and must be non-empty. */
|
|
86
|
+
export declare const MAX_RATIONALE_LENGTH = 256;
|
|
45
87
|
/** `sponsor-in` `name` is `(string-ascii 40)`. */
|
|
46
88
|
export declare const MAX_SPONSOR_NAME_LENGTH = 40;
|
|
47
89
|
/** `sponsor-in` `link` is `(optional (string-ascii 96))`. */
|
package/dist/config/legion.js
CHANGED
|
@@ -1,23 +1,66 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AIBTC News Legion
|
|
2
|
+
* AIBTC News Legion configuration.
|
|
3
3
|
*
|
|
4
4
|
* Contribution-weighted governance for aibtc.news: agents inscribe a news piece
|
|
5
5
|
* to a Bitcoin ordinal, open ONE proposal naming that inscription, and the
|
|
6
6
|
* contributors vote on whether the piece is worth paying for. A passing piece
|
|
7
7
|
* pays its proposer a fixed slice of the sBTC pool.
|
|
8
8
|
*
|
|
9
|
+
* LIVE ON STACKS MAINNET, WITH REAL sBTC. The legion ran on testnet through
|
|
10
|
+
* v5/v6; those deployments are gone from this file because a testnet chain that
|
|
11
|
+
* has already been reset once is not history worth reading, and because keeping
|
|
12
|
+
* them would mean every read path carried a per-era network. Mainnet generation
|
|
13
|
+
* 1 is the only deployment now, and its proposal ids start at 1.
|
|
14
|
+
*
|
|
15
|
+
* Everything here still moves real value: `legion_contribute` and
|
|
16
|
+
* `legion_sponsor` spend sBTC that cannot be withdrawn, so both meter against
|
|
17
|
+
* the wallet's `sats` spending rail before they sign.
|
|
18
|
+
*
|
|
9
19
|
* NETWORK IS DERIVED FROM THE CONTRACT ADDRESS, NOT FROM `NETWORK`.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
|
|
20
|
+
* Every other tool in this server follows the global `NETWORK` env var. Reading
|
|
21
|
+
* that here would let a testnet-configured server sign governance calls against
|
|
22
|
+
* a testnet node while quoting mainnet balances. `LEGION_NETWORK` reads the
|
|
23
|
+
* address prefix instead, so these tools always follow the chain the contracts
|
|
24
|
+
* actually live on.
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Every deployment this server knows, LIVE FIRST.
|
|
28
|
+
*
|
|
29
|
+
* Adding an era is one entry here with `live` moved to it; the old one keeps
|
|
30
|
+
* answering reads. Both contracts of a pair must share a deployer — gov calls
|
|
31
|
+
* its treasury as `(contract-call? .aibtc-news-treasury …)`, which resolves
|
|
32
|
+
* against the DEPLOYER OF THE GOV CONTRACT — and that is asserted below rather
|
|
33
|
+
* than trusted.
|
|
16
34
|
*/
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
35
|
+
export const LEGION_ERAS = [
|
|
36
|
+
{
|
|
37
|
+
gov: "SP5Y3W3F78NKFH4HYFNDQMJC484VZWKDH35ZR2M9.aibtc-news-gov",
|
|
38
|
+
treasury: "SP5Y3W3F78NKFH4HYFNDQMJC484VZWKDH35ZR2M9.aibtc-news-treasury",
|
|
39
|
+
version: 1,
|
|
40
|
+
live: true,
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
/** The era that accepts writes. */
|
|
44
|
+
export const LIVE_ERA = LEGION_ERAS.find((e) => e.live) ?? LEGION_ERAS[0];
|
|
45
|
+
/** Look up an era by generation number. */
|
|
46
|
+
export function eraByVersion(version) {
|
|
47
|
+
return LEGION_ERAS.find((e) => e.version === version);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Resolve a caller-supplied era version, defaulting to the live one.
|
|
51
|
+
* An unknown version is an error rather than a silent fallback — reading the
|
|
52
|
+
* wrong era would quietly answer about a different proposal with the same id.
|
|
53
|
+
*/
|
|
54
|
+
export function resolveEra(version) {
|
|
55
|
+
if (version === undefined)
|
|
56
|
+
return LIVE_ERA;
|
|
57
|
+
const found = eraByVersion(version);
|
|
58
|
+
if (!found) {
|
|
59
|
+
throw new Error(`No legion era v${version}. Known eras: ` +
|
|
60
|
+
LEGION_ERAS.map((e) => `v${e.version}${e.live ? " (live)" : ""}`).join(", "));
|
|
61
|
+
}
|
|
62
|
+
return found;
|
|
63
|
+
}
|
|
21
64
|
/**
|
|
22
65
|
* Which chain a Stacks contract id lives on, from its c32 address prefix:
|
|
23
66
|
* SP/SM are mainnet, ST/SN are testnet.
|
|
@@ -32,7 +75,20 @@ export function networkOfContract(contractId) {
|
|
|
32
75
|
`expected an address starting with SP/SM (mainnet) or ST/SN (testnet).`);
|
|
33
76
|
}
|
|
34
77
|
/** The chain the legion contracts are deployed on. */
|
|
35
|
-
export const LEGION_NETWORK = networkOfContract(
|
|
78
|
+
export const LEGION_NETWORK = networkOfContract(LIVE_ERA.gov);
|
|
79
|
+
// Every era must sit on one chain, and each pair must share a deployer. The
|
|
80
|
+
// network guard is derived from the live era, so a stray id on another chain
|
|
81
|
+
// would be signed against the wrong node; a mismatched deployer would point gov
|
|
82
|
+
// at a treasury it cannot actually call.
|
|
83
|
+
for (const e of LEGION_ERAS) {
|
|
84
|
+
if (networkOfContract(e.gov) !== LEGION_NETWORK) {
|
|
85
|
+
throw new Error(`Legion era v${e.version} (${e.gov}) is not on ${LEGION_NETWORK}, but the live era is.`);
|
|
86
|
+
}
|
|
87
|
+
if (e.gov.split(".")[0] !== e.treasury.split(".")[0]) {
|
|
88
|
+
throw new Error(`Legion era v${e.version} pairs ${e.gov} with ${e.treasury}, but gov resolves ` +
|
|
89
|
+
`its treasury against its own deployer — the two must share an address.`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
36
92
|
/**
|
|
37
93
|
* The viewer page for an inscription. This is the form every proposal on chain
|
|
38
94
|
* already stores, and the form a voter wants: clicking it opens the ordinals
|
|
@@ -49,6 +105,8 @@ export const MAX_LINK_LENGTH = 200;
|
|
|
49
105
|
export const MAX_TITLE_LENGTH = 128;
|
|
50
106
|
/** `description` is `(string-ascii 512)`. */
|
|
51
107
|
export const MAX_DESCRIPTION_LENGTH = 512;
|
|
108
|
+
/** `vote` `rationale` is `(string-ascii 256)` and must be non-empty. */
|
|
109
|
+
export const MAX_RATIONALE_LENGTH = 256;
|
|
52
110
|
/** `sponsor-in` `name` is `(string-ascii 40)`. */
|
|
53
111
|
export const MAX_SPONSOR_NAME_LENGTH = 40;
|
|
54
112
|
/** `sponsor-in` `link` is `(optional (string-ascii 96))`. */
|
|
@@ -67,32 +125,31 @@ export const STORY_STATUS = {
|
|
|
67
125
|
* Gov and treasury codes are disjoint, so one map covers both.
|
|
68
126
|
*/
|
|
69
127
|
export const LEGION_ERRORS = {
|
|
70
|
-
401: "ineligible — your weight is below
|
|
128
|
+
401: "ineligible — your weight is below minWeightToAct (contribute more first)",
|
|
71
129
|
402: "treasury has insufficient balance",
|
|
72
130
|
403: "treasury already wired to a gov contract",
|
|
73
131
|
404: "no proposal with that id",
|
|
74
132
|
405: "you have already voted on this proposal",
|
|
75
133
|
407: "voting has closed on this proposal",
|
|
76
|
-
408: "too early to conclude —
|
|
134
|
+
408: "too early to conclude — voting is still open",
|
|
77
135
|
409: "amount must be greater than zero",
|
|
78
136
|
410: "this proposal is already concluded",
|
|
79
137
|
411: "invalid payout recipient",
|
|
80
|
-
413: "your free weight does not cover the bond",
|
|
81
138
|
416: "this payout was already settled",
|
|
82
139
|
417: "the treasury payout failed",
|
|
83
|
-
418: "the pool is empty — nothing to
|
|
84
|
-
419: "the
|
|
140
|
+
418: "the pool is empty — nothing to pay out against",
|
|
141
|
+
419: "the payout would round to zero sats",
|
|
85
142
|
421: "the ordinals link must not be empty",
|
|
86
143
|
423: "a proposer cannot vote on their own piece",
|
|
87
|
-
424: "outside the veto window",
|
|
88
|
-
425: "you have already vetoed this proposal",
|
|
89
144
|
426: "contribution too small to mint any weight",
|
|
90
145
|
432: "too soon to propose — the global propose interval has not elapsed",
|
|
91
146
|
433: "the title must not be empty",
|
|
92
147
|
434: "you already have a live proposal (one at a time per principal)",
|
|
93
148
|
435: "the conclude window has passed — this proposal has already expired",
|
|
94
149
|
436: "voting has not opened yet (still in the pending period)",
|
|
95
|
-
437: "contribution is below
|
|
150
|
+
437: "contribution is below minJoinSats",
|
|
151
|
+
440: "the vote rationale must not be empty",
|
|
152
|
+
441: "the legion is not activated yet — it needs membersToActivate members holding minWeightToAct before any story can be proposed",
|
|
96
153
|
450: "sponsorship is below the treasury's minimum sponsor amount",
|
|
97
154
|
451: "the sponsor name must not be empty",
|
|
98
155
|
452: "the treasury is not wired to a gov contract yet",
|
|
@@ -1,13 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AIBTC News Legion
|
|
2
|
+
* AIBTC News Legion chain reads.
|
|
3
3
|
*
|
|
4
4
|
* Everything here reads the deployed contracts rather than trusting constants:
|
|
5
|
-
* governance parameters, the timing mode
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
5
|
+
* governance parameters, the timing mode, and the sBTC token the treasury
|
|
6
|
+
* holds. A doc that drifts from the contract is a doc; a read that drifts from
|
|
7
|
+
* the contract is a bug, so there is nothing to drift.
|
|
8
|
+
*
|
|
9
|
+
* The mainnet legion has NO VETO and NO QUORUM. A story is paid when enough
|
|
10
|
+
* distinct voters turn out, the yes share clears the threshold, AND the yes
|
|
11
|
+
* weight covers `yesMultiple` times the payout it releases — the last of these
|
|
12
|
+
* being what stops a small clique from voting money out of a large pool.
|
|
13
|
+
* Proposals are also blocked outright until the legion activates at
|
|
14
|
+
* `membersToActivate` members.
|
|
15
|
+
*
|
|
16
|
+
* Every cache is keyed by era, so a future generation cannot be served the
|
|
17
|
+
* previous one's answers.
|
|
9
18
|
*/
|
|
10
19
|
import { type ClarityValue } from "@stacks/transactions";
|
|
20
|
+
import { type LegionEra } from "../config/legion.js";
|
|
11
21
|
import type { Account } from "../transactions/builder.js";
|
|
12
22
|
/**
|
|
13
23
|
* Deep-unwrap a ClarityValue into plain JS. `cvToValue` only unwraps the top
|
|
@@ -24,36 +34,71 @@ export declare function num(value: unknown): number;
|
|
|
24
34
|
* Always reads the legion's own chain, never the globally configured one.
|
|
25
35
|
*/
|
|
26
36
|
export declare function readLegionContract(contractId: string, functionName: string, functionArgs?: ClarityValue[]): Promise<unknown>;
|
|
27
|
-
|
|
28
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Which required functions a published interface fails to satisfy.
|
|
39
|
+
*
|
|
40
|
+
* Pure, so the comparison is testable without a chain. Extra functions are
|
|
41
|
+
* fine — a contract may offer more than we call. Only missing names and
|
|
42
|
+
* changed arities matter.
|
|
43
|
+
*/
|
|
44
|
+
export declare function diffContractShape(functions: Array<{
|
|
45
|
+
name: string;
|
|
46
|
+
args: unknown[];
|
|
47
|
+
}>, required: Readonly<Record<string, number>>): string[];
|
|
48
|
+
export declare function readGov(functionName: string, functionArgs?: ClarityValue[], era?: LegionEra): Promise<unknown>;
|
|
49
|
+
export declare function readTreasury(functionName: string, functionArgs?: ClarityValue[], era?: LegionEra): Promise<unknown>;
|
|
29
50
|
export interface LegionParams {
|
|
30
|
-
|
|
51
|
+
/** Percent of cast weight that must be yes, e.g. 66. */
|
|
31
52
|
votingThreshold: number;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
53
|
+
/** Distinct voters a story needs before it can pass at all. */
|
|
54
|
+
minVoters: number;
|
|
55
|
+
/** Members holding minWeightToAct before ANY story may be proposed. */
|
|
56
|
+
membersToActivate: number;
|
|
57
|
+
/** Yes weight must be at least this multiple of the payout it releases. */
|
|
58
|
+
yesMultiple: number;
|
|
59
|
+
/** Weight floor to vote or propose. */
|
|
60
|
+
minWeightToAct: number;
|
|
61
|
+
/** Smallest contribution the contract accepts, in sats. */
|
|
62
|
+
minJoinSats: number;
|
|
63
|
+
/** Payout as basis points of the whole pool. */
|
|
64
|
+
payoutBps: number;
|
|
65
|
+
/** Blocks between filing and voting opening. */
|
|
66
|
+
voteDelay: number;
|
|
38
67
|
voteWindow: number;
|
|
39
|
-
vetoWindow: number;
|
|
40
68
|
concludeWindow: number;
|
|
41
|
-
|
|
69
|
+
/** Contract-wide cooldown between any two proposals. */
|
|
70
|
+
globalProposeInterval: number;
|
|
42
71
|
}
|
|
43
72
|
/** Every governance parameter, straight from `get-params`. */
|
|
44
|
-
export declare function getParams(): Promise<LegionParams>;
|
|
73
|
+
export declare function getParams(era?: LegionEra): Promise<LegionParams>;
|
|
74
|
+
export interface MembershipStatus {
|
|
75
|
+
/** Principals holding at least minWeightToAct. Only ever climbs. */
|
|
76
|
+
memberCount: number;
|
|
77
|
+
membersToActivate: number;
|
|
78
|
+
/** False means every `propose-story` reverts with u441, whatever else is true. */
|
|
79
|
+
activated: boolean;
|
|
80
|
+
membersNeeded: number;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Whether the legion has enough members to accept proposals at all.
|
|
84
|
+
*
|
|
85
|
+
* This is a gate no amount of weight can bypass: a single whale holding the
|
|
86
|
+
* entire pool still cannot propose until `membersToActivate` distinct
|
|
87
|
+
* principals have joined.
|
|
88
|
+
*/
|
|
89
|
+
export declare function getMembership(era?: LegionEra): Promise<MembershipStatus>;
|
|
45
90
|
/**
|
|
46
91
|
* Which clock the windows count on. `"TEST-STACKS-BLOCKS"` counts Stacks
|
|
47
92
|
* blocks; `"PROD-BURN"` counts Bitcoin burn blocks. Never assume — a window
|
|
48
93
|
* measured against the wrong tip is off by a factor of ten.
|
|
49
94
|
*/
|
|
50
|
-
export declare function getTimingMode(): Promise<string>;
|
|
95
|
+
export declare function getTimingMode(era?: LegionEra): Promise<string>;
|
|
51
96
|
/**
|
|
52
97
|
* The sBTC token the treasury actually moves, plus its fungible-token asset
|
|
53
98
|
* name — both needed to write an exact post-condition. Read from the treasury
|
|
54
99
|
* and its contract interface so a post-condition can never name the wrong asset.
|
|
55
100
|
*/
|
|
56
|
-
export declare function getLegionToken(): Promise<{
|
|
101
|
+
export declare function getLegionToken(era?: LegionEra): Promise<{
|
|
57
102
|
contract: string;
|
|
58
103
|
assetName: string;
|
|
59
104
|
}>;
|
|
@@ -61,7 +106,7 @@ export declare function getLegionToken(): Promise<{
|
|
|
61
106
|
* The height the contract's windows are measured against, on the clock
|
|
62
107
|
* `get-timing-mode` names.
|
|
63
108
|
*/
|
|
64
|
-
export declare function getClockHeight(): Promise<{
|
|
109
|
+
export declare function getClockHeight(era?: LegionEra): Promise<{
|
|
65
110
|
height: number;
|
|
66
111
|
clock: "stacks" | "burn";
|
|
67
112
|
timingMode: string;
|
|
@@ -76,14 +121,20 @@ export declare function getClockHeight(): Promise<{
|
|
|
76
121
|
export declare function getLegionAccount(): Promise<Account>;
|
|
77
122
|
export interface StoryRecord {
|
|
78
123
|
proposer: string;
|
|
79
|
-
|
|
80
|
-
|
|
124
|
+
/** The proposer's whole weight, held until the piece resolves. Never spent. */
|
|
125
|
+
lockedWeight: number;
|
|
126
|
+
/** Sats the treasury pays the proposer on a pass, snapshotted at propose time. */
|
|
127
|
+
payout: number;
|
|
81
128
|
createdAt: number;
|
|
82
129
|
voteEnd: number;
|
|
83
|
-
|
|
130
|
+
/**
|
|
131
|
+
* TotalWeight at the moment the story opened — including the proposer's own,
|
|
132
|
+
* which they cannot vote with. Recorded for context; nothing in the pass/fail
|
|
133
|
+
* decision divides by it, because this era has no quorum.
|
|
134
|
+
*/
|
|
135
|
+
totalWeightAtOpen: number;
|
|
84
136
|
yesWeight: number;
|
|
85
137
|
noWeight: number;
|
|
86
|
-
vetoWeight: number;
|
|
87
138
|
voterCount: number;
|
|
88
139
|
status: number;
|
|
89
140
|
reason: string;
|
|
@@ -93,20 +144,18 @@ export interface StoryMeta {
|
|
|
93
144
|
description: string;
|
|
94
145
|
link: string;
|
|
95
146
|
}
|
|
96
|
-
export declare function getStory(proposalId: number): Promise<StoryRecord | null>;
|
|
97
|
-
export declare function getStoryMeta(proposalId: number): Promise<StoryMeta | null>;
|
|
147
|
+
export declare function getStory(proposalId: number, era?: LegionEra): Promise<StoryRecord | null>;
|
|
148
|
+
export declare function getStoryMeta(proposalId: number, era?: LegionEra): Promise<StoryMeta | null>;
|
|
98
149
|
/**
|
|
99
|
-
* `"none" | "pending" | "voting" | "
|
|
100
|
-
* "
|
|
150
|
+
* `"none" | "pending" | "voting" | "concludable" | "expired" | "passed" |
|
|
151
|
+
* "failed"` — the contract's own view of where a piece stands.
|
|
101
152
|
*/
|
|
102
|
-
export declare function getPhase(proposalId: number): Promise<string>;
|
|
103
|
-
export declare function getLastProposalId(): Promise<number>;
|
|
104
|
-
export declare function getVoteRecord(proposalId: number, voter: string): Promise<{
|
|
153
|
+
export declare function getPhase(proposalId: number, era?: LegionEra): Promise<string>;
|
|
154
|
+
export declare function getLastProposalId(era?: LegionEra): Promise<number>;
|
|
155
|
+
export declare function getVoteRecord(proposalId: number, voter: string, era?: LegionEra): Promise<{
|
|
105
156
|
support: boolean;
|
|
106
157
|
weight: number;
|
|
107
|
-
|
|
108
|
-
export declare function getVetoRecord(proposalId: number, voter: string): Promise<{
|
|
109
|
-
weight: number;
|
|
158
|
+
rationale: string;
|
|
110
159
|
} | null>;
|
|
111
160
|
export interface ProposeStatus {
|
|
112
161
|
canPropose: boolean;
|
|
@@ -114,20 +163,24 @@ export interface ProposeStatus {
|
|
|
114
163
|
slotOpen: boolean;
|
|
115
164
|
noLiveProposal: boolean;
|
|
116
165
|
poolOk: boolean;
|
|
166
|
+
membersOk: boolean;
|
|
167
|
+
memberCount: number;
|
|
168
|
+
membersToActivate: number;
|
|
117
169
|
nextProposeHeight: number;
|
|
118
170
|
lockOnPropose: number;
|
|
119
|
-
|
|
171
|
+
payout: number;
|
|
120
172
|
freeWeight: number;
|
|
121
173
|
}
|
|
122
174
|
/** Every propose precondition folded into one read, with the individual gates. */
|
|
123
|
-
export declare function getProposeStatus(who: string): Promise<ProposeStatus>;
|
|
175
|
+
export declare function getProposeStatus(who: string, era?: LegionEra): Promise<ProposeStatus>;
|
|
124
176
|
/** Why a propose would revert right now, in the caller's words. */
|
|
125
|
-
export declare function proposeBlockers(status: ProposeStatus,
|
|
177
|
+
export declare function proposeBlockers(status: ProposeStatus, minWeightToAct: number): string[];
|
|
126
178
|
export interface StoryTimeline {
|
|
127
179
|
createdAt: number;
|
|
128
180
|
votingOpensAt: number;
|
|
129
181
|
voteEnd: number;
|
|
130
|
-
|
|
182
|
+
/** Conclude opens the moment voting closes — there is no veto window. */
|
|
183
|
+
concludeOpensAt: number;
|
|
131
184
|
concludeDeadline: number;
|
|
132
185
|
currentHeight: number;
|
|
133
186
|
clock: "stacks" | "burn";
|
|
@@ -141,13 +194,12 @@ export interface PredictedOutcome {
|
|
|
141
194
|
/** True when the outcome is what the contract already recorded, not a forecast. */
|
|
142
195
|
settled: boolean;
|
|
143
196
|
cast: number;
|
|
144
|
-
quorumPct: number;
|
|
145
197
|
yesPct: number;
|
|
146
|
-
|
|
147
|
-
|
|
198
|
+
/** Yes weight the story needs to release its payout: payout × yesMultiple. */
|
|
199
|
+
yesWeightRequired: number;
|
|
200
|
+
votersMet: boolean;
|
|
148
201
|
thresholdMet: boolean;
|
|
149
|
-
|
|
150
|
-
participantsMet: boolean;
|
|
202
|
+
yesMet: boolean;
|
|
151
203
|
payout: number;
|
|
152
204
|
}
|
|
153
205
|
/**
|