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