-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor packages APIs #301
Changes from 23 commits
b58152c
b8bb41b
2e6740e
5927d78
a5e6d8b
da71bf0
7de1be7
58254d0
737b215
71b3089
2aa2720
1292f31
5051b03
a417a00
ed40754
719f6a0
f3fc336
7752c24
9042753
d5c70a5
acb0fa1
fbc90e1
d2c4bf7
0a13562
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,4 +13,5 @@ contracts/compiled | |
examples/*/pnpm-lock.yaml | ||
pnpm-debug.log | ||
docs-json | ||
docs | ||
./docs | ||
.next |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
16 | ||
18 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# `@nucypher/*` Demos | ||
|
||
- [`taco-demo`](./taco-demo) - A demo of the `@nucypher/taco` library. | ||
- [`taco-nft-demo`](./taco-nft-demo) - A demo an NFT-based condition using the `@nucypher/taco` library. | ||
- [`nucypher-ts-demo`](https://github.com/nucypher/nucypher-ts-demo) - A demo of PRE in the `nucypher-ts` library. | ||
- [`tdec-sandbox`](https://github.com/nucypher/tdec-sandbox) - A demo of tDec in the `nucypher-ts` library. | ||
- [`tdec-nft-example`](https://github.com/nucypher/tdec-nft-example) - A demo of tDec in the `nucypher-ts` library. | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# taco-demo | ||
|
||
## Installation | ||
|
||
```bash | ||
pnpm install | ||
pnpm start | ||
``` | ||
|
||
## Usage | ||
|
||
In order to run this demo will need a MetaMask with an account funded with some | ||
$MATIC. | ||
|
||
In order to connect with the network, the demo uses a public instances of | ||
[Porter](https://docs.threshold.network/app-development/threshold-access-control-tac/porter). | ||
|
||
### Polygon | ||
|
||
`@nucypher/taco` is in an early release. We recommend **not** using it in | ||
production _just yet_. | ||
Comment on lines
+18
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this for a demo readme? |
||
|
||
### Tapir - Mumbai Testnet | ||
|
||
The current release of `@nucypher/taco` supports Ursulas working on Tapir | ||
network and contracts deployed on Mumbai testnet. | ||
|
||
## References | ||
|
||
This dApp is based on | ||
[`useDapp` example](https://github.com/EthWorks/useDapp/tree/master/packages/example). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
{ | ||
"name": "taco-demo", | ||
"version": "0.1.0", | ||
"description": "A usage example for @nucypher/taco", | ||
"private": true, | ||
"author": "Piotr Rosłaniec <p.roslaniec@gmail.com>", | ||
"scripts": { | ||
"start": "webpack serve --mode development", | ||
"build": "tsc --noEmit && rimraf build && webpack --mode production --progress" | ||
}, | ||
"dependencies": { | ||
"@nucypher/taco": "workspace:*", | ||
"@usedapp/core": "^1.2.13", | ||
"buffer": "^6.0.3", | ||
"ethers": "^5.7.1", | ||
"file-loader": "^6.2.0", | ||
"react": "^18.2.0", | ||
"react-copy-to-clipboard": "^5.1.0", | ||
"react-dom": "^18.2.0", | ||
"react-spinners": "^0.13.6" | ||
}, | ||
"devDependencies": { | ||
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7", | ||
"@types/react": "^18.0.20", | ||
"@types/react-copy-to-clipboard": "^5.0.4", | ||
"@types/react-dom": "^18.0.6", | ||
"copy-webpack-plugin": "^11.0.0", | ||
"esbuild-loader": "^2.20.0", | ||
"html-webpack-plugin": "^5.5.0", | ||
"react-refresh": "^0.14.0", | ||
"rimraf": "^3.0.2", | ||
"stream-browserify": "^3.0.0", | ||
"typescript": "^4.8.3", | ||
"webpack": "^5.74.0", | ||
"webpack-cli": "^4.10.0", | ||
"webpack-dev-server": "^4.11.1" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { | ||
conditions, | ||
decrypt, | ||
encrypt, | ||
getPorterUri, | ||
initialize, | ||
ThresholdMessageKit, | ||
} from '@nucypher/taco'; | ||
Comment on lines
+1
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Look how shiny! 🤩 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It does look very clean 🎸 |
||
import { Mumbai, useEthers } from '@usedapp/core'; | ||
import { ethers } from 'ethers'; | ||
import React, { useEffect, useState } from 'react'; | ||
|
||
import { ConditionBuilder } from './ConditionBuilder'; | ||
import { Decrypt } from './Decrypt'; | ||
import { Encrypt } from './Encrypt'; | ||
import { Spinner } from './Spinner'; | ||
|
||
export default function App() { | ||
const { activateBrowserWallet, deactivate, account, switchNetwork } = | ||
useEthers(); | ||
|
||
const [loading, setLoading] = useState(false); | ||
const [condition, setCondition] = useState<conditions.Condition>(); | ||
const [encryptedMessage, setEncryptedMessage] = | ||
useState<ThresholdMessageKit>(); | ||
const [decryptedMessage, setDecryptedMessage] = useState<string>(); | ||
const [decryptionErrors, setDecryptionErrors] = useState<string[]>([]); | ||
const [ritualId, setRitualId] = useState<number>(2); | ||
|
||
useEffect(() => { | ||
initialize(); | ||
switchNetwork(Mumbai.chainId); | ||
}, []); | ||
|
||
const encryptMessage = async (message: string) => { | ||
if (!condition) { | ||
return; | ||
} | ||
Comment on lines
+36
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it's not obvious to me what the intended flow control is here, are you using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
setLoading(true); | ||
|
||
await switchNetwork(Mumbai.chainId); | ||
|
||
const provider = new ethers.providers.Web3Provider(window.ethereum); | ||
const encryptedMessage = await encrypt( | ||
provider, | ||
message, | ||
condition, | ||
ritualId, | ||
provider.getSigner(), | ||
); | ||
|
||
setEncryptedMessage(encryptedMessage); | ||
setLoading(false); | ||
}; | ||
|
||
const decryptMessage = async (encryptedMessage: ThresholdMessageKit) => { | ||
if (!condition) { | ||
return; | ||
} | ||
setLoading(true); | ||
setDecryptedMessage(''); | ||
setDecryptionErrors([]); | ||
|
||
const provider = new ethers.providers.Web3Provider(window.ethereum); | ||
const porterUri = getPorterUri('lynx'); | ||
const decryptedMessage = await decrypt( | ||
provider, | ||
encryptedMessage, | ||
provider.getSigner(), | ||
porterUri, | ||
); | ||
|
||
setDecryptedMessage(new TextDecoder().decode(decryptedMessage)); | ||
setLoading(false); | ||
}; | ||
|
||
if (!account) { | ||
return ( | ||
<div> | ||
<h2>Web3 Provider</h2> | ||
<button onClick={() => activateBrowserWallet()}>Connect Wallet</button> | ||
</div> | ||
); | ||
} | ||
|
||
if (loading) { | ||
return <Spinner loading={loading} />; | ||
} | ||
|
||
return ( | ||
<div> | ||
<div> | ||
<h2>Web3 Provider</h2> | ||
<button onClick={deactivate}> Disconnect Wallet</button> | ||
{account && <p>Account: {account}</p>} | ||
</div> | ||
|
||
<h2>Ritual ID</h2> | ||
<p>Replace with your own ritual ID</p> | ||
<input type={'number'} value={ritualId} onChange={(e) => setRitualId(parseInt(e.currentTarget.value))} /> | ||
|
||
<ConditionBuilder | ||
enabled={true} | ||
condition={condition} | ||
setConditions={setCondition} | ||
/> | ||
|
||
<Encrypt | ||
enabled={!!condition} | ||
encrypt={encryptMessage} | ||
encryptedMessage={encryptedMessage!} | ||
/> | ||
|
||
<Decrypt | ||
enabled={!!encryptedMessage} | ||
decrypt={decryptMessage} | ||
decryptedMessage={decryptedMessage} | ||
decryptionErrors={decryptionErrors} | ||
/> | ||
</div> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import {conditions} from '@nucypher/taco'; | ||
import {Mumbai, useEthers} from '@usedapp/core'; | ||
import React, {useState} from 'react'; | ||
|
||
interface Props { | ||
condition?: conditions.Condition | undefined; | ||
setConditions: (value: conditions.Condition) => void; | ||
enabled: boolean; | ||
} | ||
|
||
const rpcCondition = new conditions.RpcCondition({ | ||
conditionType: 'rpc', | ||
chain: Mumbai.chainId, | ||
method: 'eth_getBalance', | ||
parameters: [':userAddress'], | ||
returnValueTest: { | ||
comparator: '>', | ||
value: '0', | ||
}, | ||
}); | ||
|
||
export const ConditionBuilder = ({ | ||
condition, | ||
setConditions, | ||
enabled, | ||
}: Props) => { | ||
const {library} = useEthers(); | ||
|
||
const demoCondition = JSON.stringify((condition ?? rpcCondition).toObj()); | ||
const [conditionString, setConditionString] = useState(demoCondition); | ||
|
||
if (!enabled || !library) { | ||
return <></>; | ||
} | ||
|
||
const prettyPrint = (obj: object | string) => { | ||
if (typeof obj === 'string') { | ||
obj = JSON.parse(obj); | ||
} | ||
return JSON.stringify(obj, null, 2); | ||
}; | ||
|
||
const makeInput = ( | ||
onChange = (e: any) => console.log(e), | ||
defaultValue: string, | ||
) => ( | ||
<textarea | ||
rows={15} | ||
onChange={(e: any) => onChange(e.target.value)} | ||
defaultValue={prettyPrint(defaultValue)} | ||
> | ||
{} | ||
</textarea> | ||
); | ||
|
||
const conditionJSONInput = makeInput( | ||
setConditionString, | ||
JSON.stringify(rpcCondition.toObj()), | ||
); | ||
|
||
const onCreateCondition = (e: any) => { | ||
e.preventDefault(); | ||
setConditions(conditions.Condition.fromObj(JSON.parse(conditionString))); | ||
}; | ||
|
||
return ( | ||
<> | ||
<h2>Step 1 - Create A Conditioned Access Policy</h2> | ||
<div> | ||
<div> | ||
<h3>Customize your Conditions</h3> | ||
<div> | ||
<h3>Condition JSON</h3> | ||
{conditionJSONInput} | ||
</div> | ||
</div> | ||
<button onClick={onCreateCondition}>Create Conditions</button> | ||
</div> | ||
</> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { ThresholdMessageKit } from '@nucypher/taco'; | ||
import React, { useState } from 'react'; | ||
|
||
interface Props { | ||
enabled: boolean; | ||
decrypt: (encryptedMessage: ThresholdMessageKit) => void; | ||
decryptedMessage?: string | undefined; | ||
decryptionErrors: string[]; | ||
} | ||
|
||
export const Decrypt = ({ | ||
decrypt, | ||
decryptedMessage, | ||
decryptionErrors, | ||
enabled, | ||
}: Props) => { | ||
const [encryptedMessage, setEncryptedMessage] = useState(''); | ||
|
||
if (!enabled) { | ||
return <></>; | ||
} | ||
|
||
const onDecrypt = () => { | ||
if (!encryptedMessage) { | ||
return; | ||
} | ||
const mkBytes = Buffer.from(encryptedMessage, 'base64'); | ||
const mk = ThresholdMessageKit.fromBytes(mkBytes); | ||
decrypt(mk); | ||
}; | ||
|
||
const DecryptedMessage = () => { | ||
if (!decryptedMessage) { | ||
return <></>; | ||
} | ||
return ( | ||
<> | ||
<h3>Decrypted Message:</h3> | ||
<p>{decryptedMessage}</p> | ||
</> | ||
); | ||
}; | ||
|
||
const DecryptionErrors = () => { | ||
if (decryptionErrors.length === 0) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div> | ||
<h2>Decryption Errors</h2> | ||
<p>Not enough decryption shares to decrypt the message.</p> | ||
<p>Some Ursulas have failed with errors:</p> | ||
<ul> | ||
{decryptionErrors.map((error, index) => ( | ||
<li key={index}>{error}</li> | ||
))} | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<h2>Step 3 - Decrypt Encrypted Message</h2> | ||
<input | ||
value={encryptedMessage} | ||
placeholder="Enter encrypted message" | ||
onChange={(e) => setEncryptedMessage(e.currentTarget.value)} | ||
/> | ||
<button onClick={onDecrypt}>Decrypt</button> | ||
{DecryptedMessage()} | ||
{DecryptionErrors()} | ||
</div> | ||
); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the spirit of the monorepo, shall we also internalize these demos to this repo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Internalizing
nucypher-ts-demo
will require releasing@nucypher/pre
, which I think we should postpone.tdec-sandbox
andtdec-nft-example
will be deprecated (archived) and replaced by existingdemos
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also generally agree with the division of examples/demos mentioned above 👍🏻
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^ If we are going to deprecate/archive these, should we remove these in the readme then?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove them from the
README.md
when we have a working alternative.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These things are easy to forget. If you are going to leave them for now, I'd recommend filing an issue and setting the appropriate project on it, so that it can be followed up on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tracked in #308