# Your First Multisig

## Your First Multisig <a href="#your-first-multisig" id="your-first-multisig"></a>

This tutorial introduces assorted K-of-N multi-signer authentication operations and supplements content from the following tutorials:

* Your First Transaction
* Your First Coin
* Your First Move Module

{% hint style="info" %}
Try out the above tutorials (which include dependency installations) before moving on to multisig operations.
{% endhint %}

## Step 1: Pick an SDK <a href="#step-1-pick-an-sdk" id="step-1-pick-an-sdk"></a>

Install your preferred SDK from the below list:

* TypeScript SDK

***

## Step 2: Run the example <a href="#step-2-run-the-example" id="step-2-run-the-example"></a>

Clone the endless-ts-sdk repo and build it:

```shell
git clone https://github.com/endless-labs/endless-ts-sdk.git
cd endless-ts-sdk
pnpm install
pnpm build
```

Navigate to the Typescript examples directory:

```shell
cd examples/endless
```

Install the necessary dependencies:

```shell
pnpm install
```

Run the [`binding`](https://github.com/endless-labs/endless-ts-sdk/blob/main/examples/typescript/binding.ts) example:

```shell
pnpm run bindings
```

## Step 3: Generate accounts and fund them

First, we will generate accounts for Alice, Bob, and Chad and fund them:

Fresh accounts are generated for each example run, but the output should resemble:

```shell
Fund alice: version 633280
Fund bob: version 633291

=== Account addresses ===
Alice: 0x91c381ec582ee96f96841a8f71b13a9feea83f52441e15a9e8b9d2bcf2ebbbc9
Bob:   0xd92dffdee6345ed5a0b3e3fe72b972dd90ba200bb478693dba4288998bc8343d
Chad:  0x820a4393e98c207b920a098c251c72435b5830b5b938bdb1aee77f83713d359c

=== Authentication keys ===
Alice: 0x91c381ec582ee96f96841a8f71b13a9feea83f52441e15a9e8b9d2bcf2ebbbc9
Bob:   0xd92dffdee6345ed5a0b3e3fe72b972dd90ba200bb478693dba4288998bc8343d
Chad:  0x820a4393e98c207b920a098c251c72435b5830b5b938bdb1aee77f83713d359c
```

For each user, at this moment, the account address and authentication key are identical.

## Step 4: Add Bob's authentication key into Alice's authentication key(list) <a href="#step-4-add-auth-key" id="step-4-add-auth-key"></a>

Next, Alice adds Bob's authentication key to her list of authentication keys. This involves submitting a transaction that invokes the \`add\_authentication\_key\` function within the account module of the system contract. Both Alice and Bob must sign this transaction.

```js
let txn = await endless.transaction.build.multiAgent({
    sender: alice.accountAddress,
    data: {
        function: "0x1::account::add_authentication_key",
        functionArguments: []
    },
    secondarySignerAddresses: [bob.accountAddress],
})

let aliceAuth = alice.signTransactionWithAuthenticator(txn)
let bobAuth = bob.signTransactionWithAuthenticator(txn)
pending = await endless.transaction.submit.multiAgent({
    transaction: txn,
    senderAuthenticator: aliceAuth,
    additionalSignersAuthenticators: [bobAuth],
})
tx_response = await endless.waitForTransaction({ transactionHash: pending.hash })

console.log(`\nAdd Bob's authkey into Alice authkey list: version ${tx_response.version}`)
```

## Step 5: Alice's authentication key (contains Bob's authentication key)

After add authentication key transaction, bob's authentication key is added into Alice's authentication

```shell
Alice authentication_key:
0x91c381ec582ee96f96841a8f71b13a9feea83f52441e15a9e8b9d2bcf2ebbbc9,
0xd92dffdee6345ed5a0b3e3fe72b972dd90ba200bb478693dba4288998bc8343d

Bob controlled accounts:
0x91c381ec582ee96f96841a8f71b13a9feea83f52441e15a9e8b9d2bcf2ebbbc9
```

## Step 6: Send coins from Alice to Chad, signed by Bob

We now build an EDS transfer transaction, sender is Alice's account, receiver is Chad, transaction is signed by Bob.

```js
let transferEDSRawTransaction = await endless.transaction.build.simple({
    sender: alice.accountAddress,
    data: {
        function: "0x1::endless_account::transfer",
        functionArguments: [chad.accountAddress, 1000]
    },
})

let multiAuthKeyAccount = new MultiAuthKeyAccount({ sender: alice.accountAddress, signers: [bob] })

pending = await endless.signAndSubmitTransaction({
    transaction: transferEDSRawTransaction,
    signer: multiAuthKeyAccount,
})
tx_response = await endless.waitForTransaction({ transactionHash: pending.hash })

console.log(`\ntransfer EDS from Alice to Chad with Bob auth: version ${tx_response.version}`)
```

## Step 7: remove Bob's authentication key from Alice's authentication key list

We invoke `0x1::account::remove_authentication_key` to remove Bob's authenticaion key, restore Alice's authentication key as default. This transaction also must be signed by both Alice and Bob.

```js
txn = await endless.transaction.build.simple({
    sender: alice.accountAddress,
    data: {
        function: "0x1::account::remove_authentication_key",
        functionArguments: [bob.accountAddress.data]
    },
})

aliceAuth = alice.signTransactionWithAuthenticator(txn)
pending = await endless.transaction.submit.simple({
    transaction: txn,
    senderAuthenticator: aliceAuth,
})
tx_response = await endless.waitForTransaction({ transactionHash: pending.hash })

console.log(`\nRemove Bob from Alice's auth key : version ${tx_response.version}`)
```

## Step 8: Check if Alice's authentication key is restored to default

```shell
Alice authentication_key:
0x91c381ec582ee96f96841a8f71b13a9feea83f52441e15a9e8b9d2bcf2ebbbc9

Bob controlled accounts:
None
```

## Step 9: Batch add Bob\&Chad authkey into Alice's authentication key list, but set `Threashold` to 2

By adding Bob and Chad auth key to Alice's auth key list, either Bob or Chad can sign transaction on Alice behalf. A required signature count of 2 (Threshold = 2) is enforced for transactions originating from Alice. Verification will fail if fewer than two signatures are present (e.g., only Alice's signature, or only one of Bob's or Chad's)

```js
txn = await endless.transaction.build.multiAgent({
    sender: alice.accountAddress,
    data: {
        function: "0x1::account::batch_add_authentication_key",
        functionArguments: [2]
    },
    secondarySignerAddresses: [bob.accountAddress, chad.accountAddress],
})

aliceAuth = alice.signTransactionWithAuthenticator(txn)
bobAuth = bob.signTransactionWithAuthenticator(txn)
let chadAuth = chad.signTransactionWithAuthenticator(txn)
pending = await endless.transaction.submit.multiAgent({
    transaction: txn,
    senderAuthenticator: aliceAuth,
    additionalSignersAuthenticators: [bobAuth, chadAuth],
})
tx_response = await endless.waitForTransaction({ transactionHash: pending.hash })

console.log(`\nBatch Add auth key, set "AuthThreadhold" to 2: version ${tx_response.version}`)
```

## Step 10: transfer transaction, signed only by Bob, will fail

```js
transferEDSRawTransaction = await endless.transaction.build.simple({
    sender: alice.accountAddress,
    data: {
        function: "0x1::endless_account::transfer",
        functionArguments: [chad.accountAddress, 1000]
    },
})
multiAuthKeyAccount = new MultiAuthKeyAccount({ sender: alice.accountAddress, signers: [bob] })

try {
    pending = await endless.signAndSubmitTransaction({
    transaction: transferEDSRawTransaction,
    signer: multiAuthKeyAccount,
    })
    await endless.waitForTransaction({ transactionHash: pending.hash });
} catch (error) {
    console.log("\nFailed to transfer EDS from Alice to Chad with only by Bob auth, cause `Auth Threshold` is 2")
}
```

## Step 11: transfer transaction, signed by both Bob and Chad, will success

```js
multiAuthKeyAccount = new MultiAuthKeyAccount({ sender: alice.accountAddress, signers: [bob, alice] })
pending = await endless.signAndSubmitTransaction({
    transaction: transferEDSRawTransaction,
    signer: multiAuthKeyAccount,
})
tx_response = await endless.waitForTransaction({ transactionHash: pending.hash })
console.log(`\ntransfer EDS from Alice to Chad with Alice and Bob auth, version ${tx_response.version}`)
```

The above examples showcase the Endless multi-signature feature, demonstrating how to manage Authentication Keys and generate transaction signatures. This multi-signature implementation, combined with Keyless functionality, offers an emergency escape route.

For example, if a Keyless account (A) is locked due to Web2 service issues, and its authentication key list includes another wallet (AA), then AA can rescue the funds by initiating a transaction on A's behalf, avoiding assets locked.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.endless.link/endless/devbuild/build/tutorials/your-first-multisig.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
