Skip to content

Commit

Permalink
transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
itali43 committed Dec 29, 2021
1 parent cd97c90 commit abeebbf
Show file tree
Hide file tree
Showing 33 changed files with 11,142 additions and 7,321 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
.env
package.json
node_modules
yarn-error.log
88 changes: 88 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Lit Ceramic Integration Module

### Installation

`yarn add @litelliott/lit-ceramic-integration`

### How to Implement

The following are steps to implement. In addition, we also have a wonderful folder called 'documentation' in the root directory of this repo that has markdown files with explanations of all the important methods.

1. Install as show above
NOTE: an example of this implementation can be found in the lit-ceramic web playground we built to accompany the release of this module.
2. import into your TS/JS where you'd like to use it. This is a typescript package as an FYI.

`import { Integration } from '@litelliott/lit-ceramic-integration'`

Javascript requires minor amounts of extra work to use a Typescript project, [here's an example](https://www.freecodecamp.org/news/how-to-add-typescript-to-a-javascript-project/) of what that can look like, but there are plenty of good resources for this online.

3. Create a new Integration that runs upon startup and is accessible where you intend to do encryptAndWrite or readAndDecrypt operations:
`let litCeramicIntegration = new Integration()`
4. Start the Lit Client when the DOM is loaded, or early on in the lifecycle:
`litCeramicIntegration.startLitClient(window)`
5. Here is what an encryptAndWrite operation looks like:

```
const stringToEncrypt = 'This is what we want to encrypt on Lit and then store on ceramic'
const response = litCeramicIntegration
.encryptAndWrite(stringToEncrypt)
.then((value) => updateStreamID(value))
```

Note that the stringToEncrypt is the thing which we are encrypting in this example. and the `updateStreamID` function is a bespoke (not in the integration module) function that takes the value that the promise produces and shows it in the HTML, so that the user can know what their streamID is (and therefore how they can access their encrypted and stored secret). You can do anything with the value variable, it will give back the stored value's streamID.

6. Here is what a readAndDecrypt operation looks like:

```
const streamID = 'kjzl6cwe1jw1479rnblkk5u43ivxkuo29i4efdx1e7hk94qrhjl0d4u0dyys1au'
const response = litCeramicIntegration.readAndDecrypt(streamID).then(
(value) =>
console.log(value)
)
```

This uses an example streamID and prints the secret value to the console.

### How to develop in your local environment

this helped: https://flaviocopes.com/npm-local-package/

### Notes

- Important to restart parcel in the project you're using this module with when you are editing locally, otherwise it won't update.

### To Do / Desired Future Features

- Change infuraID in ./wallet's `web3Modal`.
- Enable Swap to Ceramic's mainnet

### Test Data

#### Testing Ceramic Read Function

If you'd like ping the ceramic test net for a streamID that already works, use the following streamID: `kjzl6cwe1jw14afliaj4m2vku3uy67ulyxj0erv5jgqz6k6cw0vtz27mf76m4ww`

Manually, you can start the `ceramic daemon` and then in another terminal window enter `ceramic show kjzl6cwe1jw14afliaj4m2vku3uy67ulyxj0erv5jgqz6k6cw0vtz27mf76m4ww`
It should return the following:

{
"chain": "ethereum",
"symKey": "gvKsVkBRS7d+baui7nJgf3b/G+8df1KNEYhVZ6kF97H8I0NROsKPd7BXds4jWbMK+rqlDa3Y2st4XQIHLqXLZVWJn5EZLNsYgEuZZPFaNbw7CGswjdSeMUK6WF8vAXS1+LbYrbal3GbTA+1JZ7Rc/xCKmpqM2Dvz2Btj8dhY3AUAAAAAAAAAIKnDOtW9nceKILkczbD1YjUyC3on3kTXKSJNyq2y4dmxy42BUuU6z+iI4WWZ2wmUhg==",
"encryptedZip": "rAf1RDm7nf4STWdhPS4gYWrlNHS9HcAUO/w0E86xcEC5zdLIF0TlGKVqeCowGNKtB8ecz/zxFp/8Ra+js4WOwK/yATFi5AxoCu2s5653rDZr9AjIQ8ii4pKeeRm+qEnL3bzXtmJT+5XiixTz5zgxhGgOccYMdDeOjJUKf6okOFBwVLCrUHyPd4MdbE+SLA8/hnUh7EnTLykF+3GJnD0cyQ==",
"accessControlConditions": [
{
"chain": "ethereum",
"method": "eth_getBalance",
"parameters": [
":userAddress",
"latest"
],
"contractAddress": "0x20598860da775f63ae75e1cd2ce0d462b8cee4c7",
"returnValueTest": {
"value": "10000000000000",
"comparator": ">="
},
"standardContractType": ""
}
]
}
150 changes: 150 additions & 0 deletions ceramic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import type { CeramicApi } from '@ceramicnetwork/common'
import Ceramic from '@ceramicnetwork/http-client'
import { Caip10Link } from '@ceramicnetwork/stream-caip10-link'
import { TileDocument } from '@ceramicnetwork/stream-tile'
import { DID } from 'dids'
import ThreeIdResolver from '@ceramicnetwork/3id-did-resolver'
import KeyDidResolver from 'key-did-resolver'
import { createIDX } from './idx'
import { getProvider, getAddress } from './wallet'
import { ResolverRegistry } from 'did-resolver'
import {decodeb64 } from "./lit";

declare global {
interface Window {
ceramic?: CeramicApi
[index: string]: any
}
}

/**
* Authenticate for Lit + Ceramic.
* Creates a CeramicApi object on the ceramic testnet
*
* @returns {Promise<CeramicApi>} ceramicPromise pass in _createCeramic() promise
*/
export async function _createCeramic(): Promise<CeramicApi> {
const ceramic = new Ceramic('https://ceramic-clay.3boxlabs.com')
window.ceramic = ceramic
window.TileDocument = TileDocument
window.Caip10Link = Caip10Link

return Promise.resolve(ceramic as CeramicApi)
}

/**
* Authenticate for Lit + Ceramic.
* This uses a wallet provider to interact with the user's wallet
* Once the user has authorized, the address is retrieved and the
* decentralized identity is created. An IDX is also created for
* convenience.
*
* @param {Promise<CeramicApi>} ceramicPromise pass in _createCeramic() promise
* @returns {Promise<Array<any>>} Promise of ceramic IDX ID, ceramic object
* and user's ETH Address
*/
export async function _authenticateCeramic(
ceramicPromise: Promise<CeramicApi>
): Promise<Array<any>> {
console.log('authenticate Ceramic!')

const provider = await getProvider()
const [ceramic, address] = await Promise.all([ceramicPromise, getAddress()])
const keyDidResolver = KeyDidResolver.getResolver()
const threeIdResolver = ThreeIdResolver.getResolver(ceramic)
const resolverRegistry: ResolverRegistry = {
...threeIdResolver,
...keyDidResolver,
}
const did = new DID({
provider: provider,
resolver: resolverRegistry,
})

await did.authenticate()
await ceramic.setDID(did)
const idx = createIDX(ceramic)
window.did = ceramic.did
return Promise.resolve([idx.id, ceramic, address])
}

/**
* Write to Ceramic. This function takes in an auth and what one would
* like written and then sends it to a ceramic node in the proper format
* @param {any[]} auth is the authentication passed via the persons wallet
* @param {any[]} array of encrypted key, symkey, accessControlConditions, and chain
* @returns {Promise<string>} promise with the ceramic streamID, can be used to look up data
*/
export async function _writeCeramic(auth: any[], toBeWritten: any[]): Promise<String> {
if (auth) {
const ceramic = auth[1]
const toStore = {
encryptedZip: toBeWritten[0],
symKey: toBeWritten[1],
accessControlConditions: toBeWritten[2],
chain: toBeWritten[3],
}
const doc = await TileDocument.create(ceramic, toStore, {
// controllers: [concatId],
family: 'doc family',
})
return doc.id.toString()
} else {
console.error('Failed to authenticate in ceramic WRITE')
return 'error'
}
}

/**
* Write to Ceramic. This function takes in an auth and what one would
* like written and then sends it to a ceramic node in the proper format
*
* for testing this function and understanding ceramic's read functionality better
* see our README, Test Data section. Also the Ceramic docs on Read Functionality!
*
* @param {any[]} auth is the authentication passed via the user's wallet
* @param {String} streamId ID hash of the stream
* @returns {Promise<string>} promise with the ceramic streamID's output
*/
export async function _readCeramic(auth: any[], streamId: String): Promise<string> {
if (auth) {
const ceramic = auth[1]
const stream = await ceramic.loadStream(streamId)
return stream.content
} else {
console.error('Failed to authenticate in ceramic READ')
return 'error'
}
}

/**
* Decode info from base64. Data is stored in base64 to make upload to ceramic
* more seamless. This function decodes it so it can be decrypted with Lit in
* the next step in the read and decrypt process
*
* @param {string} response response received from ceramic streamID
* @returns {Promise<Array<any>} array of decrypted zip and symmetric key + AAC and chain
*/
export async function _decodeFromB64(response: string) {

// data is encoded in base64, decode
// const jason = JSON.stringify(response);
try {
// @ts-ignore
const enZip = response["encryptedZip"];
const deZip = decodeb64(enZip);

// @ts-ignore
const enSym = response["symKey"];
const deSym = decodeb64(enSym);

// @ts-ignore
const accessControlConditions = response["accessControlConditions"];
// @ts-ignore
const chain = response["chain"];
return [deZip, deSym, accessControlConditions, chain]
} catch (error) {
return "There was an error decrypting, is it possible you inputted the wrong streamID?"
}

};
Empty file removed ceramicFunctions.ts
Empty file.
14 changes: 14 additions & 0 deletions client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as LitJsSdk from "lit-js-sdk";

/**
* Starts Lit Client in background. should be run upon starting of project.
*
* @param {Window} window the window of the project, to which it attaches
* a litNodeClient
*/
export async function _startLitClient(window: Window) {
console.log("Starting Lit Client...");
const client = new LitJsSdk.LitNodeClient();
client.connect();
window.litNodeClient = client;
}
17 changes: 17 additions & 0 deletions documentation/_howToUpdateDocs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# How To Update Documentation

###### Skip to the end if you want..

DocumentationJS 'works' with Typescript... But not particularly well. As such the way to update the docs is a little wonky, and you have to run through them TS file by TS file.

As such, here are the files that have documentation and the commands that should be run.

`documentation build integration.ts --parse-extension ts -f md -o documentation/integration --shallow`
`documentation build lit.ts --parse-extension ts -f md -o documentation/lit --shallow`
`documentation build ceramic.ts --parse-extension ts -f md -o documentation/ceramic --shallow`
`documentation build client.ts --parse-extension ts -f md -o documentation/client --shallow`

### But wait, there's more!!!!

There's a convenience script that has been made to do all of these at once:
`yarn build:docs`
97 changes: 97 additions & 0 deletions documentation/ceramic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

### Table of Contents

* [\_createCeramic][1]
* [\_authenticateCeramic][2]
* [Parameters][3]
* [\_writeCeramic][4]
* [Parameters][5]
* [\_readCeramic][6]
* [Parameters][7]
* [\_decodeFromB64][8]
* [Parameters][9]

## \_createCeramic

Authenticate for Lit + Ceramic.\
Creates a CeramicApi object on the ceramic testnet

Returns **[Promise][10]\<CeramicApi>** ceramicPromise pass in \_createCeramic() promise

## \_authenticateCeramic

Authenticate for Lit + Ceramic.\
This uses a wallet provider to interact with the user's wallet
Once the user has authorized, the address is retrieved and the
decentralized identity is created. An IDX is also created for
convenience.

### Parameters

* `ceramicPromise` **[Promise][10]\<CeramicApi>** pass in \_createCeramic() promise

Returns **[Promise][10]<[Array][11]\<any>>** Promise of ceramic IDX ID, ceramic object
and user's ETH Address

## \_writeCeramic

Write to Ceramic. This function takes in an auth and what one would
like written and then sends it to a ceramic node in the proper format

### Parameters

* `auth` **[Array][11]\<any>** is the authentication passed via the persons wallet
* `toBeWritten` **[Array][11]\<any>**
* `array` **[Array][11]\<any>** of encrypted key, symkey, accessControlConditions, and chain

Returns **[Promise][10]<[string][12]>** promise with the ceramic streamID, can be used to look up data

## \_readCeramic

Write to Ceramic. This function takes in an auth and what one would
like written and then sends it to a ceramic node in the proper format

for testing this function and understanding ceramic's read functionality better
see our README, Test Data section. Also the Ceramic docs on Read Functionality!

### Parameters

* `auth` **[Array][11]\<any>** is the authentication passed via the user's wallet
* `streamId` **[String][12]** ID hash of the stream

Returns **[Promise][10]<[string][12]>** promise with the ceramic streamID's output

## \_decodeFromB64

Decode info from base64. Data is stored in base64 to make upload to ceramic
more seamless. This function decodes it so it can be decrypted with Lit in
the next step in the read and decrypt process

### Parameters

* `response` **[string][12]** response received from ceramic streamID

[1]: #_createceramic

[2]: #_authenticateceramic

[3]: #parameters

[4]: #_writeceramic

[5]: #parameters-1

[6]: #_readceramic

[7]: #parameters-2

[8]: #_decodefromb64

[9]: #parameters-3

[10]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise

[11]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array

[12]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String
21 changes: 21 additions & 0 deletions documentation/client.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

### Table of Contents

* [\_startLitClient][1]
* [Parameters][2]

## \_startLitClient

Starts Lit Client in background. should be run upon starting of project.

### Parameters

* `window` **[Window][3]** the window of the project, to which it attaches
a litNodeClient

[1]: #_startlitclient

[2]: #parameters

[3]: https://developer.mozilla.org/docs/Web/API/Window
Loading

0 comments on commit abeebbf

Please sign in to comment.