> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phantom.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sign-In-With (SIW) standards

> Authenticate users with Sign-In-With standards including SIWS, SIWE, and CAIP-122 supported by Phantom.

Applications that rely on `signMessage` for authenticating users can choose to opt-in to one of the various Sign-In with (SIW) standards. If a message follows one of the supported standards, Phantom will verify required fields at the time of signing.

At the time of this writing, Phantom supports:

* **Sign-In with Solana** ([specification](https://github.com/phantom/sign-in-with-solana))
* **Sign-In with Ethereum** ([EIP-4361](https://eips.ethereum.org/EIPS/eip-4361))
* **Sign-In with X** ([CAIP-122](https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-122.md))

The serialized format of SIW messages is as follows:

```
${domain} wants you to sign in with your ${blockchain} account:
${address}

${statement}

URI: ${uri}
Version: ${version}
Chain ID: ${chain-id}
Nonce: ${nonce}
Issued At: ${issued-at}
Expiration Time: ${expiration-time}
Not Before: ${not-before}
Request ID: ${request-id}
Resources:
- ${resources[0]}
- ${resources[1]}
...
- ${resources[n]}
```

| Name | Type | Required? | Description |
| - | - | - | - |
| `domain` | `string` | true | The authority that is requesting the signing. |
| `address` | `string` | true | The blockchain address that is performing the signing. |
| `statement` | `string` | false | A human-readable ASCII assertion that the user will sign. It MUST NOT contain `\\n`. |
| `uri` | `string` | true | A URI referring to the resource that is the subject of the signing—that is, the subject of the claim. |
| `version` | `string` | true | The current version of the message. |
| `chain-id` | `string` | true | The Chain ID to which the session is bound, and the network where Contract Accounts MUST be resolved. |
| `nonce` | `string` | true | A randomized token to prevent signature replay attacks. |
| `issued-at` | `string` | true | The issuance time. |
| `expiration-time` | `string` | false | The time at which the signed authentication message is no longer valid. |
| `not-before` | `string` | false | The time at which the signed authentication message starts being valid. |
| `request-id` | `string` | false | A system-specific identifier used to uniquely refer to the authentication request. |
| `resources` | `string[]` | false | A list of URIs the user wishes to have resolved as part of the authentication by the relying party. |

### Sign-In with Solana

See our [specification and integration guide](https://github.com/phantom/sign-in-with-solana) on GitHub.

<Warning>
  Phantom validates recognized Sign-In with Solana (SIWS) messages before displaying an approval prompt. Set the message `domain` to the requesting page's exact host, including the port when present. When you provide a `uri`, its origin must match the requesting page's origin. A mismatch returns error `-32000` (`Invalid Input`) without prompting the user.
</Warning>

### Sign-In with Ethereum

The Sign-In with Ethereum standard is defined by [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361).

#### Examples

signMessage()

```javascript theme={null}
const provider = getProvider(); // see "Detecting the Provider"
const message = `magiceden.io wants you to sign in with your Ethereum account:
0xb9c5714089478a327f09197987f16f9e5d936e8a

Click Sign or Approve only means you have proved this wallet is owned by you.

URI: https://magiceden.io
Version: 1
Chain ID: 1
Nonce: bZQJ0SL6gJ
Issued At: 2022-10-25T16:52:02.748Z
Resources:
- https://foo.com
- https://bar.com`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.signMessage(encodedMessage, "utf8");
```

request()

```javascript theme={null}
const provider = getProvider(); // see "Detecting the Provider"
const message = `magiceden.io wants you to sign in with your Ethereum account:
0xb9c5714089478a327f09197987f16f9e5d936e8a

Click Sign or Approve only means you have proved this wallet is owned by you.

URI: https://magiceden.io
Version: 1
Chain ID: 1
Nonce: bZQJ0SL6gJ
Issued At: 2022-10-25T16:52:02.748Z
Resources:
- https://foo.com
- https://bar.com`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.request({
    method: "signMessage",
    params: {
         message: encodedMessage,
         display: "utf8",
    }
});
```

### Sign-In with X

The Sign-In with X standard is defined by [CAIP-122](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-122.md). It uses [CAIP-10](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-10) identifiers for the `address` field and [CAIP-2](https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-2) for `chain-id`.

<Info>
  While CAIP-122 is technically chain-agnostic, only Ethereum and Solana parsing are supported at this time.
</Info>

#### Ethereum example

signMessage()

```javascript theme={null}
const provider = getProvider(); // see "Detecting the Provider"
const message = `magiceden.io wants you to sign in with your Ethereum account:
eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a

Click Sign or Approve only means you have proved this wallet is owned by you.

URI: https://magiceden.io
Version: 1
Chain ID: eip155:1
Nonce: bZQJ0SL6gJ
Issued At: 2022-10-25T16:52:02.748Z
Resources:
- https://foo.com
- https://bar.com`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.signMessage(encodedMessage, "utf8");
```

request()

```javascript theme={null}
const provider = getProvider(); // see "Detecting the Provider"
const message = `magiceden.io wants you to sign in with your Ethereum account:
eip155:1:0xb9c5714089478a327f09197987f16f9e5d936e8a

Click Sign or Approve only means you have proved this wallet is owned by you.

URI: https://magiceden.io
Version: 1
Chain ID: eip155:1
Nonce: bZQJ0SL6gJ
Issued At: 2022-10-25T16:52:02.748Z
Resources:
- https://foo.com
- https://bar.com`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.request({
    method: "signMessage",
    params: {
         message: encodedMessage,
         display: "utf8",
    }
});
```

#### Solana example

signMessage()

```javascript theme={null}
const provider = getProvider(); // see "Detecting the Provider"
const message = `magiceden.io wants you to sign in with your Solana account:
solana:mainnet:FYpB58cLw5cwiN763ayB2sFT8HLF2MRUBbbyRgHYiRpK

Click Sign or Approve only means you have proved this wallet is owned by you.

URI: https://magiceden.io
Version: 1
Chain ID: solana:mainnet
Nonce: bZQJ0SL6gJ
Issued At: 2022-10-25T16:52:02.748Z
Resources:
- https://foo.com
- https://bar.com`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.signMessage(encodedMessage, "utf8");
```

request()

```javascript theme={null}
const provider = getProvider(); // see "Detecting the Provider"
const message = `magiceden.io wants you to sign in with your Solana account:
solana:mainnet:FYpB58cLw5cwiN763ayB2sFT8HLF2MRUBbbyRgHYiRpK

Click Sign or Approve only means you have proved this wallet is owned by you.

URI: https://magiceden.io
Version: 1
Chain ID: solana:mainnet
Nonce: bZQJ0SL6gJ
Issued At: 2022-10-25T16:52:02.748Z
Resources:
- https://foo.com
- https://bar.com`;
const encodedMessage = new TextEncoder().encode(message);
const signedMessage = await provider.request({
    method: "signMessage",
    params: {
         message: encodedMessage,
         display: "utf8",
    }
});
```

<Info>
  Phantom uses Ed25519 signatures for Solana message signatures. To verify a message signature, you can use the [tweetnacl](https://www.npmjs.com/package/tweetnacl) npm package.
</Info>
