forest/rpc/methods/
msig.rs1use crate::rpc::error::ServerError;
5use crate::rpc::types::ApiTipsetKey;
6use crate::rpc::types::*;
7use crate::rpc::{ApiPaths, Ctx, Permission, RpcMethod};
8use crate::shim::actors::MultisigActorStateLoad as _;
9use crate::shim::actors::multisig;
10use crate::shim::{address::Address, econ::TokenAmount};
11use enumflags2::BitFlags;
12use num_bigint::BigInt;
13
14pub enum MsigGetAvailableBalance {}
15
16impl RpcMethod<2> for MsigGetAvailableBalance {
17 const NAME: &'static str = "Filecoin.MsigGetAvailableBalance";
18 const PARAM_NAMES: [&'static str; 2] = ["address", "tipsetKey"];
19 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
20 const PERMISSION: Permission = Permission::Read;
21 const DESCRIPTION: &'static str = "Returns the spendable balance of the given multisig (total balance minus the locked amount) at the given tipset.";
22
23 type Params = (Address, ApiTipsetKey);
24 type Ok = TokenAmount;
25
26 async fn handle(
27 ctx: Ctx,
28 (address, ApiTipsetKey(tsk)): Self::Params,
29 _: &http::Extensions,
30 ) -> Result<Self::Ok, ServerError> {
31 let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?;
32 let height = ts.epoch();
33 let actor = ctx
34 .state_manager
35 .get_required_actor(&address, *ts.parent_state())?;
36 let actor_balance = TokenAmount::from(&actor.balance);
37 let ms = multisig::State::load(ctx.db(), actor.code, actor.state)?;
38 let locked_balance = ms.locked_balance(height)?;
39 let avail_balance = &actor_balance - locked_balance;
40 Ok(avail_balance)
41 }
42}
43
44pub enum MsigGetPending {}
45
46impl RpcMethod<2> for MsigGetPending {
47 const NAME: &'static str = "Filecoin.MsigGetPending";
48 const PARAM_NAMES: [&'static str; 2] = ["address", "tipsetKey"];
49 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
50 const PERMISSION: Permission = Permission::Read;
51 const DESCRIPTION: &'static str =
52 "Returns the transactions awaiting approval in the given multisig at the given tipset.";
53
54 type Params = (Address, ApiTipsetKey);
55 type Ok = Vec<Transaction>;
56
57 async fn handle(
58 ctx: Ctx,
59 (address, ApiTipsetKey(tsk)): Self::Params,
60 _: &http::Extensions,
61 ) -> Result<Self::Ok, ServerError> {
62 let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?;
63 let ms: multisig::State = ctx
64 .state_manager
65 .get_actor_state_from_address(&ts, &address)?;
66 let txns = ms
67 .get_pending_txn(ctx.db())?
68 .into_iter()
69 .map(|txn| Transaction {
70 id: txn.id,
71 to: txn.to,
72 value: txn.value,
73 method: txn.method,
74 params: txn.params,
75 approved: txn.approved,
76 })
77 .collect();
78 Ok(txns)
79 }
80}
81
82pub enum MsigGetVested {}
83impl RpcMethod<3> for MsigGetVested {
84 const NAME: &'static str = "Filecoin.MsigGetVested";
85 const PARAM_NAMES: [&'static str; 3] = ["address", "startTipsetKey", "endTipsetKey"];
86 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
87 const PERMISSION: Permission = Permission::Read;
88 const DESCRIPTION: &'static str =
89 "Returns the amount that vested in the given multisig between the start and end tipsets.";
90
91 type Params = (Address, ApiTipsetKey, ApiTipsetKey);
92 type Ok = BigInt;
93
94 async fn handle(
95 ctx: Ctx,
96 (addr, ApiTipsetKey(start_tsk), ApiTipsetKey(end_tsk)): Self::Params,
97 _: &http::Extensions,
98 ) -> Result<Self::Ok, ServerError> {
99 let start_ts = ctx
100 .chain_store()
101 .load_required_tipset_or_heaviest(&start_tsk)?;
102 let end_ts = ctx
103 .chain_store()
104 .load_required_tipset_or_heaviest(&end_tsk)?;
105
106 match start_ts.epoch().cmp(&end_ts.epoch()) {
107 std::cmp::Ordering::Greater => Err(ServerError::internal_error(
108 "start tipset is after end tipset",
109 None,
110 )),
111 std::cmp::Ordering::Equal => Ok(BigInt::from(0)),
112 std::cmp::Ordering::Less => {
113 let ms: multisig::State = ctx
114 .state_manager
115 .get_actor_state_from_address(&end_ts, &addr)?;
116 let start_lb = ms.locked_balance(start_ts.epoch())?;
117 let end_lb = ms.locked_balance(end_ts.epoch())?;
118 Ok(start_lb.atto() - end_lb.atto())
119 }
120 }
121 }
122}
123
124pub enum MsigGetVestingSchedule {}
125impl RpcMethod<2> for MsigGetVestingSchedule {
126 const NAME: &'static str = "Filecoin.MsigGetVestingSchedule";
127 const PARAM_NAMES: [&'static str; 2] = ["address", "tsk"];
128 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
129 const PERMISSION: Permission = Permission::Read;
130 const DESCRIPTION: &'static str =
131 "Returns the vesting schedule of the given multisig at the given tipset.";
132
133 type Params = (Address, ApiTipsetKey);
134 type Ok = MsigVesting;
135
136 async fn handle(
137 ctx: Ctx,
138 (addr, ApiTipsetKey(tsk)): Self::Params,
139 _: &http::Extensions,
140 ) -> Result<Self::Ok, ServerError> {
141 let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?;
142 let ms: multisig::State = ctx.state_manager.get_actor_state_from_address(&ts, &addr)?;
143 Ok(ms.get_vesting_schedule()?)
144 }
145}