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::actors::multisig::ext::MultisigExt;
11use crate::shim::{address::Address, econ::TokenAmount};
12use enumflags2::BitFlags;
13use fvm_ipld_blockstore::Blockstore;
14use num_bigint::BigInt;
15
16pub enum MsigGetAvailableBalance {}
17
18impl RpcMethod<2> for MsigGetAvailableBalance {
19 const NAME: &'static str = "Filecoin.MsigGetAvailableBalance";
20 const PARAM_NAMES: [&'static str; 2] = ["address", "tipset_key"];
21 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
22 const PERMISSION: Permission = Permission::Read;
23
24 type Params = (Address, ApiTipsetKey);
25 type Ok = TokenAmount;
26
27 async fn handle(
28 ctx: Ctx<impl Blockstore>,
29 (address, ApiTipsetKey(tsk)): Self::Params,
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.store(), actor.code, actor.state)?;
38 let locked_balance = ms.locked_balance(height)?.into();
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", "tipset_key"];
49 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
50 const PERMISSION: Permission = Permission::Read;
51
52 type Params = (Address, ApiTipsetKey);
53 type Ok = Vec<Transaction>;
54
55 async fn handle(
56 ctx: Ctx<impl Blockstore>,
57 (address, ApiTipsetKey(tsk)): Self::Params,
58 ) -> Result<Self::Ok, ServerError> {
59 let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?;
60 let ms: multisig::State = ctx
61 .state_manager
62 .get_actor_state_from_address(&ts, &address)?;
63 let txns = ms
64 .get_pending_txn(ctx.store())?
65 .iter()
66 .map(|txn| Transaction {
67 id: txn.id,
68 to: txn.to.into(),
69 value: txn.value.clone().into(),
70 method: txn.method,
71 params: txn.params.clone(),
72 approved: txn.approved.iter().map(|item| item.into()).collect(),
73 })
74 .collect();
75 Ok(txns)
76 }
77}
78
79pub enum MsigGetVested {}
80impl RpcMethod<3> for MsigGetVested {
81 const NAME: &'static str = "Filecoin.MsigGetVested";
82 const PARAM_NAMES: [&'static str; 3] = ["address", "start_tsk", "end_tsk"];
83 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
84 const PERMISSION: Permission = Permission::Read;
85
86 type Params = (Address, ApiTipsetKey, ApiTipsetKey);
87 type Ok = BigInt;
88
89 async fn handle(
90 ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
91 (addr, ApiTipsetKey(start_tsk), ApiTipsetKey(end_tsk)): Self::Params,
92 ) -> Result<Self::Ok, ServerError> {
93 let start_ts = ctx
94 .chain_store()
95 .load_required_tipset_or_heaviest(&start_tsk)?;
96 let end_ts = ctx
97 .chain_store()
98 .load_required_tipset_or_heaviest(&end_tsk)?;
99
100 match start_ts.epoch().cmp(&end_ts.epoch()) {
101 std::cmp::Ordering::Greater => Err(ServerError::internal_error(
102 "start tipset is after end tipset",
103 None,
104 )),
105 std::cmp::Ordering::Equal => Ok(BigInt::from(0)),
106 std::cmp::Ordering::Less => {
107 let ms: multisig::State = ctx
108 .state_manager
109 .get_actor_state_from_address(&end_ts, &addr)?;
110 let start_lb: TokenAmount = ms.locked_balance(start_ts.epoch())?.into();
111 let end_lb: TokenAmount = ms.locked_balance(end_ts.epoch())?.into();
112 Ok(start_lb.atto() - end_lb.atto())
113 }
114 }
115 }
116}
117
118pub enum MsigGetVestingSchedule {}
119impl RpcMethod<2> for MsigGetVestingSchedule {
120 const NAME: &'static str = "Filecoin.MsigGetVestingSchedule";
121 const PARAM_NAMES: [&'static str; 2] = ["address", "tsk"];
122 const API_PATHS: BitFlags<ApiPaths> = ApiPaths::all();
123 const PERMISSION: Permission = Permission::Read;
124
125 type Params = (Address, ApiTipsetKey);
126 type Ok = MsigVesting;
127
128 async fn handle(
129 ctx: Ctx<impl Blockstore + Send + Sync + 'static>,
130 (addr, ApiTipsetKey(tsk)): Self::Params,
131 ) -> Result<Self::Ok, ServerError> {
132 let ts = ctx.chain_store().load_required_tipset_or_heaviest(&tsk)?;
133 let ms: multisig::State = ctx.state_manager.get_actor_state_from_address(&ts, &addr)?;
134 Ok(ms.get_vesting_schedule()?)
135 }
136}