Filecoin.js

Filecoin.js

  • Documentation
  • API Reference
  • GitHub

›Extra

Getting started

  • Introduction
  • Adding Filecoin.js
  • Guides example
  • WS vs HTTP

Setup Wallet Providers

  • Setup lotus provider
  • Setup mnemonic provider
  • Setup metamask provider

Using a provider

  • Send message
  • Sign message
  • Verify message
  • Check if message is mined

Extra

  • Payment channels
  • State methods
  • Multisig Wallets

Contributing

  • How to contribute
  • Development workflow

Multisig Wallets

Multi-signature, or multisig, is a wallet configuration that requires at least two keys to authorize a transaction. You can specify the list of signers and the number of required signatures to approve a proposal when you create a multisig wallet. You can alter the signers list after creating the wallet by adding or removing addresses or by swaping an old address with a new one.

The multisig wallets can be programmed to release funds linearly by specifying a StartEpoch from which the funds are available and the UnlockDuration which controls the duration of the vesting period.

The MnemonicWalletProvider and LightWalletProvider implement all the functions listed below. The LotusWalletProvider has a few differences because it calls directly the lotus api and at the time of this writing (12 nov 2020) some things are not yet fully implemented. In msigCreate the startEpoch is hardcoded to 0 in the api call, and msigApproveRemoveSigner and msigCancelRemoveSigner are not implemented yet.

The operations you can propose are: transfer, add signer, swap signer and remove signer. The signers in the list can approve the proposal, and when the treshold is met the action is executed. The signer that initiated the operation can cancel it.

You can find the multisig actor code here.

General

    msigGetVestingSchedule(
        address: string,
        tipSetKey: TipSetKey,
    ): Promise < MsigVesting >

    msigGetAvailableBalance(
        address: string,
        tipSetKey: TipSetKey
    ): Promise < string >

    msigGetVested(
        address: string,
        startEpoch: TipSetKey,
        endEpoch: TipSetKey
    ): Promise < string >

Create multisig wallet

    msigCreate(
        requiredNumberOfSenders: number,
        approvingAddresses: string[],
        startEpoch: ChainEpoch,
        unlockDuration: ChainEpoch,
        initialBalance: string,
        senderAddressOfCreateMsg: string
    ): Promise < Cid >

Transfer funds

    msigProposeTransfer(
        address: string,
        recipientAddres: string,
        value: string,
        senderAddressOfProposeMsg: string
    ): Promise < Cid >

    msigApproveTransferTxHash(
        address: string,
        proposedMessageId: number,
        proposerAddress: string,
        recipientAddres: string,
        value: string,
        senderAddressOfApproveMsg: string
    ): Promise < Cid >

    msigCancelTransfer(
        address: string,
        senderAddressOfCancelMsg: string,
        proposedMessageId: number,
        recipientAddres: string,
        value: string,
        methodToCallInProposeMsg: number
    ): Promise < Cid >

Add signer

    msigProposeAddSigner(
        address: string,
        senderAddressOfProposeMsg: string,
        newSignerAddress: string,
        increaseNumberOfRequiredSigners: boolean
    ): Promise < Cid >

    msigApproveAddSigner(
        address: string,
        senderAddressOfApproveMsg: string,
        proposedMessageId: number,
        proposerAddress: string,
        newSignerAddress: string,
        increaseNumberOfRequiredSigners: boolean
    ): Promise < Cid >

    msigCancelAddSigner(
        address: string,
        senderAddressOfCancelMsg: string,
        proposedMessageId: number,
        newSignerAddress: string,
        increaseNumberOfRequiredSigners: boolean
    ): Promise < Cid >

Swap signer

    msigProposeSwapSigner(
        address: string,
        senderAddressOfProposeMsg: string,
        oldSignerAddress: string,
        newSignerAddress: string
    ): Promise < Cid >

    msigApproveSwapSigner(
        address: string,
        senderAddressOfApproveMsg: string,
        proposedMessageId: number,
        proposerAddress: string,
        oldSignerAddress: string,
        newSignerAddress: string
    ): Promise < Cid >

    msigCancelSwapSigner(
        address: string,
        senderAddressOfCancelMsg: string,
        proposedMessageId: number,
        oldSignerAddress: string,
        newSignerAddress: string
    ): Promise < Cid >

Remove signer

    msigProposeRemoveSigner(
        address: string,
        senderAddressOfProposeMsg: string,
        addressToRemove: string,
        decreaseNumberOfRequiredSigners: boolean
    ): Promise < Cid >

    msigApproveRemoveSigner(
        address: string,
        senderAddressOfApproveMsg: string,
        proposedMessageId: number,
        proposerAddress: string,
        addressToRemove: string,
        decreaseNumberOfRequiredSigners: boolean
    ): Promise < Cid >

    msigCancelRemoveSigner(
        address: string,
        senderAddressOfCancelMsg: string,
        proposedMessageId: number,
        addressToRemove: string,
        decreaseNumberOfRequiredSigners: boolean
    ): Promise < Cid >

Examples

// init wallet provider and create multisig wallet
const httpConnector = new HttpJsonRpcConnector({
    __LOTUS_RPC_ENDPOINT__,
    token: __LOTUS_AUTH_TOKEN__
});
const lotusClient = new LotusClient(httpConnector);
const mnemonicWalletProvider = new MnemonicWalletProvider(lotusClient, testMnemonic);

const noOfRequiredSigners = 2;
const signerAdresses = ...
const msigWalletCreator = ...

const multisigCid = await mnemonicWalletProvider.msigCreate(noOfRequiredSigners, signerAdresses, startEpoch, unlockDuration, initialBalance, msigWalletCreator);
const receipt = await lotusClient.state.waitMsg(multisigCid, 0);
// you can retrieve the address of the newly created multisig wallet from the receipt of the create wallet message
const multisigAddress = receipt.ReturnDec.RobustAddress;
const balance = await mnemonicWalletProvider.msigGetAvailableBalance(multisigAddress, []);


// propose transfer
const initTransferCid = await mnemonicWalletProvider.msigProposeTransfer(multisigAddress, receiverAddress, amountToTransfer, proposerAddress);
const receiptTransferPropose = await lotusClient.state.waitMsg(initTransferCid, 0);
// you can get the transaction id of a propose operation from the receipt of the propose message
const txnID = receiptTransferStart.ReturnDec.TxnID;

// approve transfer
const approveTransferCid = await mnemonicWalletProvider.msigApproveTransferTxHash(multisigAddress, txnID, proposerAddress, receiverAddress, amountToTransfer, approverAddress);
const receiptTransferApprove = await lotusClient.state.waitMsg(approveTransferCid, 0);

// cancel transfer - this message can only be sent by the sender of the initial proposal
const cancelTransferCid = await mnemonicWalletProvider.msigCancelTransfer(multisigAddress, proposerAddress, txnID, mnemonicAddress, amountToTransfer);
const receiptTransferCancel = await lotusClient.state.waitMsg(cancelTransferCid, 0);


// propose add signer
const initAddProposeCid = await mnemonicWalletProvider.msigProposeAddSigner(multisigAddress, proposerAddress, addressToAdd, increaseNumberOfRequiredSigners);
const receiptAddProposeCid = await lotusClient.state.waitMsg(initAddProposeCid, 0);
// you can get the transaction id of a propose operation from the receipt of the propose message
const txnID = receiptAddProposeCid.ReturnDec.TxnID;

// approve add signer
const approveAddCid = await mnemonicWalletProvider.msigApproveAddSigner(multisigAddress, approverAddress, txnID, proposerAddress, addressToAdd, increaseNumberOfRequiredSigners);
const receiptAddApprove = await lotusClient.state.waitMsg(approveAddCid, 0);

// cancel add signer - this message can only be sent by the sender of the initial proposal
const cancelAddCid = await mnemonicWalletProvider.msigCancelAddSigner(multisigAddress, proposerAddress, txnID, addressToAdd, increaseNumberOfRequiredSigners);
const receiptAddCancel = await lotusClient.state.waitMsg(cancelAddCid, 0);


// propose swap signer
const initSwapProposeCid = await mnemonicWalletProvider.msigProposeSwapSigner(multisigAddress, aproposerAddress, addressToSwapOut, addressToSwapIn);
const receiptSwapProposeCid = await lotusClient.state.waitMsg(initSwapProposeCid, 0);
// you can get the transaction id of a propose operation from the receipt of the propose message
const txnID = receiptSwapProposeCid.ReturnDec.TxnID;

// approve swap signer
const approveSwapCid = await mnemonicWalletProvider.msigApproveSwapSigner(multisigAddress, approverAddress, txnID, proposerAddress, addressToSwapOut, addressToSwapIn);
const receiptSwapApprove = await lotusClient.state.waitMsg(approveSwapCid, 0);

// cancel swap signer - this message can only be sent by the sender of the initial proposal
const cancelSwapCid = await mnemonicWalletProvider.msigCancelSwapSigner(multisigAddress, proposerAddress, txnID, addressToSwapOut, addressToSwapIn);
const receiptSwapCancel = await lotusClient.state.waitMsg(cancelSwapCid, 0);


// propose remove signer
const initRemoveProposeCid = await mnemonicWalletProvider.msigProposeRemoveSigner(multisigAddress, proposerAddress, addressToRemove, decreaseNumberOfSigners);
const receiptRemoveProposeCid = await lotusClient.state.waitMsg(initRemoveProposeCid, 0);
// you can get the transaction id of a propose operation from the receipt of the propose message
const txnID = receiptRemoveProposeCid.ReturnDec.TxnID;
assert.strictEqual(txnID, 0, 'error initiating add proposal');

// approve remove signer
const approveRemoveCid = await mnemonicWalletProvider.msigApproveRemoveSigner(multisigAddress, approverAddress, txnID, proposerAddress, addressToRemove, decreaseNumberOfSigners);
const receiptRemoveApprove = await lotusClient.state.waitMsg(approveRemoveCid, 0);

// cancel remove signer - this message can only be sent by the sender of the initial proposal
const cancelRemoveCid = await mnemonicWalletProvider.msigCancelRemoveSigner(multisigAddress, proposerAddress, txnID, addressToRemove, decreaseNumberOfSigners);
const receiptRemoveCancel = await lotusClient.state.waitMsg(cancelRemoveCid, 0);
← State methodsHow to contribute →
Docs
Getting StartedAPI Reference
Community
Slack
More
BlogGitHubStar
Copyright © 2022 Filecoin