# Getting Started

## Multisig IDL

Right now the best way to interact with the Cashmere multisig programmatically is directly through our IDL. Eventually we will provide an SDK which will make integrations easier.

The program is published on-chain at:

* **Mainnet**: [AzHKmHjEoZ7JqiTUPgPVAZgtyNLwa3BTsRgffYxCVDD](https://explorer.solana.com/address/AzHKmHjEoZ7JqiTUPgPVAZgtyNLwa3BTsRgffYxCVDDZ/anchor-program)
* **Testnet**: [AK6khFGW1guZxEJG3rd8SrEWW9Cdk13UQGD4f9hnn9AW](https://explorer.solana.com/address/AK6khFGW1guZxEJG3rd8SrEWW9Cdk13UQGD4f9hnn9AW/anchor-program?cluster=testnet)
* **Devnet**: [4wcedASdm3sDGirPGBjYsEjSGcLzFWM5fa4EY8RK6KHg](https://explorer.solana.com/address/4wcedASdm3sDGirPGBjYsEjSGcLzFWM5fa4EY8RK6KHg/anchor-program?cluster=devnet)

<details>

<summary>IDL Reference</summary>

```json
{
  "version": "0.0.0",
  "name": "multisig",
  "instructions": [
    {
      "name": "createMultisig",
      "accounts": [
        {
          "name": "multisig",
          "isMut": true,
          "isSigner": true
        },
        {
          "name": "treasury",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "payer",
          "isMut": true,
          "isSigner": true
        },
        {
          "name": "systemProgram",
          "isMut": false,
          "isSigner": false
        }
      ],
      "args": [
        {
          "name": "owners",
          "type": {
            "vec": "publicKey"
          }
        },
        {
          "name": "maxOwners",
          "type": "u8"
        },
        {
          "name": "threshold",
          "type": "u64"
        },
        {
          "name": "nonce",
          "type": "u8"
        }
      ]
    },
    {
      "name": "createTransaction",
      "accounts": [
        {
          "name": "multisig",
          "isMut": false,
          "isSigner": false
        },
        {
          "name": "transaction",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "proposer",
          "isMut": false,
          "isSigner": true
        }
      ],
      "args": [
        {
          "name": "programid",
          "type": "publicKey"
        },
        {
          "name": "dataAccounts",
          "type": {
            "vec": {
              "defined": "TransactionAccount"
            }
          }
        },
        {
          "name": "instructionData",
          "type": "bytes"
        }
      ]
    },
    {
      "name": "approve",
      "accounts": [
        {
          "name": "multisig",
          "isMut": false,
          "isSigner": false
        },
        {
          "name": "transaction",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "owner",
          "isMut": false,
          "isSigner": true
        }
      ],
      "args": []
    },
    {
      "name": "setOwnersAndChangeThreshold",
      "accounts": [
        {
          "name": "multisig",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "multisigSigner",
          "isMut": false,
          "isSigner": true
        }
      ],
      "args": [
        {
          "name": "owners",
          "type": {
            "vec": "publicKey"
          }
        },
        {
          "name": "threshold",
          "type": "u64"
        }
      ]
    },
    {
      "name": "setOwners",
      "accounts": [
        {
          "name": "multisig",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "multisigSigner",
          "isMut": false,
          "isSigner": true
        }
      ],
      "args": [
        {
          "name": "owners",
          "type": {
            "vec": "publicKey"
          }
        }
      ]
    },
    {
      "name": "changeThreshold",
      "accounts": [
        {
          "name": "multisig",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "multisigSigner",
          "isMut": false,
          "isSigner": true
        }
      ],
      "args": [
        {
          "name": "threshold",
          "type": "u64"
        }
      ]
    },
    {
      "name": "executeTransaction",
      "accounts": [
        {
          "name": "multisig",
          "isMut": false,
          "isSigner": false
        },
        {
          "name": "multisigSigner",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "transaction",
          "isMut": true,
          "isSigner": false
        },
        {
          "name": "owner",
          "isMut": false,
          "isSigner": true
        }
      ],
      "args": []
    }
  ],
  "accounts": [
    {
      "name": "Transaction",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "multisig",
            "type": "publicKey"
          },
          {
            "name": "programId",
            "type": "publicKey"
          },
          {
            "name": "accounts",
            "type": {
              "vec": {
                "defined": "TransactionAccount"
              }
            }
          },
          {
            "name": "data",
            "type": "bytes"
          },
          {
            "name": "signers",
            "type": {
              "vec": "bool"
            }
          },
          {
            "name": "didExecute",
            "type": "bool"
          },
          {
            "name": "ownerSetSeqno",
            "type": "u32"
          }
        ]
      }
    },
    {
      "name": "Multisig",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "owners",
            "type": {
              "vec": "publicKey"
            }
          },
          {
            "name": "threshold",
            "type": "u64"
          },
          {
            "name": "nonce",
            "type": "u8"
          },
          {
            "name": "ownerSetSeqno",
            "type": "u32"
          }
        ]
      }
    }
  ],
  "types": [
    {
      "name": "TransactionAccount",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "pubkey",
            "type": "publicKey"
          },
          {
            "name": "isSigner",
            "type": "bool"
          },
          {
            "name": "isWritable",
            "type": "bool"
          }
        ]
      }
    }
  ],
  "errors": [
    {
      "code": 300,
      "name": "InvalidOwner",
      "msg": "The given owner is not part of this multisig."
    },
    {
      "code": 301,
      "name": "InvalidOwnersLen",
      "msg": "Owners length must be non zero."
    },
    {
      "code": 302,
      "name": "NotEnoughSigners",
      "msg": "Not enough owners signed this transaction."
    },
    {
      "code": 303,
      "name": "TransactionAlreadySigned",
      "msg": "Cannot delete a transaction that has been signed by an owner."
    },
    {
      "code": 304,
      "name": "Overflow",
      "msg": "Overflow when adding."
    },
    {
      "code": 305,
      "name": "UnableToDelete",
      "msg": "Cannot delete a transaction the owner did not create."
    },
    {
      "code": 306,
      "name": "AlreadyExecuted",
      "msg": "The given transaction has already been executed."
    },
    {
      "code": 307,
      "name": "InvalidThreshold",
      "msg": "Threshold must be less than or equal to the number of owners."
    },
    {
      "code": 308,
      "name": "UniqueOwners",
      "msg": "Owners must be unique"
    }
  ]
}
```

</details>


# IDL Methods


# Program Client

You can generate a program client from the on-chain Cashmere IDL with the following code:

```javascript
const multisigProgram = await Program.at(multisigProgramId, provider);
```


# Create Transaction

Example code to programmatically create a transaction (proposed instruction) for an existing Cashmere multisig

```javascript
// find the PDA of the multisig (multisigSigner)
const [multisigSigner, nonce] =
  await anchor.web3.PublicKey.findProgramAddress(
    [multisig.publicKey.toBuffer()],
    multisigProgram.programId
  );

// instruction being proposed to the multisig for approval
// this instruction transfers SOL
const proposedIx = web3.SystemProgram.transfer({
      /** Account that will transfer lamports */
      fromPubkey: multisigSigner,
      /** Account that will receive transferred lamports */
      toPubkey: receiverAddress.publicKey,
      /** Amount of lamports to transfer */
      lamports: new anchor.BN(100),
    });

// accounts that will be operated on by the proposed instruction
const proposedIxAccounts = [
    {
      pubkey: multisigSigner,
      isWritable: false,
      isSigner: true,
    },
    {
      pubkey: receiverAddress.publicKey,
      isWritable: true,
      isSigner: false,
    },
  ];

// keypair for the account that will hold the
// proposed transaction instruction
const txAccountKeypair = anchor.web3.Keypair.generate();
const txAccountPublicKey = txAccountKeypair.publicKey;
const txSize = 1000; // arbitrarily big enough
    
await multisigProgram.rpc.createTransaction(
      proposedIx.programId,
      proposedIxAccounts,
      proposedIx.data,
      {
        accounts: {
          multisig: multisigPublicKey,
          transaction: txAccountPublicKey,
          proposer: provider.wallet.publicKey,
        },
        instructions: [
          // first create the account that will hold the
          // proposed transaction instruction and maintain
          // approved signers list
          await multisigProgram.account.transaction.createInstruction(
            txAccountKeypair,
            txSize
          ),
        ],
        signers: [txAccountKeypair],
      }
    );
```


# Approve Transaction

Example code to programmatically approve a transaction

```javascript
// approve a transaction with the current provider wallet
const approveTransactionIx = multisigProgram.rpc.approve({
    accounts: {
      multisig: multisigPublicKey,
      transaction: txAccountPublicKey,
      owner: provider.wallet.publicKey,
    },
    signers: [provider.wallet.publicKey]
  });
```


# Execute Transaction

Example code to programmatically approve a transaction

```javascript
// fetch the transaction account holding the 
// instruction to be executed
const txAccountRemainingAccounts = await multisigProgram.account.transaction.fetch(txAccountPublicKey);

// execute a signed transaction with the current provider wallet  
await program.rpc.executeTransaction({
    accounts: {
      multisig: multisigPublicKey,
      multisigSigner: multisigSigner,
      transaction: txAccountPublicKey,
      owner: provider.wallet.publicKey,
    },
    // the accounts that are needed by the instruction
    // to be executed
    // need to be in the correct order
    remainingAccounts: txAccount.accounts,
    signers: [provider.wallet.publicKey]
  });
```


