Merge pull request #3590 from filecoin-project/asr/multisig
Multisig API additions
This commit is contained in:
commit
9e9856bb45
@ -397,6 +397,9 @@ type FullNode interface {
|
||||
|
||||
// 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)
|
||||
// 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
|
||||
// It takes the following params: <required number of senders>, <approving addresses>, <unlock duration>
|
||||
//<initial balance>, <sender address of the create msg>, <gas price>
|
||||
@ -413,17 +416,29 @@ type FullNode interface {
|
||||
// It takes the following params: <multisig address>, <proposed message ID>, <recipient address>, <value to transfer>,
|
||||
// <sender address of the cancel msg>, <method to call in the proposed message>, <params to include in the proposed message>
|
||||
MsigCancel(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error)
|
||||
// MsigAddPropose proposes adding a signer in the multisig
|
||||
// It takes the following params: <multisig address>, <sender address of the propose msg>,
|
||||
// <new signer>, <whether the number of required signers should be increased>
|
||||
MsigAddPropose(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error)
|
||||
// MsigAddApprove approves a previously proposed AddSigner message
|
||||
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
|
||||
// <proposer address>, <new signer>, <whether the number of required signers should be increased>
|
||||
MsigAddApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error)
|
||||
// MsigAddCancel cancels a previously proposed AddSigner message
|
||||
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
|
||||
// <new signer>, <whether the number of required signers should be increased>
|
||||
MsigAddCancel(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error)
|
||||
// MsigSwapPropose proposes swapping 2 signers in the multisig
|
||||
// It takes the following params: <multisig address>, <sender address of the propose msg>,
|
||||
// <old signer> <new signer>
|
||||
// <old signer>, <new signer>
|
||||
MsigSwapPropose(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error)
|
||||
// MsigSwapApprove approves a previously proposed SwapSigner
|
||||
// It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
|
||||
// <proposer address>, <old signer> <new signer>
|
||||
// <proposer address>, <old signer>, <new signer>
|
||||
MsigSwapApprove(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error)
|
||||
// MsigSwapCancel cancels a previously proposed SwapSigner message
|
||||
// It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
|
||||
// <old signer> <new signer>
|
||||
// <old signer>, <new signer>
|
||||
MsigSwapCancel(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error)
|
||||
|
||||
MarketEnsureAvailable(context.Context, address.Address, address.Address, types.BigInt) (cid.Cid, error)
|
||||
|
@ -201,10 +201,14 @@ type FullNodeStruct struct {
|
||||
StateCirculatingSupply func(context.Context, types.TipSetKey) (api.CirculatingSupply, 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"`
|
||||
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"`
|
||||
MsigCancel func(context.Context, address.Address, uint64, address.Address, types.BigInt, address.Address, uint64, []byte) (cid.Cid, error) `perm:"sign"`
|
||||
MsigAddPropose func(context.Context, address.Address, address.Address, address.Address, bool) (cid.Cid, error) `perm:"sign"`
|
||||
MsigAddApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, bool) (cid.Cid, error) `perm:"sign"`
|
||||
MsigAddCancel func(context.Context, address.Address, address.Address, uint64, address.Address, bool) (cid.Cid, error) `perm:"sign"`
|
||||
MsigSwapPropose func(context.Context, address.Address, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
MsigSwapApprove func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
MsigSwapCancel func(context.Context, address.Address, address.Address, uint64, address.Address, address.Address) (cid.Cid, error) `perm:"sign"`
|
||||
@ -882,6 +886,10 @@ func (c *FullNodeStruct) MsigGetAvailableBalance(ctx context.Context, a address.
|
||||
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) {
|
||||
return c.Internal.MsigCreate(ctx, req, addrs, duration, val, src, gp)
|
||||
}
|
||||
@ -898,6 +906,18 @@ func (c *FullNodeStruct) MsigCancel(ctx context.Context, msig address.Address, t
|
||||
return c.Internal.MsigCancel(ctx, msig, txID, to, amt, src, method, params)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
return c.Internal.MsigAddPropose(ctx, msig, src, newAdd, inc)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
return c.Internal.MsigAddApprove(ctx, msig, src, txID, proposer, newAdd, inc)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
return c.Internal.MsigAddCancel(ctx, msig, src, txID, newAdd, inc)
|
||||
}
|
||||
|
||||
func (c *FullNodeStruct) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
|
||||
return c.Internal.MsigSwapPropose(ctx, msig, src, oldAdd, newAdd)
|
||||
}
|
||||
|
300
cli/multisig.go
300
cli/multisig.go
@ -37,9 +37,13 @@ var multisigCmd = &cli.Command{
|
||||
msigInspectCmd,
|
||||
msigProposeCmd,
|
||||
msigApproveCmd,
|
||||
msigAddProposeCmd,
|
||||
msigAddApproveCmd,
|
||||
msigAddCancelCmd,
|
||||
msigSwapProposeCmd,
|
||||
msigSwapApproveCmd,
|
||||
msigSwapCancelCmd,
|
||||
msigVestedCmd,
|
||||
},
|
||||
}
|
||||
|
||||
@ -506,6 +510,236 @@ var msigApproveCmd = &cli.Command{
|
||||
},
|
||||
}
|
||||
|
||||
var msigAddProposeCmd = &cli.Command{
|
||||
Name: "add-propose",
|
||||
Usage: "Propose to add a signer",
|
||||
ArgsUsage: "[multisigAddress signer]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{
|
||||
Name: "increase-threshold",
|
||||
Usage: "whether the number of required signers should be increased",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "account to send the propose message from",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() != 2 {
|
||||
return ShowHelp(cctx, fmt.Errorf("must pass multisig address and signer 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
|
||||
}
|
||||
|
||||
addr, err := address.NewFromString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var from address.Address
|
||||
if cctx.IsSet("from") {
|
||||
f, err := address.NewFromString(cctx.String("from"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = f
|
||||
} else {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = defaddr
|
||||
}
|
||||
|
||||
msgCid, err := api.MsigAddPropose(ctx, msig, from, addr, cctx.Bool("increase-threshold"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("sent add proposal in message: ", msgCid)
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return fmt.Errorf("add proposal returned exit %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var msigAddApproveCmd = &cli.Command{
|
||||
Name: "add-approve",
|
||||
Usage: "Approve a message to add a signer",
|
||||
ArgsUsage: "[multisigAddress proposerAddress txId newAddress increaseThreshold]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "account to send the approve message from",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() != 5 {
|
||||
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, proposer address, transaction id, new signer address, whether to increase threshold"))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
prop, err := address.NewFromString(cctx.Args().Get(1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txid, err := strconv.ParseUint(cctx.Args().Get(2), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newAdd, err := address.NewFromString(cctx.Args().Get(3))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inc, err := strconv.ParseBool(cctx.Args().Get(4))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var from address.Address
|
||||
if cctx.IsSet("from") {
|
||||
f, err := address.NewFromString(cctx.String("from"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = f
|
||||
} else {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = defaddr
|
||||
}
|
||||
|
||||
msgCid, err := api.MsigAddApprove(ctx, msig, from, txid, prop, newAdd, inc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("sent add approval in message: ", msgCid)
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return fmt.Errorf("add approval returned exit %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var msigAddCancelCmd = &cli.Command{
|
||||
Name: "add-cancel",
|
||||
Usage: "Cancel a message to add a signer",
|
||||
ArgsUsage: "[multisigAddress txId newAddress increaseThreshold]",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "from",
|
||||
Usage: "account to send the approve message from",
|
||||
},
|
||||
},
|
||||
Action: func(cctx *cli.Context) error {
|
||||
if cctx.Args().Len() != 4 {
|
||||
return ShowHelp(cctx, fmt.Errorf("must pass multisig address, transaction id, new signer address, whether to increase threshold"))
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
txid, err := strconv.ParseUint(cctx.Args().Get(1), 10, 64)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
newAdd, err := address.NewFromString(cctx.Args().Get(2))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
inc, err := strconv.ParseBool(cctx.Args().Get(3))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var from address.Address
|
||||
if cctx.IsSet("from") {
|
||||
f, err := address.NewFromString(cctx.String("from"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = f
|
||||
} else {
|
||||
defaddr, err := api.WalletDefaultAddress(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from = defaddr
|
||||
}
|
||||
|
||||
msgCid, err := api.MsigAddCancel(ctx, msig, from, txid, newAdd, inc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("sent add cancellation in message: ", msgCid)
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return fmt.Errorf("add cancellation returned exit %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var msigSwapProposeCmd = &cli.Command{
|
||||
Name: "swap-propose",
|
||||
Usage: "Propose to swap signers",
|
||||
@ -722,7 +956,7 @@ var msigSwapCancelCmd = &cli.Command{
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("sent swap approval in message: ", msgCid)
|
||||
fmt.Println("sent swap cancellation in message: ", msgCid)
|
||||
|
||||
wait, err := api.StateWaitMsg(ctx, msgCid, build.MessageConfidence)
|
||||
if err != nil {
|
||||
@ -730,9 +964,71 @@ var msigSwapCancelCmd = &cli.Command{
|
||||
}
|
||||
|
||||
if wait.Receipt.ExitCode != 0 {
|
||||
return fmt.Errorf("swap approval returned exit %d", wait.Receipt.ExitCode)
|
||||
return fmt.Errorf("swap cancellation returned exit %d", wait.Receipt.ExitCode)
|
||||
}
|
||||
|
||||
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
|
||||
},
|
||||
}
|
||||
|
@ -75,10 +75,14 @@
|
||||
* [MpoolSetConfig](#MpoolSetConfig)
|
||||
* [MpoolSub](#MpoolSub)
|
||||
* [Msig](#Msig)
|
||||
* [MsigAddApprove](#MsigAddApprove)
|
||||
* [MsigAddCancel](#MsigAddCancel)
|
||||
* [MsigAddPropose](#MsigAddPropose)
|
||||
* [MsigApprove](#MsigApprove)
|
||||
* [MsigCancel](#MsigCancel)
|
||||
* [MsigCreate](#MsigCreate)
|
||||
* [MsigGetAvailableBalance](#MsigGetAvailableBalance)
|
||||
* [MsigGetVested](#MsigGetVested)
|
||||
* [MsigPropose](#MsigPropose)
|
||||
* [MsigSwapApprove](#MsigSwapApprove)
|
||||
* [MsigSwapCancel](#MsigSwapCancel)
|
||||
@ -1839,6 +1843,84 @@ The Msig methods are used to interact with multisig wallets on the
|
||||
filecoin network
|
||||
|
||||
|
||||
### MsigAddApprove
|
||||
MsigAddApprove approves a previously proposed AddSigner message
|
||||
It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
|
||||
<proposer address>, <new signer>, <whether the number of required signers should be increased>
|
||||
|
||||
|
||||
Perms: sign
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"t01234",
|
||||
"t01234",
|
||||
42,
|
||||
"t01234",
|
||||
"t01234",
|
||||
true
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### MsigAddCancel
|
||||
MsigAddCancel cancels a previously proposed AddSigner message
|
||||
It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
|
||||
<new signer>, <whether the number of required signers should be increased>
|
||||
|
||||
|
||||
Perms: sign
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"t01234",
|
||||
"t01234",
|
||||
42,
|
||||
"t01234",
|
||||
true
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### MsigAddPropose
|
||||
MsigAddPropose proposes adding a signer in the multisig
|
||||
It takes the following params: <multisig address>, <sender address of the propose msg>,
|
||||
<new signer>, <whether the number of required signers should be increased>
|
||||
|
||||
|
||||
Perms: sign
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"t01234",
|
||||
"t01234",
|
||||
"t01234",
|
||||
true
|
||||
]
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
}
|
||||
```
|
||||
|
||||
### MsigApprove
|
||||
MsigApprove approves a previously-proposed multisig message
|
||||
It takes the following params: <multisig address>, <proposed message ID>, <proposer address>, <recipient address>, <value to transfer>,
|
||||
@ -1946,6 +2028,38 @@ Inputs:
|
||||
|
||||
Response: `"0"`
|
||||
|
||||
### MsigGetVested
|
||||
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>
|
||||
|
||||
|
||||
Perms: read
|
||||
|
||||
Inputs:
|
||||
```json
|
||||
[
|
||||
"t01234",
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
{
|
||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"/": "bafy2bzacea3wsdh6y3a36tb3skempjoxqpuyompjbmfeyf34fi3uy6uue42v4"
|
||||
},
|
||||
{
|
||||
"/": "bafy2bzacebp3shtrn43k7g3unredz7fxn4gj533d3o43tqn2p2ipxxhrvchve"
|
||||
}
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
Response: `"0"`
|
||||
|
||||
### MsigPropose
|
||||
MsigPropose proposes a multisig message
|
||||
It takes the following params: <multisig address>, <recipient address>, <value to transfer>,
|
||||
@ -1976,7 +2090,7 @@ Response:
|
||||
### MsigSwapApprove
|
||||
MsigSwapApprove approves a previously proposed SwapSigner
|
||||
It takes the following params: <multisig address>, <sender address of the approve msg>, <proposed message ID>,
|
||||
<proposer address>, <old signer> <new signer>
|
||||
<proposer address>, <old signer>, <new signer>
|
||||
|
||||
|
||||
Perms: sign
|
||||
@ -2003,7 +2117,7 @@ Response:
|
||||
### MsigSwapCancel
|
||||
MsigSwapCancel cancels a previously proposed SwapSigner message
|
||||
It takes the following params: <multisig address>, <sender address of the cancel msg>, <proposed message ID>,
|
||||
<old signer> <new signer>
|
||||
<old signer>, <new signer>
|
||||
|
||||
|
||||
Perms: sign
|
||||
@ -2029,7 +2143,7 @@ Response:
|
||||
### MsigSwapPropose
|
||||
MsigSwapPropose proposes swapping 2 signers in the multisig
|
||||
It takes the following params: <multisig address>, <sender address of the propose msg>,
|
||||
<old signer> <new signer>
|
||||
<old signer>, <new signer>
|
||||
|
||||
|
||||
Perms: sign
|
||||
|
@ -130,6 +130,33 @@ func (a *MsigAPI) MsigPropose(ctx context.Context, msig address.Address, to addr
|
||||
return smsg.Cid(), nil
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigAddPropose(ctx context.Context, msig address.Address, src address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
enc, actErr := serializeAddParams(newAdd, inc)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigPropose(ctx, msig, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.AddSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigAddApprove(ctx context.Context, msig address.Address, src address.Address, txID uint64, proposer address.Address, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
enc, actErr := serializeAddParams(newAdd, inc)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigApprove(ctx, msig, txID, proposer, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.AddSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigAddCancel(ctx context.Context, msig address.Address, src address.Address, txID uint64, newAdd address.Address, inc bool) (cid.Cid, error) {
|
||||
enc, actErr := serializeAddParams(newAdd, inc)
|
||||
if actErr != nil {
|
||||
return cid.Undef, actErr
|
||||
}
|
||||
|
||||
return a.MsigCancel(ctx, msig, txID, msig, big.Zero(), src, uint64(builtin.MethodsMultisig.AddSigner), enc)
|
||||
}
|
||||
|
||||
func (a *MsigAPI) MsigSwapPropose(ctx context.Context, msig address.Address, src address.Address, oldAdd address.Address, newAdd address.Address) (cid.Cid, error) {
|
||||
enc, actErr := serializeSwapParams(oldAdd, newAdd)
|
||||
if actErr != nil {
|
||||
@ -244,6 +271,18 @@ func (a *MsigAPI) msigApproveOrCancel(ctx context.Context, operation api.MsigPro
|
||||
return smsg.Cid(), nil
|
||||
}
|
||||
|
||||
func serializeAddParams(new address.Address, inc bool) ([]byte, error) {
|
||||
enc, actErr := actors.SerializeParams(&samsig.AddSignerParams{
|
||||
Signer: new,
|
||||
Increase: inc,
|
||||
})
|
||||
if actErr != nil {
|
||||
return nil, actErr
|
||||
}
|
||||
|
||||
return enc, nil
|
||||
}
|
||||
|
||||
func serializeSwapParams(old address.Address, new address.Address) ([]byte, error) {
|
||||
enc, actErr := actors.SerializeParams(&samsig.SwapSignerParams{
|
||||
From: old,
|
||||
|
@ -886,6 +886,48 @@ func (a *StateAPI) MsigGetAvailableBalance(ctx context.Context, addr address.Add
|
||||
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 initialPledgeDen = types.NewInt(100)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user