Skip to content

Commit db05ff1

Browse files
authored
Merge branch 'main' into ton-docs
2 parents 0709f96 + 0aaf72e commit db05ff1

File tree

10 files changed

+659
-289
lines changed

10 files changed

+659
-289
lines changed

.github/CODEOWNERS

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
* @zeta-chain/DevEx @zeta-chain/fullstack
2-
3-
/src/pages/nodes/ @zeta-chain/DevOps @zeta-chain/DevEx
1+
* @zeta-chain/devex @zeta-chain/fullstack @zeta-chain/protocol-engineering @zeta-chain/devops
+93-142
Original file line numberDiff line numberDiff line change
@@ -1,170 +1,121 @@
1-
import { useEffect, useMemo, useState } from "react";
1+
import { useEffect, useState } from "react";
22

3-
import { LoadingTable, NetworkTypeTabs, networkTypeTabs, rpcByNetworkType } from "~/components/shared";
3+
import { NetworkTypeTabs, networkTypeTabs, rpcByNetworkType } from "~/components/shared";
44

5-
function capitalizeFirstLetter(s: string) {
6-
return s.charAt(0).toUpperCase() + s.slice(1);
5+
interface Authorization {
6+
msg_url: string;
7+
authorized_policy: string;
78
}
89

9-
function formatDate(dateString: string) {
10-
const options: Intl.DateTimeFormatOptions = {
11-
year: "numeric",
12-
month: "long",
13-
day: "numeric",
10+
interface AuthorizationResponse {
11+
authorization_list: {
12+
authorizations: Authorization[];
1413
};
15-
return new Date(dateString).toLocaleDateString(undefined, options);
1614
}
1715

18-
export const AdminPolicy = () => {
19-
const [mainnetAdminPolicies, setMainnetAdminPolicies] = useState<any[]>([]);
20-
const [testnetAdminPolicies, setTestnetAdminPolicies] = useState<any[]>([]);
16+
interface Policy {
17+
policy_type: string;
18+
address: string;
19+
}
20+
21+
interface PoliciesResponse {
22+
policies: {
23+
items: Policy[];
24+
};
25+
}
2126

27+
export const AdminPolicy = () => {
28+
const [authorizations, setAuthorizations] = useState<Authorization[]>([]);
29+
const [policies, setPolicies] = useState<Policy[]>([]);
2230
const [activeTab, setActiveTab] = useState(networkTypeTabs[0]);
2331

2432
useEffect(() => {
25-
setMainnetAdminPolicies([]);
26-
setTestnetAdminPolicies([]);
27-
2833
const baseUrl = rpcByNetworkType[activeTab.networkType];
2934

30-
fetch(`${baseUrl}/zeta-chain/observer/params`)
35+
// Fetch authorizations
36+
fetch(`${baseUrl}/zeta-chain/authority/authorizations`)
37+
.then((response) => response.json())
38+
.then((data: AuthorizationResponse) => {
39+
setAuthorizations(data.authorization_list.authorizations);
40+
})
41+
.catch((error) => {
42+
console.error("Error fetching authorizations:", error);
43+
});
44+
45+
// Fetch policies
46+
fetch(`${baseUrl}/zeta-chain/authority/policies`)
3147
.then((response) => response.json())
32-
.then((data) => {
33-
const policies = data.params.admin_policy;
34-
policies.forEach((policy: any) => {
35-
fetch(`${baseUrl}/cosmos/group/v1/group_policy_info/${policy.address}`)
36-
.then((response) => response.json())
37-
.then((detailData) => {
38-
fetch(`${baseUrl}/cosmos/group/v1/group_members/${detailData.info.group_id}`)
39-
.then((response) => response.json())
40-
.then((membersData) => {
41-
if (activeTab.networkType === "mainnet") {
42-
setMainnetAdminPolicies((prevPolicies) => [
43-
...prevPolicies,
44-
{
45-
...detailData.info,
46-
created_at: formatDate(detailData.info.created_at),
47-
policy_type: capitalizeFirstLetter(policy.policy_type),
48-
members: membersData.members.map((m: any) => ({
49-
...m.member,
50-
addedAt: formatDate(m.member.added_at),
51-
})),
52-
decision_policy: detailData.info.decision_policy,
53-
},
54-
]);
55-
}
56-
57-
if (activeTab.networkType === "testnet") {
58-
setTestnetAdminPolicies((prevPolicies) => [
59-
...prevPolicies,
60-
{
61-
...detailData.info,
62-
created_at: formatDate(detailData.info.created_at),
63-
policy_type: capitalizeFirstLetter(policy.policy_type),
64-
members: membersData.members.map((m: any) => ({
65-
...m.member,
66-
addedAt: formatDate(m.member.added_at),
67-
})),
68-
decision_policy: detailData.info.decision_policy,
69-
},
70-
]);
71-
}
72-
});
73-
});
74-
});
48+
.then((data: PoliciesResponse) => {
49+
setPolicies(data.policies.items);
7550
})
7651
.catch((error) => {
77-
console.error("Error fetching admin policies:", error);
52+
console.error("Error fetching policies:", error);
7853
});
7954
}, [activeTab.networkType]);
8055

81-
const adminPolicies = useMemo(() => {
82-
return activeTab.networkType === "mainnet" ? mainnetAdminPolicies : testnetAdminPolicies;
83-
}, [activeTab.networkType, mainnetAdminPolicies, testnetAdminPolicies]);
56+
const groupedAuthorizations = authorizations.reduce((acc, auth) => {
57+
const group = auth.authorized_policy;
58+
if (!acc[group]) {
59+
acc[group] = [];
60+
}
61+
const cleanMsg = auth.msg_url.replace("/zetachain.zetacore.", "");
62+
acc[group].push(cleanMsg);
63+
return acc;
64+
}, {} as Record<string, string[]>);
65+
66+
const getPolicyAddress = (policyType: string) => {
67+
const policy = policies.find((p) => p.policy_type === policyType);
68+
return policy?.address || "";
69+
};
70+
71+
const formatGroupName = (group: string) => {
72+
return `Group Policy "${group.replace("group", "")}"`;
73+
};
74+
75+
const formatModuleName = (module: string) => {
76+
return `${module.charAt(0).toUpperCase() + module.slice(1)} Module`;
77+
};
78+
79+
const groupByModule = (messages: string[]) => {
80+
return messages.reduce((acc, msg) => {
81+
const module = msg.split(".")[0];
82+
if (!acc[module]) {
83+
acc[module] = [];
84+
}
85+
acc[module].push(msg);
86+
return acc;
87+
}, {} as Record<string, string[]>);
88+
};
8489

8590
return (
8691
<div className="mt-8 first:mt-0">
8792
<NetworkTypeTabs activeTab={activeTab} setActiveTab={setActiveTab} layoutIdPrefix="admin-policy-" />
8893

89-
{adminPolicies.length > 0 ? (
90-
adminPolicies.map((policy: any, index) => (
91-
// eslint-disable-next-line react/no-array-index-key
92-
<div key={index}>
93-
<h3 className="text-xl mt-8 font-medium">Policy: {policy?.policy_type}</h3>
94-
95-
<div className="overflow-x-auto mt-8">
96-
<table>
97-
<tbody>
98-
<tr>
99-
<td>Address</td>
100-
<td>{policy.address}</td>
101-
</tr>
102-
<tr>
103-
<td>Admin</td>
104-
<td>{policy.admin}</td>
105-
</tr>
106-
<tr>
107-
<td>Created At</td>
108-
<td>{policy.created_at}</td>
109-
</tr>
110-
<tr>
111-
<td>Group ID</td>
112-
<td>{policy.group_id}</td>
113-
</tr>
114-
<tr>
115-
<td>Metadata</td>
116-
<td>{policy.metadata}</td>
117-
</tr>
118-
<tr>
119-
<td>Decision Policy Type</td>
120-
<td>{policy.decision_policy["@type"].split("/").pop()}</td>
121-
</tr>
122-
<tr>
123-
<td>Threshold</td>
124-
<td>{policy.decision_policy.threshold}</td>
125-
</tr>
126-
<tr>
127-
<td>Min Execution Period</td>
128-
<td>{policy.decision_policy.windows.min_execution_period}</td>
129-
</tr>
130-
<tr>
131-
<td>Voting Period</td>
132-
<td>{policy.decision_policy.windows.voting_period}</td>
133-
</tr>
134-
</tbody>
135-
</table>
136-
</div>
137-
138-
<h3 className="text-xl mt-8 font-medium">Members</h3>
139-
140-
<div className="overflow-x-auto mt-8">
141-
<table>
142-
<thead>
143-
<tr>
144-
<th>Added At</th>
145-
<th>Address</th>
146-
<th>Metadata</th>
147-
<th>Weight</th>
148-
</tr>
149-
</thead>
150-
<tbody>
151-
{policy.members.map((member: any, memberIndex: number) => (
152-
// eslint-disable-next-line react/no-array-index-key
153-
<tr key={memberIndex}>
154-
<td>{member.addedAt}</td>
155-
<td>{member.address}</td>
156-
<td>{member.metadata}</td>
157-
<td>{member.weight}</td>
158-
</tr>
159-
))}
160-
</tbody>
161-
</table>
94+
<div className="mt-8 space-y-8">
95+
{Object.entries(groupedAuthorizations).map(([group, messages]) => {
96+
const moduleGroups = groupByModule(messages);
97+
return (
98+
<div key={group}>
99+
<h2 className="text-2xl font-medium mb-2">{formatGroupName(group)}</h2>
100+
<div className="text-sm text-gray-500 mb-4">Address: {getPolicyAddress(group)}</div>
101+
<div className="space-y-4">
102+
{Object.entries(moduleGroups).map(([module, msgs]) => (
103+
<div key={module}>
104+
<h3 className="text-lg font-medium mb-2">{formatModuleName(module)}</h3>
105+
<ul className="list-disc list-inside space-y-1">
106+
{msgs.map((msg, index) => (
107+
<li key={index} className="text-sm">
108+
{msg.split(".")[1]}
109+
</li>
110+
))}
111+
</ul>
112+
</div>
113+
))}
114+
</div>
162115
</div>
163-
</div>
164-
))
165-
) : (
166-
<LoadingTable rowCount={9} />
167-
)}
116+
);
117+
})}
118+
</div>
168119
</div>
169120
);
170121
};

src/pages/developers/architecture/privileged.mdx

+4-13
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ title: Privileged Actions
33
---
44

55
import { AdminPolicy } from "~/components/Docs";
6-
76
import { Alert } from "~/components/shared";
87

98
Certain privileged actions (transaction messages) are only allowed to be
@@ -25,8 +24,6 @@ ZetaChain can have any number of groups. Anyone can create a group. In this
2524
document we only consider policy accounts that give authorization to perform
2625
privileged actions.
2726

28-
These "special" policy accounts are defined in the [params of the observer
29-
module](https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/authority/policies).
3027
These policy accounts are set during genesis and as any module parameter they
3128
can be changed through governance. This is important, because even though the
3229
protocol has a notion of admins and privileged policy accounts, they are chosen
@@ -35,15 +32,9 @@ members of a group become malicious, the community can create a new group with
3532
new admin and members and use the parameter change governance proposal to point
3633
the parameter of the observer module to the new policy accounts.
3734

38-
To learn which policy accounts can send which privileged messages, query the [zeta-chain/authority/authorizations](https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/authority/authorizations) endpoint.
39-
40-
<Alert variant="note">
41-
{" "}
42-
Notice that policy accounts below are called "groupEmergency", "groupOperational", "groupAdmin". These are just names that indicate the level of
43-
permissions and are not related to the actual groups associated with policy accounts. As you can see in testnet there are three entries
44-
that both point to the same policy account. This means that right now even though there are three
45-
levels of permissions ("groupEmergency", "groupOperational", "groupAdmin") there is only one policy account that is authorized to perform
46-
privileged actions. {" "}
47-
</Alert>
35+
The table below shows all privileged messages grouped by their required policy
36+
account and module. Each message is organized under its respective module
37+
(crosschain, fungible, observer, etc.) and requires authorization from the
38+
specified policy account.
4839

4940
<AdminPolicy />

src/pages/developers/chains/_meta.json

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
"title": "Ton",
2424
"description": "Make calls to universal apps and deposit from TON"
2525
},
26+
"sui": {
27+
"title": "Sui",
28+
"description": "Make calls to universal apps and deposit tokens from Sui"
29+
},
2630
"bitcoin": {
2731
"title": "Bitcoin",
2832
"description": "Make calls to universal apps and deposit BTC from Bitcoin"

0 commit comments

Comments
 (0)