Msig: Introduce an API & CLI to calculate amount that vests between 2 tipsets
This commit is contained in:
parent
6bdd433570
commit
aaad01105e
@ -384,6 +384,9 @@ type FullNode interface {
|
|||||||
|
|
||||||
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
|
// MsigGetAvailableBalance returns the portion of a multisig's balance that can be withdrawn or spent
|
||||||
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
MsigGetAvailableBalance(context.Context, address.Address, types.TipSetKey) (types.BigInt, error)
|
||||||
|
// MsigGetVested returns the amount of FIL that vested in a multisig in a certain period.
|
||||||
|
// It takes the following params: <multisig address>, <start epoch>, <end epoch>
|
||||||
|
MsigGetVested(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error)
|
||||||
// MsigCreate creates a multisig wallet
|
// MsigCreate creates a multisig wallet
|
||||||
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
|
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
|
||||||
//<initial balance>, <sender address of the create msg>, <gas price>
|
//<initial balance>, <sender address of the create msg>, <gas price>
|
||||||
|
@ -197,6 +197,7 @@ type FullNodeStruct struct {
|
|||||||
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
|
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, error) `perm:"read"`
|
||||||
|
|
||||||
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
MsigGetAvailableBalance func(context.Context, address.Address, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||||
|
MsigGetVested func(context.Context, address.Address, types.TipSetKey, types.TipSetKey) (types.BigInt, error) `perm:"read"`
|
||||||
MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
MsigCreate func(context.Context, uint64, []address.Address, abi.ChainEpoch, types.BigInt, address.Address, types.BigInt) (cid.Cid, error) `perm:"sign"`
|
||||||
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
MsigPropose func(context.Context, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
||||||
MsigApprove func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
MsigApprove func(context.Context, address.Address, uint64, address.Address, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
||||||
@ -866,6 +867,10 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
|
|||||||
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
|
return c.Internal.MsigGetAvailableBalance(ctx, a, tsk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FullNodeStruct) MsigGetVested(ctx context.Context, a address.Address, sTsk types.TipSetKey, eTsk types.TipSetKey) (types.BigInt, error) {
|
||||||
|
return c.Internal.MsigGetVested(ctx, a, sTsk, eTsk)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
|
func (c *FullNodeStruct) MsigCreate(ctx context.Context, req uint64, addrs []address.Address, duration abi.ChainEpoch, val types.BigInt, src address.Address, gp types.BigInt) (cid.Cid, error) {
|
||||||
return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp)
|
return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp)
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,7 @@ var multisigCmd = &cli.Command{
|
|||||||
msigSwapProposeCmd,
|
msigSwapProposeCmd,
|
||||||
msigSwapApproveCmd,
|
msigSwapApproveCmd,
|
||||||
msigSwapCancelCmd,
|
msigSwapCancelCmd,
|
||||||
|
msigVestedCmd,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,3 +737,65 @@ var msigSwapCancelCmd = &cli.Command{
|
|||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var msigVestedCmd = &cli.Command{
|
||||||
|
Name: "vested",
|
||||||
|
Usage: "Gets the amount vested in an msig between two epochs",
|
||||||
|
ArgsUsage: "[multisigAddress]",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "start-epoch",
|
||||||
|
Usage: "start epoch to measure vesting from",
|
||||||
|
Value: 0,
|
||||||
|
},
|
||||||
|
&cli.Int64Flag{
|
||||||
|
Name: "end-epoch",
|
||||||
|
Usage: "end epoch to stop measure vesting at",
|
||||||
|
Value: -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Action: func(cctx *cli.Context) error {
|
||||||
|
if cctx.Args().Len() != 1 {
|
||||||
|
return ShowHelp(cctx, fmt.Errorf("must pass multisig address"))
|
||||||
|
}
|
||||||
|
|
||||||
|
api, closer, err := GetFullNodeAPI(cctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer closer()
|
||||||
|
ctx := ReqContext(cctx)
|
||||||
|
|
||||||
|
msig, err := address.NewFromString(cctx.Args().Get(0))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
start, err := api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Int64("start-epoch")), types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var end *types.TipSet
|
||||||
|
if cctx.Int64("end-epoch") < 0 {
|
||||||
|
end, err = LoadTipSet(ctx, cctx, api)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
end, err = api.ChainGetTipSetByHeight(ctx, abi.ChainEpoch(cctx.Int64("end-epoch")), types.EmptyTSK)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret, err := api.MsigGetVested(ctx, msig, start.Key(), end.Key())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("Vested: %s between %d and %d\n", types.FIL(ret), start.Height(), end.Height())
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -886,6 +886,48 @@ func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Add
|
|||||||
return types.BigSub(act.Balance, minBalance), nil
|
return types.BigSub(act.Balance, minBalance), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *StateAPI) MsigGetVested(ctx context.Context, addr address.Address, start types.TipSetKey, end types.TipSetKey) (types.BigInt, error) {
|
||||||
|
startTs, err := a.Chain.GetTipSetFromKey(start)
|
||||||
|
if err != nil {
|
||||||
|
return types.EmptyInt, xerrors.Errorf("loading start tipset %s: %w", start, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
endTs, err := a.Chain.GetTipSetFromKey(end)
|
||||||
|
if err != nil {
|
||||||
|
return types.EmptyInt, xerrors.Errorf("loading end tipset %s: %w", end, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if startTs.Height() > endTs.Height() {
|
||||||
|
return types.EmptyInt, xerrors.Errorf("start tipset %d is after end tipset %d", startTs.Height(), endTs.Height())
|
||||||
|
} else if startTs.Height() == endTs.Height() {
|
||||||
|
return big.Zero(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var mst samsig.State
|
||||||
|
act, err := a.StateManager.LoadActorState(ctx, addr, &mst, endTs)
|
||||||
|
if err != nil {
|
||||||
|
return types.EmptyInt, xerrors.Errorf("failed to load multisig actor state at end epoch: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if act.Code != builtin.MultisigActorCodeID {
|
||||||
|
return types.EmptyInt, fmt.Errorf("given actor was not a multisig")
|
||||||
|
}
|
||||||
|
|
||||||
|
if mst.UnlockDuration == 0 ||
|
||||||
|
mst.InitialBalance.IsZero() ||
|
||||||
|
mst.StartEpoch+mst.UnlockDuration <= startTs.Height() ||
|
||||||
|
mst.StartEpoch >= endTs.Height() {
|
||||||
|
return big.Zero(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
startLk := mst.InitialBalance
|
||||||
|
if startTs.Height() > mst.StartEpoch {
|
||||||
|
startLk = mst.AmountLocked(startTs.Height() - mst.StartEpoch)
|
||||||
|
}
|
||||||
|
|
||||||
|
return big.Sub(startLk, mst.AmountLocked(endTs.Height()-mst.StartEpoch)), nil
|
||||||
|
}
|
||||||
|
|
||||||
var initialPledgeNum = types.NewInt(110)
|
var initialPledgeNum = types.NewInt(110)
|
||||||
var initialPledgeDen = types.NewInt(100)
|
var initialPledgeDen = types.NewInt(100)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user