<|start_filename|>drivers/dids/.replrc.js<|end_filename|>
const { DIDs } = require('./dist');
const { ClusterType, SolanaUtil } = require('@identity.com/sol-did-client');
const { Keypair, Connection} = require('@solana/web3.js');

const clusterName = 'devnet';
const cluster = ClusterType.parse(clusterName);

const connection = new Connection(cluster.solanaUrl(), 'recent');
const payerAccountPromise = SolanaUtil.newAccountWithLamports(
  connection,
  1000000000
);

const didsPromise = payerAccountPromise
  .then(payerAccount => new DIDs({ payer: payerAccount.secretKey, cluster: clusterName }));

module.exports = {
  enableAwait: true,
  context: { dids: didsPromise, Keypair },
  prompt: 'DID $ '
}


<|start_filename|>example-sparse-did:solid:FcFhBFRf6smQ48p7jFcE35uNuE9ScuUu6R2rdFtWjWhP.json<|end_filename|>
{
  "@context": [
    "https://w3id.org/did/v1.0",
    "https://w3id.org/sol/v1"
  ],
  "id": "did:sol:FcFhBFRf6smQ48p7jFcE35uNuE9ScuUu6R2rdFtWjWhP",
  "publicKeys": [
    {
      "id": "did:sol:FcFhBFRf6smQ48p7jFcE35uNuE9ScuUu6R2rdFtWjWhP#key1",
      "type": "Ed25519VerificationKey2018",
      "controller": "did:sol:FcFhBFRf6smQ48p7jFcE35uNuE9ScuUu6R2rdFtWjWhP",
      "publicKeyBase58": "<KEY>"
    }
  ],
  "authentication": [
    "did:sol:FcFhBFRf6smQ48p7jFcE35uNuE9ScuUu6R2rdFtWjWhP#key1"
  ],
  "capabilityInvocation": [
    "did:sol:FcFhBFRf6smQ48p7jFcE35uNuE9ScuUu6R2rdFtWjWhP#key1"
  ]
}


<|start_filename|>example-did:solid:DSLYfgMTJVMuUKcEge4yNCgAAgt5Xn5YU7wniPXh7BuH.json<|end_filename|>
{
  "@context": "https://w3id.org/did/v1",
  "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa",
  "publicKey": [
    {
      "publicKeyBase58": "<KEY>",
      "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key1",
      "usage": "signing",
      "type": "Secp256k1VerificationKey2018",
      "controller": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa"
    },
    {
      "publicKeyBase58": "<KEY>",
      "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key2",
      "usage": "encryption",
      "type": "X25519KeyAgreementKey2019",
      "controller": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa"
    }
  ],
  "authentication": [
    "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key1",
    "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key2"
  ],
  "capabilityInvocation": [
    "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key2"
  ],
  "keyAgreement": [
    "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key2"
  ],
  "assertion": [
    "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#key1"
  ],
  "service": [
    {
      "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#agent",
      "type": "AgentService",
      "serviceEndpoint": "https://hub.civic.com/did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa/agent"
    }, {
      "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#messages",
      "type": "MessagingService",
      "serviceEndpoint": "https://hub.civic.com/did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa/messages"
    }
  ]
}


<|start_filename|>docs/did-method-spec.html<|end_filename|>
<!DOCTYPE html>
<html>
<head>
  <meta charset='utf-8'>
  <title>SOL DID Method Specification</title>
  <style>
    #instructions {
      border: dashed 1px black;
      padding: 1em;
      background-color:#d0d0d0;
    }
    .replace-me {
      font-style:italic;
      color:magenta
    }
  </style>
  <script
    src='https://www.w3.org/Tools/respec/respec-w3c'
    class='remove'></script>
  <script class='remove'>
    var respecConfig = {
      specStatus: "ED",
      editors: [{
        name: "<NAME>",
        url: "https://identity.com",
      }
      ],
      processVersion: 2017,
      edDraftURI: "https://github.com/identity-com/sol-did",
      shortName: "SOL"
    };
  </script>
</head>
<body>
<section class="introductory">
  <h2>About</h2>
  <p>The SOL DID method specification conforms to the requirements specified in the DID specification
    currently published by the W3C Credentials Community Group. For more information about DIDs and
    DID method specifications, please see the <a
      href="https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-fall2017/blob/master/topics-and-advance-readings/did-primer.md"
      target="_blank">DID Primer</a> and <a href="https://w3c-ccg.github.io/did-spec/">DID Spec</a>.</p>
</section>
<section id='abstract'>
  <p>
    Solana is a high-speed, low-fee public ledger based on a novel Proof-of-History consensus network.
    The SOL DID method is a method for storing DIDs and managing DID documents on Solana, built and maintained
    by Identity.com in conjunction with Solana.
  </p>
</section>
<section id='sotd'>
  <p>&nbsp;
  </p>
</section>
<section>
  <h2>SOL DID Method </h2>
  <p>The namestring that shall identify this DID method is: <code>sol</code></p>
  <p>A DID that uses this method MUST begin with the following prefix: <code>did:sol</code>.
    Per the DID specification, this string MUST be in lowercase. The remainder of the DID, after the prefix,
    is the NSI specified below.</p>
</section>
<section>
  <h2>Target System(s)</h2>
  <p>This DID method applies to the Solana mainnet network as well as the testnet and devnet clusters.</p>
</section>
<section>
  <h2>Namespace Specific Identifier (NSI)</h2>
  <p>
    The SOL DID scheme is defined by the following <a href="ftp://ftp.rfc-editor.org/in-notes/std/std68.txt">ABNF</a>:<br><br>
    <code>
      sol-did    = "did:sol" *(":" network) ":" idstring<br>
      idstring      = 40*48(base58char)<br>
      network  = "testnet" / "devnet" / "localnet" <br>
      base58char          = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "A" / "B" / "C"<br/>
      &nbsp;&nbsp;&nbsp;&nbsp;/ "D" / "E" / "F" / "G" / "H" / "J" / "K" / "L" / "M" / "N" / "P" / "Q"<br/>
      &nbsp;&nbsp;&nbsp;&nbsp;/ "R" / "S" / "T" / "U" / "V" / "W" / "X" / "Y" / "Z" / "a" / "b" / "c"<br/>
      &nbsp;&nbsp;&nbsp;&nbsp;/ "d" / "e" / "f" / "g" / "h" / "i" / "j" / "k" / "m" / "n" / "o" / "p"<br/>
      &nbsp;&nbsp;&nbsp;&nbsp;/ "q" / "r" / "s" / "t" / "u" / "v" / "w" / "x" / "y" / "z"<br>
    </code><br>
    All SOL DIDs are base58 encoded using the Bitcoin/IPFS alphabets of a 32-byte key.
    The encoding uses most alphas and digits, omitting 0OIl to avoid readability problems. This
    gives an NSI length of between 40 and 48 characters, and it means that DIDs are case-sensitive and may not
    be case-normalized, even though the prefix is always lower-case.<br>
    <br>
    Optionally, a network may be specified to indicate which Solana cluster contains the DID document.
  </p>
  <h3>Identifier Generation Method</h3>
  <p>The 32-byte key underlying a SOL DID is generated from the following deterministic algorithm.
    Given a DID owner with a public key on the x25519 ECC Curve, the DID owner key, the DID method ("sol"), a
    "bump seed", and the Solana program ID are hashed together.
  </p><p>
  The "bump seed" ensures the resultant address
  does not clash with the account address space, which lie on the Curve25519
  elliptic curve.
</p><p>
  The program ID is <code>idDa4XeCjVwKcprVAo812coUQbovSZ4kDGJf2sPaBnM</code> on all networks.
</p><p>
  The bump seed is deterministically derivable off-chain as follows:
</p><p>
  <pre>
    Initialize the seed to 256 (2^8)
    Do:
      Decrement the seed by 1
      Hash the owner address, DID method, seed, and program ID
    While the resultant point is on the Curve25519 curve
  </pre>
</p>
  <p>A convenient regex to match <code>SOL</code> DID identifiers is: <br><br>
    <code>^[1-9A-HJ-NP-Za-km-z]{40,48}$</code><br><br>
    A convenient regex to match the entire DID string is:<br><br>
    <code>^did\:sol(\:(testnet|devnet|localnet))?\:[1-9A-HJ-NP-Za-km-z]{40,48}$</code>
  </p>
  <h3>Examples</h3>
  <p>Valid <code>SOL</code> DIDs might be:
    <ul>
  <li><code>did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa</code></li>
  <li><code>did:sol:devnet:6Na3uiqyRGZZQdd19RLCb6kJHR51reFdhXzAuc6Y8Yef</code></li>
  </ul></p>
</section>
<section>
  <h2>Operations</h2>
  The following section outlines the DID operations for the did:sol method.
  <h3 id="create">Create (Register)</h3>
  <p>
      A SOL DID can be created by combining the <code>did:sol(:network)</code> prefix with the <code>AUTHORITY</code>.
    An initial 'sparse' DID document can be generated without the need to register it on the Solana blockchain:
    <pre>
{
    "@context": [
        "https://w3id.org/did/v1.0",
        "https://w3id.org/sol/v1"
    ],
    "id": "did:sol:IDENTIFIER",
    "verificationMethod": [
        {
            "id": "did:sol:IDENTIFIER#key1",
            "type": "Ed25519VerificationKey2018",
            "controller": "did:sol:IDENTIFIER",
            "publicKeyBase58": "AUTHORITY"
        }
    ],
    "authentication": [
        "did:sol:IDENTIFIER#key1"
    ],
    "assertionMethod": [],
    "keyAgreement": [],
    "capabilityInvocation": [
        "did:sol:IDENTIFIER#key1"
    ],
    "capabilityDelegation": [],
    "service": [],
    "publicKey": [
        {
            "id": "did:sol:IDENTIFIER#key1",
            "type": "Ed25519VerificationKey2018",
            "controller": "did:sol:IDENTIFIER",
            "publicKeyBase58": "AUTHORITY"
        }
    ]
}
</pre>
  where: </p><p>
  <code>AUTHORITY</code> is the base58-encoded 32-byte x25519 public key of the DID owner,</p><p>
  <code>IDENTIFIER</code> is the DID method identifier derived from the authority.</p><p>

    Changing the default data of a SOL DID involves submitting a transaction to the Solana blockchain calling the "Initialize" instruction
    on the SOL Program. The only required input to this program is the public key of the 'authority', that is, the
    initial owner of the DID.

    The transaction must be signed by the authority.</p><p>

    The authority is a special key from which the DID is derived. It is always present in the
    <a href="https://www.w3.org/TR/did-core/#dfn-verification-method">verification methods</a> list,
    and by default is added as the only key in the
    <a href="https://www.w3.org/TR/did-core/#capability-invocation">capabilityInvocations</a>
    list, indicating that it is permitted to change
    the DID Document contents. It can, however be removed from the list by submitting an update instruction where the
    capabilityInvocation list is explicitly set (e.g. to the empty list or some other list of keys).

  </p><p>An optional additional SolData field may be added, containing additional document data, such as service
  endpoints or additional keys.
  </p>
<h4 id="fees">Fees and Rent</h4>
  <p>Updating a SOL DID on Solana incurs two types of fee, imposed by the Solana blockchain
    and paid in the chain's native token, SOL.</p>
  <ul>
    <li><strong>Transaction Fee:</strong>
      <p>
      Each action (register, update, delete)
      incurs a
      <a href="https://docs.solana.com/implemented-proposals/transaction-fees">transaction fee</a>.
      This fee is independent of the size of the document.
      </p>
    </li>
    <li><strong>Rent:</strong>
      <p>
      Document registration incurs
      <a href="https://docs.solana.com/implemented-proposals/rent">rent</a>,
      A fee charged on data storage on Solana. The cost of rent depends on the size of the document and
      the length of time that the DID should persist on Solana.
      </p><p>
      It is recommended to deposit sufficient rent to ensure exemption from garbage-collection,
      and this is the assumption made by the
      <a href="#reference-implementations">reference implementation</a>
      client. This rent is then reimbursed upon revocation of the DID.
      </p>
    </li>
  </ul>
  <p>By default, the fee payer is the owner of the DID that will be created. However, the implementation supports
  a separate fee payer, that will incur the charges of registration/updating/deletion of the DID without having
  any permissions on the DID itself. This allows a central body to generate DIDs for its customers, without
  requiring them to have a SOL balance.</p>
  <h3>Read (Resolve)</h3>
  <p>A SOL DID record can be looked up on Solana,by stripping the did:sol: prefix from the DID, and
      network identifier if present, and looking up the resultant account on-chain. If no data is present on-chain,
      the generated DID document (<a href="#create">see above</a>) should be returned.</p>
  <p>
    Anyone can query a DID record, by sending the above request.
    The response contains the DID document,
    encoded in a binary form defined by the <a href="https://borsh.io/">Borsh</a>
    serialization library. A client library is required to convert it to a DID Document.
    The schema for this format is defined in the
    <a href="#reference-implementations">reference implementation client.</a>
  </p>
  <h3>Update (Replace)</h3>
  <p>To replace or update the DID document, the owner of the DID should send a transaction containing
    the "write" instruction to the SOL program.
    This transaction must be signed by a key that is referenced in the
    <strong>capabilityInvocation</strong> property.
  </p><p>
  The instruction parameters are:
</p>
  <ul>
    <li>the account public key (aka the DID method identifier) of the DID to edit</li>
    <li>a valid partial DID document, encoded into binary form</li>
    <li>the byte offset at which to write the data</li>
  </ul>
  <p>
  Each value is expected to be calculated by a client library, rather than calculated manually
  (see the <a href="#reference-implementations">reference implementation</a> for details).
  </p><p>
  For example, adding the following DID sub-document:
  <pre>
{
    "service": [
        {
            "id": "did:sol:IDENTIFIER#agent",
            "type": "AgentService",
            "serviceEndpoint": "https://hub.myhub.com/did:sol:IDENTIFIER/agent"
        }, {
            "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#messages",
            "type": "MessagingService",
            "serviceEndpoint": "https://hub.myhub.com/did:sol:IDENTIFIER/messages"
        }
    ]
}

</pre>
  to the above document, results in:
  <pre>
{
    "@context": [
        "https://w3id.org/did/v1.0",
        "https://w3id.org/sol/v1"
    ],
    "id": "did:sol:IDENTIFIER",
    "verificationMethod": [
        {
            "id": "did:sol:IDENTIFIER#key1",
            "type": "Ed25519VerificationKey2018",
            "controller": "did:sol:IDENTIFIER",
            "publicKeyBase58": "AUTHORITY"
        }
    ],
    "authentication": [
        "did:sol:IDENTIFIER#key1"
    ],
    "assertionMethod": [],
    "keyAgreement": [],
    "capabilityInvocation": [
        "did:sol:IDENTIFIER#key1"
    ],
    "capabilityDelegation": [],
    "service": [
        {
            "id": "did:sol:IDENTIFIER#agent",
            "type": "AgentService",
            "serviceEndpoint": "https://hub.myhub.com/did:sol:IDENTIFIER/agent"
        }, {
            "id": "did:sol:ygGfLvAyuRymPNv2fJDK1ZMpdy59m8cV5dak6A8uHKa#messages",
            "type": "MessagingService",
            "serviceEndpoint": "https://hub.myhub.com/did:sol:IDENTIFIER/messages"
        }
    ],
    "publicKey": [
        {
            "id": "did:sol:IDENTIFIER#key1",
            "type": "Ed25519VerificationKey2018",
            "controller": "did:sol:IDENTIFIER",
            "publicKeyBase58": "AUTHORITY"
        }
    ]
}

</pre>

  Only the AUTHORITY key can make this change,
  as that is the only one referenced inside <strong>capabilityInvocation</strong>.
  <br/>
  An update can add an entry to or remove an entry from the capabilityInvocation list.
  <br/>
  As with creation, an update transaction can specify a separate fee payer account to pay the transaction fee.
  <h3>Delete (Revoke)</h3>
  <p>A SOL DID can be irreversibly deleted or revoked.</p>
  <p> To revoke the document of the DID, the owner of
    the DID should send a transaction with a CloseAccount instruction.
    As with create and update, the owner
  of the DID is the default fee payer for the transaction,
    however, a separate fee payer account can be specified,
    in which case, this account will also receive any reimbursed
    <a href="#fees">rent</a> in the account that stores the DID document.
  </p>
    <p>When a SOL DID has been deleted, the DID document will resolve to the <a href="#create">generated</a> version.</p>
</section>

<section>
  <h2>Security Considerations</h2>
  <h3>Attacks</h3>
  <p>Since all changes to SOL DIDs are locally-signed transactions on the Solana blockchain,
    it leverages the security of the <a href="https://solana.com/solana-security-audit-2019.pdf">audited</a>
    Solana prototol.
    Any vulnerabilities in that protocol will apply to SOL.</p>
  <p>
    SOL stores only public DIDs/DID Documents, which include public keys and service endpoints, on-chain.
  </p>
    <h3>Recovery From Key Compromise</h3>

    <p>It is recommended, although not enforced by SOL, that more than one key be included in the
    <strong>capabilityInvocation</strong> list. This allows a second trusted key to remove the reference
    to the first in the event of a key compromise. It is also recommended to include additional verification
    methods and keys that have permissions to perform actions with the DID (such as sign messages),
      but do not have permissions to update the document itself.
    This allows the capabilityInvocation keys to be stored in cold-storage, and only used when a key
    needs to be revoked. This protects against malicious rewriting of the document to add attackers' keys.</p>
</section>

<section>
  <h2>Privacy Considerations</h2>
  <div>
    DIDs should be assumed to be pseudonymous. Since the DID is registered on a decentralized ledger,
    it is not fully revocable, and this risk should be recognised by users of the DID method. As with all
    public pseudonymous persistent identifiers, there exists a risk of correlation when associating any other
    information with the DID in a way that exposes this information publicly.
  </div>
</section>

<section id="reference-implementations">
  <h2>Reference Implementations</h2>
  It is expected that integrators of the SOL DID method do not interact with the Solana blockchain directly,
  but use a client library.

  A reference implementation, written in Typescript, is available at
  <a href="https://github.com/identity-com/sol-did" target="_blank">https://github.com/identity-com/sol-did</a>
  and as <a href="https://www.npmjs.com/package/@identity.com/sol-did-client" target="_blank">an NPM library</a>
</section>
<section id='conformance'></section>
</body>
</html>
