Browse Source

Merge pull request #1 from bfriel/brian/typos

Brian/typos
Brian Friel 2 years ago
parent
commit
e1d9a27aa8
5 changed files with 332 additions and 140 deletions
  1. 85 0
      .github/CODE_OF_CONDUCT.md
  2. 64 0
      .github/ISSUE_TEMPLATE/bug_report.yml
  3. 8 0
      .github/ISSUE_TEMPLATE/config.yml
  4. 1 0
      .github/SECURITY.md
  5. 174 140
      README.md

+ 85 - 0
.github/CODE_OF_CONDUCT.md

@@ -0,0 +1,85 @@
+Contributor Covenant Code of Conduct
+====================================
+
+Our Pledge
+----------
+
+We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
+
+Our Standards
+-------------
+
+Examples of behavior that contributes to a positive environment for our community include:
+
+-   Demonstrating empathy and kindness toward other people
+-   Being respectful of differing opinions, viewpoints, and experiences
+-   Giving and gracefully accepting constructive feedback
+-   Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
+-   Focusing on what is best not just for us as individuals, but for the overall community
+
+Examples of unacceptable behavior include:
+
+-   The use of sexualized language or imagery, and sexual attention or advances of any kind
+-   Trolling, insulting or derogatory comments, and personal or political attacks
+-   Public or private harassment
+-   Publishing others' private information, such as a physical or email address, without their explicit permission
+-   Other conduct which could reasonably be considered inappropriate in a professional setting
+
+Enforcement Responsibilities
+----------------------------
+
+Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
+
+Scope
+-----
+
+This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
+
+Enforcement
+-----------
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting oss@phantom.app. All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the reporter of any incident.
+
+Enforcement Guidelines
+----------------------
+
+Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1\. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
+
+### 2\. Warning
+
+**Community Impact**: A violation through a single incident or series of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
+
+### 3\. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
+
+### 4\. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the community.
+
+Attribution
+-----------
+
+This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.0, available at <https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
+
+For answers to common questions about this code of conduct, see the FAQ at <https://www.contributor-covenant.org/faq>. Translations are available at <https://www.contributor-covenant.org/translations>.

+ 64 - 0
.github/ISSUE_TEMPLATE/bug_report.yml

@@ -0,0 +1,64 @@
+name: Bug Report
+description: File a bug/issue
+title: 'bug: <title>'
+body:
+  - type: markdown
+    attributes:
+      value: |
+        Thanks for taking the time to fill out this bug report! The more info you provide, the more we can help you.
+
+  - type: checkboxes
+    attributes:
+      label: Is there an existing issue for this?
+      description: Please search to see if an issue already exists for the bug you encountered.
+      options:
+        - label: I have searched the existing issues
+          required: true
+
+  - type: input
+    attributes:
+      label: Package Version
+      description: What version of sign in with are you using?
+      placeholder: 1.0.0
+    validations:
+      required: true
+
+  - type: textarea
+    attributes:
+      label: Current Behavior
+      description: A concise description of what you're experiencing.
+    validations:
+      required: false
+
+  - type: textarea
+    attributes:
+      label: Expected Behavior
+      description: A concise description of what you expected to happen.
+    validations:
+      required: false
+
+  - type: textarea
+    attributes:
+      label: Steps To Reproduce
+      description: Steps or code snippets to reproduce the behavior.
+    validations:
+      required: false
+
+  - type: input
+    attributes:
+      label: Link to Minimal Reproducible Example (StackBlitz, CodeSandbox, GitHub repo etc.)
+      description: |
+        Please provide a link to a minimal repository that can reproduce the problem you ran into.
+        This makes investigating issues and helping you out significantly easier! For most issues, you will likely get asked to provide one so why not add one now :)
+    validations:
+      required: false
+
+  - type: textarea
+    attributes:
+      label: Anything else?
+      description: |
+        Browser info? Screenshots? Anything that will give us more context about the issue you are encountering!
+
+        Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
+    validations:
+      required: false

+ 8 - 0
.github/ISSUE_TEMPLATE/config.yml

@@ -0,0 +1,8 @@
+blank_issues_enabled: false
+contact_links:
+  - name: Start a Discussion
+    url: https://github.com/orgs/phantom/discussions/categories/general
+    about: Ask questions and discuss with other community members
+  - name: Get Developer Support
+    url: https://github.com/orgs/phantom/discussions/categories/help-support
+    about: Get developer support from the Phantom dev community

+ 1 - 0
.github/SECURITY.md

@@ -0,0 +1 @@
+You can find our bug bounty policy [here](https://phantom.app/bug-bounty).

+ 174 - 140
README.md

@@ -1,35 +1,36 @@
-# Sign-In With Solana
-
-* [Introduction](#introduction)
-* [Motivation](#motivation)
-* [Specification](#specification)
-  * [Sign-In Input Fields](#sign-in-input-fields)
-  * [Sign-In Output Fields](#sign-in-output-fields)
-  * [ABNF Message Format](#abnf-message-format)
-  * [Minimal Message Template](#minimal-message-template)
-  * [Maximal Message Template](#maximal-message-template)
-* [Dapp Integration](#dapp-integration)
-  * [Overview](#overview)
-  * [Dependencies](#dependencies)
-  * [Sign-In Input Generation](#sign-in-input-generation-backend)
-  * [Sign-In Output Verification](#sign-in-output-verification-backend)
-  * [Context Provider](#context-provider-frontend)
-  * [Wallet Provider](#wallet-provider-frontend)
-* [Wallet Integration](#wallet-integration-guide)
-  * [Overview](#overview-1)
-  * [Dependencies](#dependencies-1)
-  * [Wallet-Standard Wrapper and Provider Method](#wallet-standard-wrapper-and-provider-method)
-  * [Message Construction](#message-construction)
-  * [Message Parsing](#message-parsing)
-  * [Message Verification](#message-verification)
-* [Full Feature Demo](#full-feature-demo)
-* [Reference Implementation](#reference-implementation) 
+# Sign In With Solana
+
+- [Introduction](#introduction)
+- [Motivation](#motivation)
+- [Specification](#specification)
+  - [Sign-In Input Fields](#sign-in-input-fields)
+  - [Sign-In Output Fields](#sign-in-output-fields)
+  - [ABNF Message Format](#abnf-message-format)
+  - [Minimal Message Template](#minimal-message-template)
+  - [Maximal Message Template](#maximal-message-template)
+- [Dapp Integration](#dapp-integration)
+  - [Overview](#overview)
+  - [Dependencies](#dependencies)
+  - [Sign-In Input Generation](#sign-in-input-generation-backend)
+  - [Sign-In Output Verification](#sign-in-output-verification-backend)
+  - [Context Provider](#context-provider-frontend)
+  - [Wallet Provider](#wallet-provider-frontend)
+- [Wallet Integration](#wallet-integration-guide)
+  - [Overview](#overview-1)
+  - [Dependencies](#dependencies-1)
+  - [Wallet-Standard Wrapper and Provider Method](#wallet-standard-wrapper-and-provider-method)
+  - [Message Construction](#message-construction)
+  - [Message Parsing](#message-parsing)
+  - [Message Verification](#message-verification)
+- [Full Feature Demo](#full-feature-demo)
+- [Reference Implementation](#reference-implementation)
 
 ## Introduction
 
-Sign In With Solana (SIWS) is a new feature that lets applications authenticate their users and prove ownership of their addresses. The feature aims at standardizing message formats to improve the authentication UX and security, and replaces the traditionally clunky `connect` + `signMessage` flow with a one-click `signIn` method.
+Sign In With Solana (SIWS) is a new feature that lets applications authenticate their users and prove ownership of their addresses. SIWS aims to standardize message formats in order to improve authentication UX and security, replacing the traditionally clunky `connect` + `signMessage` flow with a one-click `signIn` method.
 
 ## Motivation
+
 Centralised entities like Google, Facebook and X dictate our digital identities. They define our digital identifiers (usernames, email addresses) and exercise control over our data, reputations, and digital footprints. This presents two significant concerns:
 
 1.  Censorship: They possess the power to ban, block, or limit specific users at their discretion
@@ -37,19 +38,20 @@ Centralised entities like Google, Facebook and X dictate our digital identities.
 
 A decentralised authentication approach widely used to tackle the above revolves around signing off-chain messages. This approach is safer than entering passwords and entrusting authentication control to the dapp, however, it faces some significant challenges:
 
-1.  The user experience is inconsistent, as every dapp has its unique message format, leaving users unsure of what to expect
+1. The user experience is inconsistent, as every dapp has its unique message format, leaving users unsure of what to expect
 2. The lack of standardization in message formats forces wallets to display confusing messages in plaintext, further baffling users
-3. Malicious websites pretending as legitimate dapps can trick users into signing messages, and neither the wallet nor the user can intervene
+3. Malicious websites pretending to be legitimate dapps can trick users into signing messages, and neither the wallet nor the user can intervene
 4. The traditional `connect` + `signMessage` requires multiple unintuitive steps
 
-Sign-In With Solana offers a comprehensive solution to these challenges and more. The [technical specification](https://github.com/solana-labs/wallet-standard/blob/alpha/packages/core/features/src/signIn.ts) for SIWS is modeled after [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) (Sign In With Ethereum) but extends beyond its capabilities. SIWS shifts the responsibility of message construction from dapps to the wallet, resulting in consistent, user-friendly interfaces and enhanced end-user security.
+Sign In With Solana offers a comprehensive solution to these challenges and more. The [technical specification](https://github.com/solana-labs/wallet-standard/blob/alpha/packages/core/features/src/signIn.ts) for SIWS is modeled after [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) (Sign In With Ethereum) but extends beyond its capabilities. SIWS shifts the responsibility of message construction from dapps to the wallet, resulting in consistent, user-friendly interfaces and enhanced end-user security.
 
 Additionally, SIWS standardises the message format, which enables wallets to scrutinize message data to ensure its legitimacy or raise red flags for suspicious activity. Domain binding is a key feature of SIWS, enabling wallets to alert users if a website is impersonating another entity
 
-
 ## Specification
+
 ### Sign-In Input Fields
-To make a sign-in request, dapps do not need to construct a message themselves, unlike EIP-4361 or legacy Solana messages. Rather, dapps construct the `signInInput` object containing a set of standard message parameters. All these fields are optional strings. Dapps can optionally send a minimal (empty) `signInInput` object to the wallet.
+
+Unlike EIP-4361 or legacy Solana messages, dapps do not need to construct a message themselves in order to make a sign-in request. Rather, dapps construct the `signInInput` object containing a set of standard message parameters. All these fields are optional strings. Dapps can optionally send a minimal (empty) `signInInput` object to the wallet.
 
 - `domain`: Optional EIP-4361 domain requesting the sign-in. If not provided, the wallet must determine the domain to include in the message.
 - `address`: Optional Solana address performing the sign-in. The address is case-sensitive. If not provided, the wallet must determine the Address to include in the message.
@@ -63,8 +65,9 @@ To make a sign-in request, dapps do not need to construct a message themselves,
 - `notBefore`: Optional ISO 8601 datetime string. This represents the time at which the sign-in request becomes valid. If not provided, the wallet must not include Not Before in the message.
 - `requestId`: Optional EIP-4361 Request ID. In addition to using `nonce` to avoid replay attacks, dapps can also choose to include a unique signature in the `requestId` . Once the wallet returns the signed message, dapps can then verify this signature against the state to add an additional, strong layer of security. If not provided, the wallet must not include Request ID in the message.
 - `resources`: Optional EIP-4361 Resources. Usually a list of references in the form of URIs that the dapp wants the user to be aware of. These URIs should be separated by `\n-`, ie, URIs in new lines starting with the character `-`. If not provided, the wallet must not include Resources in the message.
-    
+
 ### Sign-In Output Fields
+
 Once the user is successfully signed-in, the wallet returns back the `signInOutput` object to the dapp, which can be used for verifying the sign-in process.
 
 - `account` [`WalletAccount`]: Account that was signed in. The address of the account may be different from the provided input Address.
@@ -73,7 +76,8 @@ Once the user is successfully signed-in, the wallet returns back the `signInOutp
 - `signatureType` [`"ed25519"`]: Optional type of the message signature produced. If not provided, the signature must be Ed25519.
 
 ### ABNF Message Format
-The Sign-In With Solana message constructed by the wallet using `signInInput` should follow the `sign-in-with-solana` Augment Backus–Naur Form expression:
+
+The Sign In With Solana message constructed by the wallet using `signInInput` should follow the `sign-in-with-solana` Augment Backus–Naur Form expression:
 
 ```
 sign-in-with-solana =
@@ -108,14 +112,18 @@ message-resources       = *( LF "- " URI )
 ```
 
 ### Minimal Message Template
+
 If the dapp sends an empty `signInInput`, the wallet should construct a minimal sign-in message using the requesting domain and address as follows:
+
 ```
 ${domain} wants you to sign in with your Solana account:
 ${address}
 ```
 
 ### Maximal Message Template
+
 This is an informal format in which the wallet should construct the message if all optional fields are provided in `signInInput`:
+
 ```
 ${domain} wants you to sign in with your Solana account:
 ${address}
@@ -138,18 +146,22 @@ Resources:
 ```
 
 ## Dapp Integration
-SIWS comes with first-class support in both the Solana Wallet Standard and Solana Wallet Adapter libraries. If your dapp makes use of the Solana Wallet Adapter, migration is easy.
+
+SIWS comes with first-class support in both the [Solana Wallet Standard](https://github.com/solana-labs/wallet-standard) and [Solana Wallet Adapter](https://github.com/solana-labs/wallet-adapter) libraries. If your dapp makes use of the Solana Wallet Adapter, migration is easy.
+
 ### Overview
+
 1. User chooses one of the standard wallets (Wallet Standard compatible wallets)
-2. Dapp checks if the given wallet has the signIn feature enabled
-3. If not, Dapp continues with the legacy authentication mechanism using connect + signMessage
-4. Else, Dapp constructs the signInInput which is an object containing a set of standard message parameters as defined in the spec.
-5. The Dapp sends this object to the Wallet and requests signIn
+2. Dapp checks if the given wallet has the `signIn` feature enabled
+3. If not, Dapp continues with the legacy authentication mechanism using `connect` + `signMessage`
+4. Else, Dapp constructs the `signInInput` which is an object containing a set of standard message parameters as defined in the spec.
+5. The Dapp sends this object to the Wallet and requests `signIn`
 6. The Dapp receives the constructed message, the message signature and the public address of the connected account from the Wallet
-7. The Dapp verifies the returned message and the signature against the signInInput provided to the Wallet. This verification happens server-side
+7. The Dapp verifies the returned message and the signature against the `signInInput` provided to the Wallet. This verification happens server-side
 8. On successful verification, the authentication process is completed and the user is connected and authenticated to the Dapp
 
 ### Dependencies
+
 The first step is to update the necessary dependencies. Add/update these in your `package.json`:
 
 ```json
@@ -160,6 +172,7 @@ The first step is to update the necessary dependencies. Add/update these in your
 ```
 
 ### Sign-In Input Generation (Backend)
+
 The Sign-In input object should be generated server-side. In most cases, the object can be empty and thus the input generation step can be skipped. Create the following endpoint on your backend server:
 
 ```tsx
@@ -167,19 +180,20 @@ import { SolanaSignInInput } from "@solana/wallet-standard-features";
 
 export const createSignInData = async (): Promise<SolanaSignInInput> => {
   const now: Date = new Date();
-  const uri = window.location.href
+  const uri = window.location.href;
   const currentUrl = new URL(uri);
   const domain = currentUrl.host;
 
   // Convert the Date object to a string
   const currentDateTime = now.toISOString();
-  
+
   // signInData can be kept empty in most cases: all fields are optional
   // const signInData: SolanaSignInInput = {};
 
   const signInData: SolanaSignInInput = {
     domain,
-    statement: "Clicking Sign or Approve only means you have proved this wallet is owned by you. This request will not trigger any blockchain transaction or cost any gas fee.",
+    statement:
+      "Clicking Sign or Approve only means you have proved this wallet is owned by you. This request will not trigger any blockchain transaction or cost any gas fee.",
     version: "1",
     nonce: "oBbLoEldZs",
     chainId: "mainnet",
@@ -192,81 +206,87 @@ export const createSignInData = async (): Promise<SolanaSignInInput> => {
 ```
 
 ### Sign-In Output Verification (Backend)
+
 Legacy message verification on Solana is tedious and dapps have to verify using the `tweetnacl` library as follows:
 
 ```tsx
-const verified = nacl
-  .sign
-  .detached
-  .verify(
-    new TextEncoder().encode(message),
-    bs58.decode(signature),
-    bs58.decode(public_key)
-  )
+const verified = nacl.sign.detached.verify(
+  new TextEncoder().encode(message),
+  bs58.decode(signature),
+  bs58.decode(public_key)
+);
 ```
 
-Sign-In With Solana brings about a developer experience improvement with a helper method implementation for message and signature verification: [`verifySignIn`](https://github.com/solana-labs/wallet-standard/blob/master/packages/core/util/src/signIn.ts#L8) method of the `@solana/wallet-standard-util` package. Under-the-hood, the `verifySignIn` method:
-1. parses and deconstructs the `signedMessage` field of the `output` (ie, the constructed message returned by the wallet)
-2. checks the extracted fields against the fields in the `input`
-3. re-constructs the message according to the ABNF Message Format
-4. verifies the message signature
+Sign In With Solana improves the developer experience by providing a helper method implementation for message and signature verification: [`verifySignIn`](https://github.com/solana-labs/wallet-standard/blob/master/packages/core/util/src/signIn.ts#L8). This method is available in the `@solana/wallet-standard-util` package. Under-the-hood, the `verifySignIn` method:
+
+1. Parses and deconstructs the `signedMessage` field of the `output` (ie, the constructed message returned by the wallet)
+2. Checks the extracted fields against the fields in the `input`
+3. Re-constructs the message according to the ABNF Message Format
+4. Verifies the message signature
 
 With all the complexity abstracted away, make a simple backend endpoint calling the `verifySignIn` method as follows:
 
 ```tsx
-import type { SolanaSignInInput, SolanaSignInOutput } from '@solana/wallet-standard-features';
-import { verifySignIn } from '@solana/wallet-standard-util';
-
-
-export function verifySIWS(input: SolanaSignInInput, output: SolanaSignInOutput): boolean {
+import type {
+  SolanaSignInInput,
+  SolanaSignInOutput,
+} from "@solana/wallet-standard-features";
+import { verifySignIn } from "@solana/wallet-standard-util";
+
+export function verifySIWS(
+  input: SolanaSignInInput,
+  output: SolanaSignInOutput
+): boolean {
   return verifySignIn(input, output);
 }
 ```
 
 ### Context Provider (Frontend)
+
 Add the following `autoSignIn` callback method to your `ContextProvider`:
-    
+
 ```tsx
-import { type SolanaSignInInput } from '@solana/wallet-standard-features';
-import { verifySignIn } from '@solana/wallet-standard-util';
+import { type SolanaSignInInput } from "@solana/wallet-standard-features";
+import { verifySignIn } from "@solana/wallet-standard-util";
 
 const autoSignIn = useCallback(async (adapter: Adapter) => {
-      // If the signIn feature is not available, return true
-      if (!('signIn' in adapter)) return true;
+  // If the signIn feature is not available, return true
+  if (!("signIn" in adapter)) return true;
+
+  // Fetch the signInInput from the backend
+  const createResponse = await fetch("/backend/createSignInData");
 
-      // Fetch the signInInput from the backend
-      const createResponse = await fetch("/backend/createSignInData");
+  const input: SolanaSignInInput = await createResponse.json();
 
-      const input: SolanaSignInInput = await createResponse.json();
+  // Send the signInInput to the wallet and trigger a sign-in request
+  const output = await adapter.signIn(input);
 
-      // Send the signInInput to the wallet and trigger a sign-in request
-      const output = await adapter.signIn(input);
-      
-      // Verify the sign-in output against the generated input server-side
-      const verifyResponse = await fetch('/backend/verifySIWS', {
-        method: 'POST',
-        body: JSON.stringify({input, output}),
-      });
-      const success = await verifyResponse.json();
+  // Verify the sign-in output against the generated input server-side
+  const verifyResponse = await fetch("/backend/verifySIWS", {
+    method: "POST",
+    body: JSON.stringify({ input, output }),
+  });
+  const success = await verifyResponse.json();
 
-      // If verification fails, throw an error
-      if (!success) throw new Error('Sign In verification failed!');
+  // If verification fails, throw an error
+  if (!success) throw new Error("Sign In verification failed!");
 
-      return false;
+  return false;
 }, []);
 ```
 
 This callback function determines whether a user should be auto-connected (returns `true`) or prompted to sign-in (returns `false`).
 
 - Check if the user’s wallet supports the `signIn` feature.
-    - If `signIn` is not available, this callback returns `true`
+  - If `signIn` is not available, this callback returns `true`
 - If `signIn` is available:
-    - Create the `SolanaSignInInput` object server-side
-    - The input is passed into the `signIn` method and the sign-in request is triggered
-    - The output is verified using the `verifySignIn` [method](https://github.com/solana-labs/wallet-standard/blob/master/packages/core/util/src/signIn.ts#L8) server-side
-    - If all of the above, the callback returns `false` and the user is prompted to sign-in
+  - Create the `SolanaSignInInput` object server-side
+  - The input is passed into the `signIn` method and the sign-in request is triggered
+  - The output is verified using the `verifySignIn` [method](https://github.com/solana-labs/wallet-standard/blob/master/packages/core/util/src/signIn.ts#L8) server-side
+  - If all of the above, the callback returns `false` and the user is prompted to sign-in
 
 ### Wallet Provider (Frontend)
+
 Pass `autoSignIn` callback to the `autoConnect` attribute of `WalletProvider`:
 
 ```tsx
@@ -280,100 +300,110 @@ Pass `autoSignIn` callback to the `autoConnect` attribute of `WalletProvider`:
 When the connecting wallet does not support the `signIn` feature, `autoSignIn` returns `true` and thus the wallet goes on to `autoConnect` to the dapp, rather than `signIn`.
 
 ## Wallet Integration
+
 ### Overview
-1. The Wallet receieves the signIn request from the dapp
+
+1. The Wallet receieves the `signIn` request from the dapp
 2. The Wallet constructs a message in the ABNF format using the message parameter strings
 3. The constructed message is parsed to check if the construction follows the standard ABNF format and is consistent with the spec
-4. If parsing fails, the user is not shown the signIn prompt and the wallet throws an RPC error
+4. If parsing fails, the user is not shown the `signIn` prompt and the wallet throws an RPC error
 5. Else, the parsed parameters are verified to follow the correct format and predefined thresholds
-6. If verification is successful, the Wallet prompts the user with the signIn request, showing the message statement and the advanced details hidden by default. No errors are shown
+6. If verification is successful, the Wallet prompts the user with the `signIn` request, showing the message statement and the advanced details hidden by default. No errors are shown
 7. If verification fails, the user is still prompted, but is shown the verification errors
 8. In both cases, the user is able to either accept the signIn request or decline the request
 9. In case the user accepts the request, the wallet connects the user to the Dapp and signs the constructed message
 10. The Wallet returns the constructed message, the message signature and the public address of the connected account back to the Dapp
 
 ### Dependencies
+
 Wallets will need to upgrade the following packages:
+
 ```json
 "@solana/wallet-standard-features": "1.1.0",
 "@solana/wallet-standard-util": "1.1.0",
 ```
 
 ### Wallet-Standard Wrapper and Provider Method
+
 First step will be to implement a provider method and a wrapper for the `signIn` provider method to make the feature Wallet-Standard compatible. Here's a [sample implementation](https://github.com/solana-labs/wallet-standard/blob/9d17ab038fb4c39fa08378571de40ea5ad593d46/packages/wallets/ghost/src/wallet.ts#L288) for the Wallet-Standard wrapper:
 
 ```tsx
-import type { SolanaSignInInput, SolanaSignInOutput } from '@solana/wallet-standard-features';
+import type {
+  SolanaSignInInput,
+  SolanaSignInOutput,
+} from "@solana/wallet-standard-features";
 
 export class PhantomWallet implements Wallet {
   #signIn: SolanaSignInMethod = async (...inputs) => {
-      const outputs: SolanaSignInOutput[] = [];
-      if (inputs.length > 1) {
-          for (const input of inputs) {
-              outputs.push(await this.#phantom.signIn(input));
-          }
-      } else {
-          return [await this.#phantom.signIn(inputs[0])];
+    const outputs: SolanaSignInOutput[] = [];
+    if (inputs.length > 1) {
+      for (const input of inputs) {
+        outputs.push(await this.#phantom.signIn(input));
       }
-      return outputs;
+    } else {
+      return [await this.#phantom.signIn(inputs[0])];
+    }
+    return outputs;
   };
 }
 ```
 
 ### Message Construction
-Once we have the provider method and the Wallet-Standard wrapper, we can start with the message construction. The message should be constructed following the [ABNF Message format](#abnf-message-format). The construction follows the same algorithm implemented in the [`createSignInMessageText` method](https://github.com/solana-labs/wallet-standard/blob/9d17ab038fb4c39fa08378571de40ea5ad593d46/packages/core/util/src/signIn.ts#L121) of the `@solana/wallet-standard-utils` package. 
+
+Once we have the provider method and the Wallet-Standard wrapper, we can start with the message construction. The message should be constructed following the [ABNF Message format](#abnf-message-format). The construction follows the same algorithm implemented in the [`createSignInMessageText` method](https://github.com/solana-labs/wallet-standard/blob/9d17ab038fb4c39fa08378571de40ea5ad593d46/packages/core/util/src/signIn.ts#L121) of the `@solana/wallet-standard-utils` package.
 
 One thing to note is that although the `domain` and the `address` are not mandatory fields for the `signInInput`, they are mandatory for the constucted message. If these fields are not present in the input, they need to be extracted by the wallet using the requesting domain and address.
 
 ```tsx
 export function createSignInMessageText(input: SolanaSignInInput): string {
-    let message = `${input.domain} wants you to sign in with your Solana account:\n`;
-    message += `${input.address}`;
+  let message = `${input.domain} wants you to sign in with your Solana account:\n`;
+  message += `${input.address}`;
 
-    if (input.statement) {
-        message += `\n\n${input.statement}`;
-    }
+  if (input.statement) {
+    message += `\n\n${input.statement}`;
+  }
 
-    const fields: string[] = [];
-    if (input.uri) {
-        fields.push(`URI: ${input.uri}`);
-    }
-    if (input.version) {
-        fields.push(`Version: ${input.version}`);
-    }
-    if (input.chainId) {
-        fields.push(`Chain ID: ${input.chainId}`);
-    }
-    if (input.nonce) {
-        fields.push(`Nonce: ${input.nonce}`);
-    }
-    if (input.issuedAt) {
-        fields.push(`Issued At: ${input.issuedAt}`);
-    }
-    if (input.expirationTime) {
-        fields.push(`Expiration Time: ${input.expirationTime}`);
-    }
-    if (input.notBefore) {
-        fields.push(`Not Before: ${input.notBefore}`);
-    }
-    if (input.requestId) {
-        fields.push(`Request ID: ${input.requestId}`);
-    }
-    if (input.resources) {
-        fields.push(`Resources:`);
-        for (const resource of input.resources) {
-            fields.push(`- ${resource}`);
-        }
-    }
-    if (fields.length) {
-        message += `\n\n${fields.join('\n')}`;
+  const fields: string[] = [];
+  if (input.uri) {
+    fields.push(`URI: ${input.uri}`);
+  }
+  if (input.version) {
+    fields.push(`Version: ${input.version}`);
+  }
+  if (input.chainId) {
+    fields.push(`Chain ID: ${input.chainId}`);
+  }
+  if (input.nonce) {
+    fields.push(`Nonce: ${input.nonce}`);
+  }
+  if (input.issuedAt) {
+    fields.push(`Issued At: ${input.issuedAt}`);
+  }
+  if (input.expirationTime) {
+    fields.push(`Expiration Time: ${input.expirationTime}`);
+  }
+  if (input.notBefore) {
+    fields.push(`Not Before: ${input.notBefore}`);
+  }
+  if (input.requestId) {
+    fields.push(`Request ID: ${input.requestId}`);
+  }
+  if (input.resources) {
+    fields.push(`Resources:`);
+    for (const resource of input.resources) {
+      fields.push(`- ${resource}`);
     }
+  }
+  if (fields.length) {
+    message += `\n\n${fields.join("\n")}`;
+  }
 
-    return message;
+  return message;
 }
 ```
 
 ### Message Parsing
+
 Message parsing can be made easy and manageable using an ABNF Parser Generator like apg-js: [https://github.com/ldthomas/apg-js](https://github.com/ldthomas/apg-js).
 
 Wallets can create BNF grammar files and the `apg-js` packages recursively generates parsers for the constructed message.
@@ -381,11 +411,13 @@ Wallets can create BNF grammar files and the `apg-js` packages recursively gener
 The grammar for SIWS ABNF messages follows [this](#abnf-message-format) format.
 
 ### Message Verification
+
 Once successfully parsed, individual message fields should be verified against predefined thresholds and conditions. Here is a sample implementation of the verification method:
 
 ```tsx
 export function verify(data: SolanaSignInInput, opts: VerificationOptions) {
-  const { expectedAddress, expectedURL, expectedChainId, issuedAtThreshold } = opts;
+  const { expectedAddress, expectedURL, expectedChainId, issuedAtThreshold } =
+    opts;
   const errors: VerificationErrorType[] = [];
   const now = Date.now();
 
@@ -448,10 +480,12 @@ export function verify(data: SolanaSignInInput, opts: VerificationOptions) {
 ```
 
 ## Full Feature Demo
+
 [https://www.loom.com/share/228d2a4820fb44f69fb10c4fb5f2b55a](https://www.loom.com/share/228d2a4820fb44f69fb10c4fb5f2b55a)
 
 ## Reference Implementation
+
 You can find the source code for the example implementation [here](https://github.com/phantom/sign-in-with-solana/tree/main/example-dapp).
 
 You can play around with SIWS here: [https://siws.vercel.app/](https://siws.vercel.app/).
-Note: Currently SIWS is only supported on Phantom extension (version >=23.11.0)
+Note: Currently SIWS is only supported on Phantom extension (version >=23.11.0)