├── .circleci
└── config.yml
├── .eslintignore
├── .eslintrc.js
├── .gitbook.yaml
├── .github
├── FUNDING.yml
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── .huskyrc.js
├── .prettierrc
├── LICENSE
├── README.md
├── babel.config.js
├── commitlint.config.js
├── docs
├── README.md
├── SUMMARY.md
├── comparison_to_others
│ └── README.md
├── getting_started
│ └── README.md
└── using_aztec
│ └── README.md
├── lerna.json
├── package.json
├── packages
├── contract-artifacts
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── .lintstagedrc
│ ├── .prettierrc.js
│ ├── addresses
│ │ └── rinkeby.json
│ ├── contracts
│ │ ├── NoteStream.ts
│ │ ├── StreamUtilities.ts
│ │ ├── Types.ts
│ │ └── contracts.ts
│ ├── package.json
│ ├── src
│ │ ├── addresses.ts
│ │ ├── artifacts.ts
│ │ └── index.ts
│ └── tsconfig.json
├── contracts
│ ├── .env.development
│ ├── .eslintrc.js
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .lintstagedrc
│ ├── README.md
│ ├── buidler.config.js
│ ├── contracts
│ │ ├── AZTEC
│ │ │ └── Imports.sol
│ │ ├── NoteStream.sol
│ │ ├── StreamUtilities.sol
│ │ ├── Types.sol
│ │ ├── mocks
│ │ │ └── StreamUtilitiesMock.sol
│ │ └── test
│ │ │ ├── ERC20Mintable.sol
│ │ │ └── Imports.sol
│ ├── env.js
│ ├── package.json
│ ├── scripts
│ │ ├── deploy.js
│ │ └── deployZkAsset.js
│ ├── tasks
│ │ └── export.js
│ └── test
│ │ ├── NoteStream
│ │ ├── cancelStream.js
│ │ ├── constructor.js
│ │ ├── createStream.js
│ │ ├── getStream.js
│ │ ├── index.js
│ │ └── withdrawFromStream.js
│ │ ├── StreamUtilities
│ │ ├── getRatio.js
│ │ ├── index.js
│ │ ├── processCancellation.js
│ │ ├── processWithdrawal.js
│ │ ├── validateJoinSplitProof.js
│ │ └── validateRatioProof.js
│ │ ├── fixtures.js
│ │ └── runTests.js
├── dev-utils
│ ├── .eslintignore
│ ├── .eslintrc
│ ├── .gitignore
│ ├── .lintstagedrc
│ ├── .prettierrc.js
│ ├── README.md
│ ├── babel.config.js
│ ├── package.json
│ └── src
│ │ ├── chaiPlugin.js
│ │ ├── constants.js
│ │ ├── errors.js
│ │ ├── index.js
│ │ └── mochaContexts.js
├── monorepo-scripts
│ ├── .lintstagedrc
│ ├── ci
│ │ └── hasChanged.sh
│ └── package.json
├── react-app
│ ├── .env
│ ├── .eslintrc.js
│ ├── .lintstagedrc
│ ├── .prettierrc.js
│ ├── README.md
│ ├── now.json
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ ├── src
│ │ ├── App.tsx
│ │ ├── abis
│ │ │ └── ERC20Detailed.ts
│ │ ├── components
│ │ │ ├── Link.tsx
│ │ │ ├── Sidebar
│ │ │ │ ├── SideBarLinks.tsx
│ │ │ │ ├── WalletButton.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── StreamTable
│ │ │ │ ├── StreamRow.tsx
│ │ │ │ └── index.tsx
│ │ │ ├── Table
│ │ │ │ ├── TableHead.tsx
│ │ │ │ ├── columns.ts
│ │ │ │ ├── index.tsx
│ │ │ │ └── sorting.ts
│ │ │ ├── display
│ │ │ │ └── DoubleProgressBar.tsx
│ │ │ ├── form
│ │ │ │ ├── AddressInput.tsx
│ │ │ │ ├── AmountInput.tsx
│ │ │ │ └── ZkAssetSelect.tsx
│ │ │ └── modals
│ │ │ │ └── CreateStreamModal.tsx
│ │ ├── contexts
│ │ │ ├── AztecContext.tsx
│ │ │ └── OnboardContext.tsx
│ │ ├── graphql
│ │ │ └── streams.ts
│ │ ├── hooks
│ │ │ ├── useDecodedNote.ts
│ │ │ └── useENSName.ts
│ │ ├── index.css
│ │ ├── index.tsx
│ │ ├── pages
│ │ │ ├── ExchangePage.tsx
│ │ │ ├── HomePage.tsx
│ │ │ ├── ReceivePage.tsx
│ │ │ └── SendPage.tsx
│ │ ├── react-app-env.d.ts
│ │ ├── serviceWorker.ts
│ │ ├── setupTests.ts
│ │ ├── theme.tsx
│ │ ├── types
│ │ │ ├── declarations.d.ts
│ │ │ └── types.ts
│ │ └── utils
│ │ │ ├── ens
│ │ │ └── lookupAddress.ts
│ │ │ ├── links.ts
│ │ │ ├── note.ts
│ │ │ ├── proofs
│ │ │ ├── dividend.ts
│ │ │ ├── index.ts
│ │ │ ├── joinsplit.ts
│ │ │ └── proofs.ts
│ │ │ ├── stream
│ │ │ ├── cancellation.ts
│ │ │ ├── creation.ts
│ │ │ ├── index.ts
│ │ │ └── withdrawal.ts
│ │ │ ├── time.ts
│ │ │ ├── transak.ts
│ │ │ └── units
│ │ │ └── convertToTokenValue.ts
│ └── tsconfig.json
└── subgraph
│ ├── .eslintrc.js
│ ├── .gitignore
│ ├── .lintstagedrc
│ ├── .prettierrc.js
│ ├── README.md
│ ├── abis
│ └── NoteStream.json
│ ├── networks.yaml
│ ├── package.json
│ ├── schema.graphql
│ ├── src
│ └── mappings
│ │ ├── noteStream.ts
│ │ ├── tokens.ts
│ │ ├── transactions.ts
│ │ └── zkAssets.ts
│ ├── subgraph.template.yaml
│ ├── templatify.js
│ ├── tsconfig.json
│ └── updateAddresses.js
└── yarn.lock
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | orbs:
4 | welcome: circleci/welcome-orb@0.4.1
5 |
6 | jobs:
7 | build:
8 | working_directory: ~/repo
9 | docker:
10 | - image: circleci/node:10.18.1
11 | steps:
12 | - checkout
13 | - run:
14 | name: 'Update NPM'
15 | command: sudo npm install -g npm@6.13.4
16 | - run:
17 | name: 'Update Yarn'
18 | command: yarn policies set-version 1.22.4
19 | - run:
20 | name: 'Set caching variables'
21 | command: |
22 | LAST_SUCCESSFUL_BUILD_URL="https://circleci.com/api/v1.1/project/github/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/tree/dev?filter=successful&limit=1"
23 | LAST_SUCCESSFUL_COMMIT=`curl -Ss -u "$CIRCLE_TOKEN:" $LAST_SUCCESSFUL_BUILD_URL | jq -r '.[0]["vcs_revision"]'`
24 | echo $LAST_SUCCESSFUL_COMMIT > /tmp/last-successful-commit
25 | echo $CIRCLE_SHA1 > /tmp/current-commit
26 | - restore_cache:
27 | keys:
28 | - build-cache-{{ .Branch }}-{{ checksum "/tmp/last-successful-commit" }}
29 | - build-cache-dev-{{ checksum "/tmp/last-successful-commit" }}
30 | - run:
31 | name: 'Install Dependencies'
32 | command: yarn install
33 | - run:
34 | name: 'Build Packages'
35 | command: yarn build
36 | - save_cache:
37 | key: repo-{{ .Environment.CIRCLE_SHA1 }}
38 | paths:
39 | - ~/repo
40 | - save_cache:
41 | key: build-cache-{{ .Branch }}-{{ checksum "/tmp/current-commit" }}
42 | paths:
43 | - ~/repo/packages/contract-artifacts/node_modules
44 | - ~/repo/packages/contract-artifacts/lib
45 | - ~/repo/packages/contracts/node_modules
46 | - ~/repo/packages/dev-utils/node_modules
47 | - ~/repo/packages/react-app/node_modules
48 | - ~/repo/packages/subgraph/node_modules
49 | test:
50 | working_directory: ~/repo
51 | docker:
52 | - image: circleci/node:10.18.1
53 | steps:
54 | - restore_cache:
55 | keys:
56 | - repo-{{ .Environment.CIRCLE_SHA1 }}
57 | - run:
58 | name: 'Test Packages'
59 | command: yarn test
60 |
61 | workflows:
62 | version: 2
63 | main:
64 | jobs:
65 | - build:
66 | filters:
67 | branches:
68 | ignore: gh-pages
69 | - test:
70 | requires:
71 | - build
72 | filters:
73 | branches:
74 | ignore: gh-pages
75 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # ignored directories
2 | node_modules/*
3 | /build/*
4 | /demo/*
5 | /lib/*
6 |
7 | # ignored file types
8 | **/*.json
9 | **/*.md
10 | **/*.lock
11 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'airbnb-base',
4 | ],
5 | parser: 'babel-eslint',
6 | env: {
7 | es6: true,
8 | },
9 | rules: {
10 | 'max-len': ['error', {
11 | code: 120,
12 | ignoreComments: true,
13 | ignoreTrailingComments: true,
14 | ignoreUrls: true,
15 | ignoreStrings: true,
16 | ignoreTemplateLiterals: true,
17 | ignoreRegExpLiterals: true,
18 | }],
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/.gitbook.yaml:
--------------------------------------------------------------------------------
1 | root: ./docs/
2 |
3 | structure:
4 | readme: README.md
5 | summary: SUMMARY.md
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: ["https://gitcoin.co/grants/733/notestream"]
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Additional context**
27 | Add any other context about the problem here.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | **/node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # production
12 | build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.*.local
18 |
19 | # debug
20 | npm-debug.log*
21 | yarn-debug.log*
22 | yarn-error.log*
23 |
24 | # subgraph
25 | /packages/subgraph/build/
26 | /packages/subgraph/src/types/
27 |
28 | # now
29 | .now
30 |
--------------------------------------------------------------------------------
/.huskyrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "hooks": {
3 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
4 | "pre-commit": "lerna run --concurrency 1 --stream precommit --since HEAD"
5 | }
6 | }
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 4,
4 | "semi": true,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@babel/preset-typescript',
4 | ['@babel/preset-env',
5 | {
6 | targets: {
7 | node: 'current',
8 | },
9 | },
10 | ],
11 | ],
12 | };
13 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | // prettier-ignore
2 | module.exports = {
3 | extends: [
4 | '@commitlint/config-conventional',
5 | ],
6 | };
7 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # Welcome to the NoteStream Docs
2 |
3 | If you are interested in how to use NoteStream to privately stream Ethereum tokens, then please look at our [Getting Started](./getting_started/README.md) page.
4 |
5 | # Github
6 |
7 | The codebase for the NoteStream contracts and frontend are hosted publicly on [Github](https://github.com/TomAFrench/NoteStream).
8 |
9 | # Networks
10 |
11 | As NoteStream is in rapid development, it is currently only deployed on the Rinkeby test network. We hope to deploy to other testnets and subsequently the Ethereum Mainnet in due time.
12 |
13 | # Gas Costs
14 |
15 | We have not measured the gas costs associated with using NoteStream in detail, however we expect the majority of the cost to be from validating the ZK proof required for all transactions using AZTEC Protocol. Since EIP 1108, this takes in the range of 200,000-300,000 gas which corresponds to roughly 5-6x that of a standard ERC20 token transfer.
--------------------------------------------------------------------------------
/docs/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 |
4 | * [Getting Started](getting_started/README.md)
5 | * [Using Aztec notes](using_aztec/README.md)
6 | * [Comparison to other money streaming options](comparison_to_others/README.md)
7 |
8 |
--------------------------------------------------------------------------------
/docs/comparison_to_others/README.md:
--------------------------------------------------------------------------------
1 | # Sablier
--------------------------------------------------------------------------------
/docs/getting_started/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 | ## Trade ERC20 tokens for ZkAssets
3 |
4 | Many of the tokens which you will want to stream are going to be ERC20 tokens such as DAI. These don't have the privacy features needed for NoteStream to work. Luckily we can wrap these tokens into an ZkAsset before we start streaming them.
5 | To do this click the "Deposit ERC20 tokens for private assets" and enter the number of tokens you want to convert into ZkAssets.
6 |
7 | ## Deposit a note into a stream
8 |
9 | You can create a stream by clicking the "Create a new stream" button and then following the shown instructions.
10 | It is important to note that the stream recipient must have registered for an AZTEC address in order for then to be able to receive a stream. This is done automatically upon first visiting the NoteStream website.
11 |
12 | ## Withdrawing from a stream
13 |
14 | The NoteStream app continually calculates the maximum amount which you can withdraw from the streams you are receiving. If you click the "withdraw" button next to the stream you want to withdraw from then a ZK proof will be generated to withdraw this amount from the stream note to your wallet.
15 |
16 | ## Converting back into ERC20 tokens
17 |
18 | Once you have withdrawn your ZkAssets, you can convert them back into ERC20 tokens in much the same way as converting ERC20s into ZkAssets.
19 | Of course, when you convert ZkAssets back into ERC20 tokens you lose the privacy properties given by AZTEC notes. There is also the possibility to leak information on the value of a stream if you immediately convert a withdrawal back into ERC20 tokens.
20 |
21 | # Terminology
22 | ## AZTEC Note
23 |
24 | AZTEC notes can be thought of as tokens on Ethereum for which all balances are encrypted so only their owners can view them.
25 | This is a gross oversimplification as these notes instead work on UTXO model (similar to Bitcoin) rather than then fungible balance model of ERC20 tokens which are all familiar with.
26 |
27 | ## ZkAsset
28 |
29 | A zero knowledge representation of an ERC20 token. For example: DAI is represented by the zkDAI ZkAsset.
30 |
31 | ## Stream Note
32 | The AZTEC note held by the NoteStream contract for a given stream. This note represents the total value of the stream at any time.
33 |
34 | # How it works
35 | ## Where is my money held?
36 |
37 | Each stream is made up of an AZTEC note locked on the NoteStream smart contract. The logic of this smart contract is such that only the stream's sender or receiver may interact with this note.
38 |
39 | ## How can my streams be private if everything on Ethereum is public?
40 |
41 | You're right that everything that happens on the Ethereum network is available for anyone to inspect, however NoteStream uses AZTEC Protocol which allows funds to be transferred as "notes" for which the value is encrypted. Everyone can see that a stream exists but nobody but you will know how much value it contains.
42 |
43 | # Interacting with NoteStream
44 | ## Can I cancel streams?
45 |
46 | Yes. Both the stream sender and recipient can cancel the stream at any time. This will send the appropriate fraction of the stream note's value to each party and then delete the stream.
47 | Can I modify a stream in progress?
48 | No. We're looking at the possibility to allow a stream's sender to modify a stream in progress in certain ways, e.g. extending the stream by topping up the stream note's value.
49 |
50 | # Privacy
51 |
52 | There are a number of privacy enhancing measures you can take using ZkAssets which are general rather than NoteStream-specific. Please see ["Using Aztec notes"](./using_aztec/README.md) for more information.
53 |
54 | ## NoteStream-specific public information
55 |
56 | There are two times at which information about the stream is made visible
57 |
58 | ### Creating a stream
59 |
60 | A stream is made up of the following information:
61 | - Sender address
62 | - Recipent address
63 | - Stream note hash
64 | - ZkAsset address
65 | - Start Time
66 | - Stop Time
67 |
68 | An observer will then be able to see who is streaming to whom, what kind of token they are streaming and when this stream occurred. e.g.
69 | > Alice streamed Bob an unknown amount of zkDAI represented by the AZTEC note with hash 0x1a3...cE1 from 9:00am until 5:00pm on 12/4/20
70 |
71 | ### Withdrawing/cancelling a stream
72 |
73 | Withdrawal and cancellation transactions leak the same information. Here we discuss a withdrawal transaction as an example.
74 |
75 | Each withdrawal transaction includes information on the fraction of the stream's duration which is being withdrawn. This is required such that the NoteStream contract can ensure that the withdrawal is valid.
76 | An observer may then for example see that the recipient is withdrawing a value corresponding to a certain fraction of the remaining value on the stream note.
77 |
78 | However it is important to note that without knowledge of the initial value of the stream note then it is impossible to determine the absolute value being withdrawn. e.g.
79 |
80 | > Bob withdrew 50% of the value of the stream at 1:00pm on 12/4/20
81 |
82 |
83 | # Security
84 | ## Is NoteStream safe?
85 | Currently there are a number of known security flaws which mean that NoteStream should not be used for any Mainnet funds (as such, there is no current Mainnet deployment.). I'm currently speaking with AZTEC about updates to their SDK in order to fix these.
86 |
87 | ## How do I know you can't steal my funds?
88 |
89 | All Notestream contracts are open source and verified on Etherscan.
--------------------------------------------------------------------------------
/docs/using_aztec/README.md:
--------------------------------------------------------------------------------
1 | # Issues associated with depositing/withdrawing ERC20 tokens
2 |
3 | An important factor to keep in mind is that the process of depositing ERC20s into a ZkAsset doesn't immediately make them private, i.e. there will be a transaction visible on the blockchain in which a certain amount of DAI is converted into a number of zkDAI notes.
4 | It's impossible to tell what each individual note is worth but the sum of them must equal the number of ERC20s deposited. In the worst case scenario, if all of those notes are then used in a single transaction (such as creation of a NoteStream stream) then it's obvious that the transaction value is equal to that of the ERC20 deposit.
5 |
6 | This might sound like it means that it's impossible to have privacy using ZkAssets as anyone can trace your notes back to when they were deposited. However as people send ZkAssets to each other and notes are split and joined, a given deposit may be linked to a huge amount of notes spread over a vast number of people. We're very quickly at a point where we can see that 1000 people all together own the value from a given deposit but it's impossible to work out exactly who owns what fraction.
7 |
8 | ## Improving privacy of deposits
9 |
10 | Even before this mixing behaviour there are steps you can take to improve your privacy. When depositing ERC20s into a ZkAsset its possible to create a number of notes which have zero value attached. This might sound pointless but it allows you then spend your entire deposit without letting anyone know how much you've spent.
11 |
12 | An observer will only be able to tell that your stream is worth at most equal to your deposit but it could be anything less than that.
13 | This behaviour is implemented automatically by the AZTEC sdk so you don't need to worry about it.
14 |
15 | ## Take aways
16 |
17 | In order to improve the privacy of your transactions using ZkAssets it is best to
18 |
19 | - Have a long history of transactions using this ZkAsset since your last deposit (idealling receiving ZkAsset funds from other people as well)
20 | - Deposit an amount of ERC20 tokens in excess of what you are planning on immediately streaming.
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "lerna": "3.13.1",
3 | "packages": [
4 | "packages/*"
5 | ],
6 | "version": "independent",
7 | "command": {
8 | "publish": {
9 | "ignoreChanges": [
10 | "*.md",
11 | "lib",
12 | "scripts",
13 | "test/**/*"
14 | ]
15 | }
16 | },
17 | "npmClient": "yarn",
18 | "useWorkspaces": true
19 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@notestream/monorepo",
3 | "version": "1.0.0",
4 | "keywords": [
5 | "ethereum",
6 | "react",
7 | "workspaces",
8 | "yarn"
9 | ],
10 | "private": true,
11 | "scripts": {
12 | "pre-commit": "lint-staged",
13 | "build": "lerna link && yarn wsrun --package $PKG --recursive --stages -c build",
14 | "clean": "yarn wsrun --package $PKG --parallel -c clean",
15 | "clean:node_modules": "lerna clean --yes; shx rm -rf node_modules",
16 | "commit": "git-cz",
17 | "contracts:compile": "yarn workspace @notestream/contracts compile",
18 | "contracts:deploy": "yarn workspace @notestream/contracts deploy",
19 | "contracts:test": "yarn workspace @notestream/contracts test",
20 | "react-app:build": "yarn workspace @notestream/react-app build",
21 | "react-app:eject": "yarn workspace @notestream/react-app eject",
22 | "react-app:start": "yarn workspace @notestream/react-app start",
23 | "react-app:test": "yarn workspace @notestream/react-app test",
24 | "subgraph:auth": "yarn workspace @notestream/subgraph auth",
25 | "subgraph:codegen": "yarn workspace @notestream/subgraph codegen",
26 | "subgraph:build": "yarn workspace @notestream/subgraph build",
27 | "subgraph:deploy": "yarn workspace @notestream/subgraph deploy",
28 | "test": "yarn wsrun --package $PKG --serial -c --if has:changed --ifDependency test",
29 | "wsrun": "wsrun --exclude-missing --fast-exit"
30 | },
31 | "workspaces": {
32 | "packages": [
33 | "packages/*"
34 | ],
35 | "nohoist": [
36 | "**/@graphprotocol/graph-ts",
37 | "**/@graphprotocol/graph-ts/**"
38 | ]
39 | },
40 | "devDependencies": {
41 | "@commitlint/cli": "^8.3.5",
42 | "@commitlint/config-conventional": "^8.3.4",
43 | "commitizen": "^4.0.4",
44 | "husky": "^4.2.5",
45 | "lerna": "^3.20.2",
46 | "now": "^18.0.0",
47 | "wsrun": "^5.2.0"
48 | },
49 | "config": {
50 | "commitizen": {
51 | "path": "./node_modules/cz-conventional-changelog"
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | "extends": [
3 | '../../.eslintrc.js',
4 | "plugin:@typescript-eslint/recommended",
5 | "plugin:@typescript-eslint/recommended-requiring-type-checking",
6 | "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
7 | "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
8 | ],
9 | "env": {
10 | "es6": true,
11 | "browser": true
12 | },
13 | "parser": "@typescript-eslint/parser",
14 | "parserOptions": {
15 | "project": "./tsconfig.json",
16 | "tsconfigRootDir": __dirname,
17 | "sourceType": "module"
18 | },
19 | "plugins": [
20 | "@typescript-eslint",
21 | ],
22 | "rules": {
23 | "import/extensions": [
24 | "error",
25 | "ignorePackages",
26 | {
27 | "js": "never",
28 | "ts": "never"
29 | }
30 | ]
31 | },
32 | "settings": {
33 | 'import/resolver': {
34 | node: {
35 | extensions: ['.js', '.ts']
36 | },
37 | },
38 | }
39 | };
40 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/.gitignore:
--------------------------------------------------------------------------------
1 | lib
--------------------------------------------------------------------------------
/packages/contract-artifacts/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.ts": [
3 | "eslint --fix"
4 | ]
5 | }
--------------------------------------------------------------------------------
/packages/contract-artifacts/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | trailingComma: "all",
4 | singleQuote: true,
5 | tabWidth: 2
6 | };
--------------------------------------------------------------------------------
/packages/contract-artifacts/addresses/rinkeby.json:
--------------------------------------------------------------------------------
1 | {
2 | "ACE": "0x065178E11D516D115eA9437336f8d1bF4178f48c",
3 | "NoteStream": "0xCcb98Efa4eA6a3814ece095f73264c43D7D50071"
4 | }
5 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/contracts/StreamUtilities.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | contractName: 'StreamUtilities',
3 | abi: [],
4 | bytecode:
5 | '0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820b0c8047152ae625605cc7c7239b8e424dfb7a37caeb5490776c10883d23299b664736f6c634300050f0032',
6 | deployedBytecode:
7 | '0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820b0c8047152ae625605cc7c7239b8e424dfb7a37caeb5490776c10883d23299b664736f6c634300050f0032',
8 | linkReferences: {},
9 | deployedLinkReferences: {},
10 | };
11 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/contracts/Types.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | contractName: 'Types',
3 | abi: [],
4 | bytecode:
5 | '0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820c6de8fa01af98cbb93ea48dee56a2beaa2f6e7cace3b23b6e79c686855a1cb6064736f6c634300050f0032',
6 | deployedBytecode:
7 | '0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820c6de8fa01af98cbb93ea48dee56a2beaa2f6e7cace3b23b6e79c686855a1cb6064736f6c634300050f0032',
8 | linkReferences: {},
9 | deployedLinkReferences: {},
10 | };
11 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/contracts/contracts.ts:
--------------------------------------------------------------------------------
1 | export default ['NoteStream', 'StreamUtilities', 'Types'];
2 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@notestream/contract-artifacts",
3 | "description": "Addresses of deployed AZTEC contracts on Ethereum mainnet and testnets",
4 | "version": "0.2.0",
5 | "author": "Tom French",
6 | "bugs": {
7 | "url": "https://github.com/TomAFrench/NoteStream/issues"
8 | },
9 | "devDependencies": {
10 | "@babel/cli": "^7.4.3",
11 | "@babel/core": "^7.4.0",
12 | "@babel/plugin-proposal-object-rest-spread": "^7.4.0",
13 | "@babel/preset-env": "^7.9.0",
14 | "@babel/preset-typescript": "^7.9.0",
15 | "@typescript-eslint/eslint-plugin-tslint": "^2.27.0",
16 | "eslint": "^5.15.3",
17 | "eslint-config-airbnb-base": "^13.1.0",
18 | "eslint-config-prettier": "^6.0.0",
19 | "eslint-plugin-import": "^2.20.2",
20 | "lint-staged": "^10.2.2",
21 | "shx": "^0.3.2",
22 | "typescript": "^3.8.3"
23 | },
24 | "engines": {
25 | "node": ">=8.3"
26 | },
27 | "files": [
28 | "/abis",
29 | "/addresses",
30 | "/lib"
31 | ],
32 | "homepage": "https://github.com/TomAFrench/NoteStream#readme",
33 | "keywords": [
34 | "aztec",
35 | "blockchain",
36 | "confidentiality",
37 | "cryptography",
38 | "ethereum",
39 | "privacy"
40 | ],
41 | "license": "LGPL-3.0",
42 | "main": "./lib",
43 | "repository": {
44 | "type": "git",
45 | "url": "git+https://github.com/TomAFrench/NoteStream.git"
46 | },
47 | "scripts": {
48 | "precommit": "lint-staged",
49 | "commit": "git-cz",
50 | "prepare": "yarn clean && yarn lint --fix",
51 | "build": "yarn prepare && yarn build:types && yarn build:js",
52 | "build:js": " babel src --out-dir lib --extensions '.ts,.tsx' --root-mode upward ./src",
53 | "build:types": "tsc --emitDeclarationOnly",
54 | "clean": "shx rm -rf ./lib",
55 | "has:changed": "bash ../monorepo-scripts/ci/hasChanged.sh contract-artifacts",
56 | "lint": "eslint --config .eslintrc.js --ext .js,.ts . ",
57 | "watch": "yarn build --watch"
58 | },
59 | "config": {
60 | "commitizen": {
61 | "path": "./node_modules/cz-conventional-changelog"
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/src/addresses.ts:
--------------------------------------------------------------------------------
1 | // import mainnetAddresses from "../addresses/mainnet.json";
2 | import rinkebyAddresses from '../addresses/rinkeby.json';
3 |
4 | export type Address = string;
5 |
6 | export interface Deployment {
7 | ACE: Address;
8 | NoteStream: Address;
9 | }
10 |
11 | /**
12 | * Used to get addresses of contracts that have been deployed to either the
13 | * Ethereum mainnet or a supported testnet. Throws if there are no known
14 | * contracts deployed on the corresponding network.
15 | * @param networkId The desired networkId.
16 | * @returns The set of addresses for contracts which have been deployed on the
17 | * given networkId.
18 | */
19 | const getContractAddressesForNetwork = (networkId: number): Deployment => {
20 | switch (networkId) {
21 | // case 1:
22 | // return mainnetAddresses;
23 | case 4:
24 | return rinkebyAddresses;
25 | default:
26 | throw new Error(
27 | `Unknown network id (${networkId}). No known NoteStream contracts have been deployed on this network.`,
28 | );
29 | }
30 | };
31 |
32 | export default getContractAddressesForNetwork;
33 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/src/artifacts.ts:
--------------------------------------------------------------------------------
1 | import NoteStream from '../contracts/NoteStream';
2 | import StreamUtilities from '../contracts/StreamUtilities';
3 | import Types from '../contracts/Types';
4 |
5 | export default {
6 | NoteStream,
7 | StreamUtilities,
8 | Types,
9 | };
10 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/src/index.ts:
--------------------------------------------------------------------------------
1 | export { default as artifacts } from './artifacts';
2 | export { default as getContractAddressesForNetwork } from './addresses';
3 |
--------------------------------------------------------------------------------
/packages/contract-artifacts/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Basic Options */
4 | "lib": ["ES2015", "DOM"],
5 | "module": "ES2015",
6 | "outDir": "lib",
7 | "sourceMap": true,
8 | "target": "ES2015",
9 | "declaration": true,
10 | /* Strict Type-Checking Options */
11 | "noImplicitAny": true,
12 | "strict": true,
13 | /* Module Resolution Options */
14 | "esModuleInterop": true,
15 | "moduleResolution": "node",
16 | "resolveJsonModule": true,
17 | "skipLibCheck": false,
18 | /* Advanced Options */
19 | "forceConsistentCasingInFileNames": true
20 | },
21 | "include": ["./src/**/*", "./contracts/**/*", "./lib/**/*"]
22 | }
23 |
--------------------------------------------------------------------------------
/packages/contracts/.env.development:
--------------------------------------------------------------------------------
1 | TESTING_ACCOUNT=0x4EA13A06F40EBAE073F8BCE58A504C6FD95DE00F958BC1D7FCD8D97E33AE9215
2 | TESTING_ACCOUNT_ADDRESS=0xcF217475D84997E9c0EbA3052E1F818916fE3eEC
3 | TESTING_ACCOUNT_MNEMONIC=system box custom picture wonder across logic love program pyramid position plunge
4 | INFURA_API_KEY=eca546af737a406487d1e844a99d7955
5 |
--------------------------------------------------------------------------------
/packages/contracts/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | '../../.eslintrc.js',
4 | 'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
5 | ],
6 | env: {
7 | mocha: true,
8 | },
9 | rules: {
10 | 'import/extensions': [
11 | 'error',
12 | 'ignorePackages',
13 | {
14 | js: 'never',
15 | ts: 'never',
16 | },
17 | ],
18 | 'import/no-extraneous-dependencies': [
19 | 'error',
20 | { devDependencies: ['**/*.js'] },
21 | ],
22 | },
23 | overrides: [
24 | {
25 | files: ['test/**/*.js'],
26 | rules: {
27 | 'func-names': 'off',
28 | },
29 | },
30 | {
31 | files: ['scripts/**/*.js'],
32 | rules: {
33 | 'no-console': 'off',
34 | },
35 | },
36 | ],
37 | };
38 |
--------------------------------------------------------------------------------
/packages/contracts/.gitattributes:
--------------------------------------------------------------------------------
1 | *.sol linguist-language=Solidity
--------------------------------------------------------------------------------
/packages/contracts/.gitignore:
--------------------------------------------------------------------------------
1 | #Buidler files
2 | cache
3 | artifacts
4 |
--------------------------------------------------------------------------------
/packages/contracts/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.js": [
3 | "eslint --fix"
4 | ]
5 | }
--------------------------------------------------------------------------------
/packages/contracts/README.md:
--------------------------------------------------------------------------------
1 | ## @notestream/contracts
2 |
3 | A minimalist, opinionated structure for managing smart contract ABIs and addresses.
4 |
5 | [Read more about Application Binary Interfaces (ABIs) here](https://ethereum.stackexchange.com/questions/234/what-is-an-abi-and-why-is-it-needed-to-interact-with-contracts).
6 |
--------------------------------------------------------------------------------
/packages/contracts/buidler.config.js:
--------------------------------------------------------------------------------
1 | const { usePlugin, task } = require('@nomiclabs/buidler/config');
2 | const { exportContracts } = require('./tasks/export.js');
3 |
4 | usePlugin('@nomiclabs/buidler-waffle');
5 | usePlugin('@nomiclabs/buidler-etherscan');
6 | require('dotenv').config({ path: '.env.development' });
7 |
8 | task('export', 'Exports the contract ABIs').setAction(async (args, bre) => {
9 | exportContracts(bre);
10 | });
11 |
12 | module.exports = {
13 | solc: {
14 | version: '0.5.15',
15 | optimizer: {
16 | enabled: true,
17 | runs: 200,
18 | },
19 | evmVersion: 'istanbul',
20 | },
21 | paths: {
22 | artifacts: './build',
23 | },
24 | // contracts_build_directory: "./build",
25 | mocha: {
26 | bail: true,
27 | enableTimeouts: false,
28 | reporter: 'spec',
29 | },
30 | networks: {
31 | rinkeby: {
32 | url: `https://rinkeby.infura.io/v3/${process.env.INFURA_API_KEY}`,
33 | chainId: 4,
34 | from: process.env.TESTING_ACCOUNT_ADDRESS,
35 | accounts: [process.env.TESTING_ACCOUNT],
36 | // gas: 5500000,
37 | gasPrice: 10000000000,
38 | },
39 | },
40 | etherscan: {
41 | url: 'https://api-rinkeby.etherscan.io/api',
42 | apiKey: process.env.ETHERSCAN_API_KEY,
43 | },
44 | };
45 |
--------------------------------------------------------------------------------
/packages/contracts/contracts/AZTEC/Imports.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.11;
2 |
3 | import "@aztec/protocol/contracts/ACE/ACE.sol";
4 | import "@aztec/protocol/contracts/ACE/noteRegistry/epochs/201912/base/FactoryBase201912.sol";
5 | import "@aztec/protocol/contracts/ACE/validators/joinSplit/JoinSplit.sol";
6 | import "@aztec/protocol/contracts/ACE/validators/dividend/Dividend.sol";
7 | import "@aztec/protocol/contracts/ERC1724/ZkAsset.sol";
8 |
9 |
10 | // You might think this file is a bit odd, but let me explain.
11 | // We only use some contracts in our tests, which means Truffle
12 | // will not compile it for us, because it is from an external
13 | // dependency.
14 | //
15 | // We are now left with three options:
16 | // - Copy/paste these contracts
17 | // - Run the tests with `truffle compile --all` on
18 | // - Or trick Truffle by claiming we use it in a Solidity test
19 | //
20 | // You know which one I went for.
21 |
22 | contract Imports {
23 | constructor() public {}
24 | }
25 |
--------------------------------------------------------------------------------
/packages/contracts/contracts/Types.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.11;
2 |
3 |
4 | /**
5 | * @title NoteStream Types
6 | * @author NoteStream
7 | */
8 | library Types {
9 | struct AztecStream {
10 | bytes32 noteHash;
11 | uint256 startTime;
12 | uint256 lastWithdrawTime;
13 | uint256 stopTime;
14 | address recipient;
15 | address sender;
16 | address tokenAddress;
17 | bool isEntity;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/packages/contracts/contracts/mocks/StreamUtilitiesMock.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.11;
2 | pragma experimental ABIEncoderV2;
3 |
4 | import "../StreamUtilities.sol";
5 |
6 |
7 | contract StreamUtilitiesMock {
8 |
9 | // The provided struct object is stored here as StreamUtilities expects a storage variable.
10 | Types.AztecStream public stream;
11 |
12 | function getRatio(bytes memory _proofData)
13 | public
14 | pure
15 | returns (uint256 ratio)
16 | {
17 | return StreamUtilities.getRatio(_proofData);
18 | }
19 |
20 | function validateRatioProof(
21 | address _aceContractAddress,
22 | bytes memory _proof1,
23 | uint256 _withdrawDuration,
24 | Types.AztecStream memory _stream
25 | )
26 | public
27 | returns (bytes memory, bytes memory)
28 | {
29 | stream = _stream;
30 | return StreamUtilities._validateRatioProof(_aceContractAddress, _proof1, _withdrawDuration, stream);
31 | }
32 |
33 | function validateJoinSplitProof(
34 | address _aceContractAddress,
35 | bytes memory _proof2,
36 | bytes32 _withdrawalNoteHash,
37 | Types.AztecStream memory _stream
38 | ) public returns (bytes memory proof2Outputs) {
39 | stream = _stream;
40 | return StreamUtilities._validateJoinSplitProof(_aceContractAddress, _proof2, _withdrawalNoteHash, stream);
41 | }
42 |
43 | function processWithdrawal(
44 | address _aceContractAddress,
45 | bytes memory _proof2,
46 | bytes memory _proof1OutputNotes,
47 | Types.AztecStream memory _stream
48 | ) public returns (bytes32) {
49 | stream = _stream;
50 | return StreamUtilities._processWithdrawal(_aceContractAddress, _proof2, _proof1OutputNotes, stream);
51 | }
52 |
53 | function processCancelation(
54 | address _aceContractAddress,
55 | bytes memory _proof2,
56 | bytes memory _proof1OutputNotes,
57 | Types.AztecStream memory _stream
58 | ) public returns (bool) {
59 | stream = _stream;
60 | return StreamUtilities._processCancelation(_aceContractAddress, _proof2, _proof1OutputNotes, stream);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/packages/contracts/contracts/test/ERC20Mintable.sol:
--------------------------------------------------------------------------------
1 | pragma solidity =0.5.15;
2 |
3 | import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
4 | import "@openzeppelin/contracts/token/ERC20/ERC20Detailed.sol";
5 |
6 | /**
7 | * @title ERC20Mintable
8 | * @dev ERC20 minting logic
9 | * Sourced from OpenZeppelin and thoroughly butchered to remove security guards.
10 | * Anybody can mint - STRICTLY FOR TEST PURPOSES
11 | */
12 | contract ERC20Mintable is ERC20, ERC20Detailed {
13 |
14 | /**
15 | * @dev Sets the values for {name} and {symbol} and {decimals}
16 | *
17 | * All three of these values are immutable: they can only be set once during
18 | * construction.
19 | */
20 | constructor (string memory name, string memory symbol, uint8 decimals) public ERC20Detailed(name,symbol, decimals){}
21 |
22 | /**
23 | * @dev Function to mint tokens
24 | * @param _to The address that will receive the minted tokens.
25 | * @param _value The amount of tokens to mint.
26 | * @return A boolean that indicates if the operation was successful.
27 | */
28 | function mint(address _to, uint256 _value) public returns (bool) {
29 | _mint(_to, _value);
30 | return true;
31 | }
32 | }
--------------------------------------------------------------------------------
/packages/contracts/contracts/test/Imports.sol:
--------------------------------------------------------------------------------
1 | pragma solidity ^0.5.11;
2 |
3 | import "@aztec/protocol/contracts/ACE/noteRegistry/epochs/201912/base/FactoryBase201912.sol";
4 | import "@aztec/protocol/contracts/ACE/ACE.sol";
5 | import "@aztec/protocol/contracts/ACE/validators/joinSplit/JoinSplit.sol";
6 | import "@aztec/protocol/contracts/ACE/validators/dividend/Dividend.sol";
7 |
8 | // You might think this file is a bit odd, but let me explain.
9 | // We only use some contracts in our tests, which means Truffle
10 | // will not compile it for us, because it is from an external
11 | // dependency.
12 | //
13 | // We are now left with three options:
14 | // - Copy/paste these contracts
15 | // - Run the tests with `truffle compile --all` on
16 | // - Or trick Truffle by claiming we use it in a Solidity test
17 | //
18 | // You know which one I went for.
19 |
20 | contract Imports {
21 | constructor() public {}
22 | }
23 |
--------------------------------------------------------------------------------
/packages/contracts/env.js:
--------------------------------------------------------------------------------
1 | import path from 'path';
2 | import fs from 'fs';
3 | import dotenv from 'dotenv';
4 |
5 | if (!process.env.NODE_ENV) {
6 | process.env.NODE_ENV = 'development';
7 | }
8 |
9 | const { NODE_ENV } = process.env;
10 | const prefix = path.resolve(__dirname, './.env');
11 | const dotenvFiles = [
12 | `${prefix}.${NODE_ENV}.local`,
13 | `${prefix}.${NODE_ENV}`,
14 | prefix,
15 | ].filter(Boolean);
16 |
17 | dotenvFiles.forEach((dotenvFile) => {
18 | if (fs.existsSync(dotenvFile)) {
19 | dotenv.config({ path: dotenvFile });
20 | }
21 | });
22 |
--------------------------------------------------------------------------------
/packages/contracts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@notestream/contracts",
3 | "version": "0.1.0",
4 | "description": "NoteStream contracts",
5 | "main": "./src/index.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/TomAFrench/NoteStream.git"
9 | },
10 | "author": "Tom French",
11 | "license": "ISC",
12 | "bugs": {
13 | "url": "https://github.com/TomAFrench/NoteStream/issues"
14 | },
15 | "homepage": "https://github.com/TomAFrench/NoteStream#readme",
16 | "scripts": {
17 | "precommit": "lint-staged",
18 | "commit": "git-cz",
19 | "compile": "buidler compile",
20 | "clean": "buidler clean",
21 | "deploy": "buidler run scripts/deploy.js",
22 | "export": "buidler export",
23 | "has:changed": "bash ../monorepo-scripts/ci/hasChanged.sh contracts",
24 | "test": "buidler test test/runTests.js",
25 | "lint:js": "eslint --config .eslintrc.js ./scripts ./test"
26 | },
27 | "files": [
28 | "/contracts"
29 | ],
30 | "devDependencies": {
31 | "@aztec/bn128": "^1.3.2",
32 | "@aztec/contract-addresses": "1.16.1",
33 | "@aztec/contract-artifacts": "^1.22.0",
34 | "@aztec/dev-utils": "^2.3.1",
35 | "@aztec/protocol": "^1.7.0",
36 | "@nomiclabs/buidler": "^1.3.3",
37 | "@nomiclabs/buidler-ethers": "^1.3.3",
38 | "@nomiclabs/buidler-etherscan": "^1.3.3",
39 | "@nomiclabs/buidler-waffle": "^1.3.3",
40 | "@notestream/dev-utils": "^0.1.0",
41 | "@openzeppelin/contracts": "^2.5.0",
42 | "@openzeppelin/upgrades": "^2.8.0",
43 | "chai": "^4.2.0",
44 | "chalk": "^4.0.0",
45 | "crypto": "^1.0.1",
46 | "dotenv": "^8.2.0",
47 | "eslint": "^7.0.0",
48 | "eslint-config-airbnb": "^18.1.0",
49 | "eslint-config-prettier": "^6.11.0",
50 | "eslint-plugin-prettier": "^3.1.3",
51 | "ethereum-waffle": "^2.5.0",
52 | "ethers": "^4.0.47",
53 | "lint-staged": "^10.2.2",
54 | "moment": "^2.24.0"
55 | },
56 | "config": {
57 | "commitizen": {
58 | "path": "./node_modules/cz-conventional-changelog"
59 | }
60 | },
61 | "dependencies": {
62 | "@aztec/protocol": "^1.7.0"
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/packages/contracts/scripts/deploy.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const env = require('@nomiclabs/buidler');
3 | const { getContractAddressesForNetwork } = require('@aztec/contract-addresses');
4 | const bn128 = require('@aztec/bn128');
5 | const { proofs } = require('@aztec/dev-utils');
6 |
7 | const fs = require('fs');
8 | const path = require('path');
9 | const chalk = require('chalk');
10 |
11 | const addressDirectory = path.resolve(
12 | __dirname,
13 | '../../contract-artifacts/addresses/'
14 | );
15 |
16 | const TESTING_ADDRESS = '0xC6E67ee008a7720722e42F34f30a16d806A45c3F';
17 |
18 | async function deployAZTEC() {
19 | process.stdout.write(`Deploying ${chalk.cyan('ACE')}...\r`);
20 | const ACE = env.artifacts.require('ACE');
21 | const ace = await ACE.new();
22 | console.log(
23 | `Deployed ${chalk.cyan('ACE')} to ${chalk.yellow(ace.address)}`
24 | );
25 |
26 | console.log('Setting CRS');
27 | await ace.setCommonReferenceString(bn128.CRS);
28 |
29 | const { JOIN_SPLIT_PROOF, DIVIDEND_PROOF } = proofs;
30 |
31 | process.stdout.write(
32 | `Deploying ${chalk.cyan('JoinSplit validator contract')}...\r`
33 | );
34 | const JoinSplitValidator = env.artifacts.require('./JoinSplit');
35 | const joinSplitValidator = await JoinSplitValidator.new();
36 | await ace.setProof(JOIN_SPLIT_PROOF, joinSplitValidator.address);
37 | console.log(
38 | `Deployed ${chalk.cyan(
39 | 'JoinSplit validator contract'
40 | )} to ${chalk.yellow(joinSplitValidator.address)}`
41 | );
42 | process.stdout.write(
43 | `Deploying ${chalk.cyan('Dividend validator contract')}...\r`
44 | );
45 | const DividendValidator = env.artifacts.require('./Dividend');
46 | const dividendValidator = await DividendValidator.new();
47 | console.log(
48 | `Deployed ${chalk.cyan(
49 | 'Dividend validator contract'
50 | )} to ${chalk.yellow(dividendValidator.address)}`
51 | );
52 | await ace.setProof(DIVIDEND_PROOF, dividendValidator.address);
53 |
54 | const generateFactoryId = (epoch, cryptoSystem, assetType) =>
55 | epoch * 256 ** 2 + cryptoSystem * 256 ** 1 + assetType * 256 ** 0;
56 |
57 | process.stdout.write(`Deploying ${chalk.cyan('Note Registry')}...\r`);
58 | const BaseFactory = env.artifacts.require(
59 | './noteRegistry/epochs/201912/base/FactoryBase201912'
60 | );
61 | const baseFactory = await BaseFactory.new(ace.address);
62 | console.log(
63 | `Deployed ${chalk.cyan('Note Registry')} to ${chalk.yellow(
64 | baseFactory.address
65 | )}`
66 | );
67 | await ace.setFactory(generateFactoryId(1, 1, 1), baseFactory.address);
68 |
69 | return ace;
70 | }
71 |
72 | async function deployZkAsset(aceAddress) {
73 | process.stdout.write(`Deploying ${chalk.cyan('ERC20')}...\r`);
74 | const ERC20Mintable = env.artifacts.require('ERC20Mintable');
75 | const erc20Mintable = await ERC20Mintable.new('TESTCOIN', 'TEST', 18);
76 | await erc20Mintable.mint(TESTING_ADDRESS, '100000');
77 | console.log(
78 | `Deployed ${chalk.cyan('Note Registry')} to ${chalk.yellow(
79 | erc20Mintable.address
80 | )}`
81 | );
82 |
83 | // Deploy a ZkAsset linked to this ERC20
84 | process.stdout.write(`Deploying ${chalk.cyan('ZkAsset')}...\r`);
85 | const ZkAsset = env.artifacts.require('ZkAsset');
86 | const zkAsset = await ZkAsset.new(aceAddress, erc20Mintable.address, 1);
87 | console.log(
88 | `Deployed ${chalk.cyan('ZkAsset')} to ${chalk.yellow(zkAsset.address)}`
89 | );
90 |
91 | return zkAsset;
92 | }
93 |
94 | function saveDeployedAddresses(addresses) {
95 | fs.writeFileSync(
96 | path.resolve(addressDirectory, `${env.network.name}.json`),
97 | JSON.stringify(addresses, null, 2)
98 | );
99 | }
100 |
101 | async function main() {
102 | console.log();
103 | // Read the address of the ACE contract on chosen network
104 | const networkId = env.network.config.chainId;
105 | const addresses = {};
106 |
107 | try {
108 | addresses.ACE = getContractAddressesForNetwork(networkId).ACE;
109 | console.log(
110 | `Using existing ${chalk.cyan('ACE')} at ${chalk.yellow(
111 | addresses.ACE
112 | )}`
113 | );
114 | } catch (e) {
115 | // throw new Error("Unsupported Network")
116 | console.log('This network is unsupported by AZTEC');
117 |
118 | // Assume we're in BuidlerEVM/Ganache
119 | // We need to deploy ACE and a ZkAsset
120 | const ace = await deployAZTEC();
121 | addresses.ACE = ace.address;
122 |
123 | const zkAsset = await deployZkAsset(addresses.ACE);
124 | addresses.ZkAsset = zkAsset.address;
125 | }
126 |
127 | process.stdout.write(`Deploying ${chalk.cyan('NoteStream')}...\r`);
128 | const NoteStream = env.artifacts.require('NoteStream');
129 | const noteStream = await NoteStream.new(addresses.ACE);
130 | addresses.NoteStream = noteStream.address;
131 |
132 | console.log(
133 | `Deployed ${chalk.cyan('NoteStream')} to ${chalk.yellow(
134 | noteStream.address
135 | )}`
136 | );
137 |
138 | // Write deployed addresses to file
139 | saveDeployedAddresses(addresses);
140 | }
141 |
142 | // We recommend this pattern to be able to use async/await everywhere
143 | // and properly handle errors.
144 | main()
145 | .then(() => process.exit(0))
146 | .catch((error) => {
147 | console.error(error);
148 | process.exit(1);
149 | });
150 |
--------------------------------------------------------------------------------
/packages/contracts/scripts/deployZkAsset.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-console */
2 | const env = require('@nomiclabs/buidler');
3 | const { getContractAddressesForNetwork } = require('@aztec/contract-addresses');
4 |
5 | const chalk = require('chalk');
6 |
7 | const erc20Address = '0x022E292b44B5a146F2e8ee36Ff44D3dd863C915c';
8 |
9 | async function main() {
10 | console.log();
11 | const ethers = await env.ethers;
12 | // Read the address of the ACE contract on chosen network
13 | const networkId = env.network.config.chainId;
14 |
15 | const aceAddress = getContractAddressesForNetwork(networkId).ACE;
16 | console.log(
17 | `Using existing ${chalk.cyan('ACE')} at ${chalk.yellow(aceAddress)}`
18 | );
19 |
20 | process.stdout.write(`Deploying ${chalk.cyan('ZkAsset')}...\r`);
21 | const ZkAsset = await ethers.getContractFactory('ZkAsset');
22 | const zkAsset = await ZkAsset.deploy(
23 | aceAddress,
24 | erc20Address,
25 | '10000000000000000'
26 | );
27 | await zkAsset.deployed();
28 |
29 | console.log(
30 | `Deployed ${chalk.cyan('ZkAsset')} to ${chalk.yellow(zkAsset.address)}`
31 | );
32 | }
33 |
34 | // We recommend this pattern to be able to use async/await everywhere
35 | // and properly handle errors.
36 | main()
37 | .then(() => process.exit(0))
38 | .catch((error) => {
39 | console.error(error);
40 | process.exit(1);
41 | });
42 |
--------------------------------------------------------------------------------
/packages/contracts/tasks/export.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const chalk = require('chalk');
4 | // const bre = require('@nomiclabs/buidler');
5 |
6 | const publishDir = path.resolve(
7 | __dirname,
8 | '../../contract-artifacts/contracts/'
9 | );
10 |
11 | async function exportContracts(bre) {
12 | const contractDir = bre.config.paths.sources;
13 | const artifactsDir = bre.config.paths.artifacts;
14 | if (!fs.existsSync(publishDir)) {
15 | fs.mkdirSync(publishDir);
16 | }
17 | const finalContractList = [];
18 | fs.readdirSync(contractDir).forEach((file) => {
19 | if (file.indexOf('.sol') >= 0) {
20 | const contractName = file.replace('.sol', '');
21 | console.log(
22 | 'Publishing',
23 | chalk.cyan(contractName),
24 | 'to',
25 | chalk.yellow(publishDir)
26 | );
27 | try {
28 | const contract = fs
29 | .readFileSync(
30 | path.resolve(artifactsDir, `${contractName}.json`)
31 | )
32 | .toString();
33 | fs.writeFileSync(
34 | `${publishDir}/${contractName}.ts`,
35 | `export default ${contract}`
36 | );
37 | finalContractList.push(contractName);
38 | } catch (e) {
39 | console.log(e);
40 | }
41 | }
42 | });
43 | fs.writeFileSync(
44 | `${publishDir}/contracts.ts`,
45 | `export default ${JSON.stringify(finalContractList)}`
46 | );
47 | }
48 |
49 | module.exports = { exportContracts };
50 |
--------------------------------------------------------------------------------
/packages/contracts/test/NoteStream/constructor.js:
--------------------------------------------------------------------------------
1 | const { waffle } = require('@nomiclabs/buidler');
2 | const { use, expect } = require('chai');
3 | const { solidity, deployContract } = require('ethereum-waffle');
4 |
5 | const { devConstants } = require('@notestream/dev-utils');
6 | const NoteStream = require('../../build/NoteStream.json');
7 |
8 | const { ZERO_ADDRESS } = devConstants;
9 |
10 | use(solidity);
11 |
12 | describe('NoteStream - constructor', function () {
13 | const { provider } = waffle;
14 | const [deployer] = provider.getWallets();
15 |
16 | it('reverts when the ACE contract is the zero address', async function () {
17 | await expect(
18 | deployContract(deployer, NoteStream, [ZERO_ADDRESS])
19 | ).to.be.revertedWith('ACE contract is the zero address');
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/packages/contracts/test/NoteStream/createStream.js:
--------------------------------------------------------------------------------
1 | // const { devConstants } = require("@notestream/dev-utils");
2 | const { waffle } = require('@nomiclabs/buidler');
3 | const { use, expect } = require('chai');
4 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
5 | const { bigNumberify, Interface } = require('ethers/utils');
6 |
7 | const { devConstants } = require('@notestream/dev-utils');
8 | const moment = require('moment');
9 | const crypto = require('crypto');
10 |
11 | const {
12 | // STANDARD_SALARY,
13 | STANDARD_TIME_OFFSET,
14 | STANDARD_TIME_DELTA,
15 | ZERO_ADDRESS,
16 | } = devConstants;
17 |
18 | const NoteStream = require('../../build/NoteStream.json');
19 | const { noteStreamFixture } = require('../fixtures');
20 |
21 | use(solidity);
22 |
23 | describe('NoteStream - createStream', function () {
24 | const { provider } = waffle;
25 | const [sender, recipient] = provider.getWallets();
26 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
27 |
28 | const NoteStreamInterface = new Interface(NoteStream.abi);
29 |
30 | let noteStream;
31 | let zkAsset;
32 | beforeEach(async function () {
33 | ({ noteStream, zkAsset } = await loadFixture(noteStreamFixture));
34 | });
35 |
36 | const now = bigNumberify(moment().format('X'));
37 | const startTime = now.add(STANDARD_TIME_OFFSET.toString());
38 | const stopTime = startTime.add(STANDARD_TIME_DELTA.toString());
39 | const notehash = crypto.randomBytes(32);
40 |
41 | describe('when not paused', function () {
42 | describe('when the recipient is valid', function () {
43 | it('creates the stream', async function () {
44 | const tx = await noteStream.createStream(
45 | recipient.address,
46 | notehash,
47 | zkAsset.address,
48 | startTime,
49 | stopTime
50 | );
51 | const receipt = await tx.wait();
52 | const { streamId } = NoteStreamInterface.parseLog(
53 | receipt.logs[receipt.logs.length - 1]
54 | ).values;
55 |
56 | const streamObject = await noteStream.getStream(streamId);
57 | expect(streamObject.sender).to.equal(sender.address);
58 | expect(streamObject.recipient).to.equal(recipient.address);
59 | expect(streamObject.noteHash).to.equal(
60 | `0x${notehash.toString('hex')}`
61 | );
62 |
63 | expect(streamObject.tokenAddress).to.equal(zkAsset.address);
64 | expect(streamObject.startTime).to.equal(startTime);
65 | expect(streamObject.lastWithdrawTime).to.equal(startTime);
66 | expect(streamObject.stopTime).to.equal(stopTime);
67 | });
68 |
69 | it('increases the next stream id', async function () {
70 | const currentStreamId = await noteStream.nextStreamId();
71 | await noteStream.createStream(
72 | recipient.address,
73 | notehash,
74 | zkAsset.address,
75 | startTime,
76 | stopTime
77 | );
78 |
79 | const nextStreamId = await noteStream.nextStreamId();
80 | expect(nextStreamId).to.equal(currentStreamId.add(1));
81 | });
82 |
83 | it('emits a createStream event', async function () {
84 | await expect(
85 | noteStream.createStream(
86 | recipient.address,
87 | notehash,
88 | zkAsset.address,
89 | startTime,
90 | stopTime
91 | )
92 | ).to.emit(noteStream, 'CreateStream');
93 | });
94 |
95 | it('reverts when the stream starts in the past', async function () {
96 | const invalidStartTime = now.sub(
97 | STANDARD_TIME_OFFSET.toString()
98 | );
99 | await expect(
100 | noteStream.createStream(
101 | recipient.address,
102 | notehash,
103 | zkAsset.address,
104 | invalidStartTime,
105 | stopTime
106 | )
107 | ).to.be.revertedWith('start time before block.timestamp');
108 | });
109 |
110 | it('reverts when the stream duration is zero', async function () {
111 | await expect(
112 | noteStream.createStream(
113 | recipient.address,
114 | notehash,
115 | zkAsset.address,
116 | startTime,
117 | startTime
118 | )
119 | ).to.be.revertedWith('Stream duration not greater than zero');
120 | });
121 |
122 | it('reverts when the stream duration is zero', async function () {
123 | const invalidStopTime = startTime.sub(
124 | STANDARD_TIME_DELTA.toString()
125 | );
126 | await expect(
127 | noteStream.createStream(
128 | recipient.address,
129 | notehash,
130 | zkAsset.address,
131 | startTime,
132 | invalidStopTime
133 | )
134 | ).to.be.revertedWith('Stream duration not greater than zero');
135 | });
136 | });
137 |
138 | it('reverts when the recipient is the caller itself', async function () {
139 | await expect(
140 | noteStream.createStream(
141 | sender.address,
142 | notehash,
143 | zkAsset.address,
144 | startTime,
145 | stopTime
146 | )
147 | ).to.be.revertedWith('stream to the caller');
148 | });
149 |
150 | it('reverts when the recipient is the NoteStream contract itself', async function () {
151 | await expect(
152 | noteStream.createStream(
153 | noteStream.address,
154 | notehash,
155 | zkAsset.address,
156 | startTime,
157 | stopTime
158 | )
159 | ).to.be.revertedWith('stream to the contract itself');
160 | });
161 |
162 | it('reverts when the recipient is the zero address', async function () {
163 | await expect(
164 | noteStream.createStream(
165 | ZERO_ADDRESS,
166 | notehash,
167 | zkAsset.address,
168 | startTime,
169 | stopTime
170 | )
171 | ).to.be.revertedWith('stream to the zero address');
172 | });
173 | });
174 |
175 | it('reverts when paused', async function () {
176 | // Note that `sender` coincides with the owner of the contract
177 |
178 | await noteStream.pause();
179 | await expect(
180 | noteStream.createStream(
181 | recipient.address,
182 | notehash,
183 | zkAsset.address,
184 | startTime,
185 | stopTime
186 | )
187 | ).to.be.revertedWith('Pausable: paused');
188 | });
189 | });
190 |
--------------------------------------------------------------------------------
/packages/contracts/test/NoteStream/getStream.js:
--------------------------------------------------------------------------------
1 | // const { devConstants } = require("@notestream/dev-utils");
2 | const { waffle } = require('@nomiclabs/buidler');
3 | const { use, expect } = require('chai');
4 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
5 | const { bigNumberify } = require('ethers/utils');
6 |
7 | const { noteStreamFixture } = require('../fixtures');
8 |
9 | use(solidity);
10 |
11 | describe('NoteStream - getStream', function () {
12 | const { provider } = waffle;
13 | const [sender, recipient] = provider.getWallets();
14 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
15 |
16 | let noteStream;
17 | beforeEach(async function () {
18 | ({ noteStream } = await loadFixture(noteStreamFixture));
19 | });
20 |
21 | it('reverts when the stream does not exist', async function () {
22 | const streamId = bigNumberify(419863);
23 | await expect(noteStream.getStream(streamId)).to.be.revertedWith(
24 | 'stream does not exist'
25 | );
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/packages/contracts/test/NoteStream/index.js:
--------------------------------------------------------------------------------
1 | require('./constructor.js');
2 | require('./getStream.js');
3 | require('./createStream.js');
4 | require('./withdrawFromStream.js');
5 | require('./cancelStream.js');
6 |
--------------------------------------------------------------------------------
/packages/contracts/test/StreamUtilities/getRatio.js:
--------------------------------------------------------------------------------
1 | const { waffle } = require('@nomiclabs/buidler');
2 | const { use } = require('chai');
3 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
4 | const { StreamUtilitiesFixture } = require('../fixtures');
5 |
6 | use(solidity);
7 |
8 | describe('StreamUtilities - getRatio', function () {
9 | const { provider } = waffle;
10 | const [sender, recipient] = provider.getWallets();
11 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
12 |
13 | // eslint-disable-next-line no-unused-vars
14 | let streamUtilitiesMock;
15 | beforeEach(async function () {
16 | ({ streamUtilitiesMock } = await loadFixture(StreamUtilitiesFixture));
17 | });
18 |
19 | it('returns the correct ratio');
20 | });
21 |
--------------------------------------------------------------------------------
/packages/contracts/test/StreamUtilities/index.js:
--------------------------------------------------------------------------------
1 | require('./getRatio.js');
2 | require('./validateRatioProof.js');
3 | require('./validateJoinSplitProof.js');
4 | require('./processWithdrawal.js');
5 | require('./processCancellation.js');
6 |
--------------------------------------------------------------------------------
/packages/contracts/test/StreamUtilities/processCancellation.js:
--------------------------------------------------------------------------------
1 | const { waffle } = require('@nomiclabs/buidler');
2 | const { use } = require('chai');
3 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
4 | const { StreamUtilitiesFixture } = require('../fixtures');
5 |
6 | use(solidity);
7 |
8 | describe('StreamUtilities - processCancellation', function () {
9 | const { provider } = waffle;
10 | const [sender, recipient] = provider.getWallets();
11 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
12 |
13 | // eslint-disable-next-line no-unused-vars
14 | let streamUtilitiesMock;
15 | beforeEach(async function () {
16 | ({ streamUtilitiesMock } = await loadFixture(StreamUtilitiesFixture));
17 | });
18 |
19 | it('reverts if withdraw note is not owned by recipient');
20 | it('reverts if refund note is not owned by sender');
21 | it('reverts if recipient does not have view access to the withdraw note');
22 | it('reverts if sender does not have view access to the refund note');
23 | it('emits a confidentialTransfer event');
24 | it('returns true');
25 | });
26 |
--------------------------------------------------------------------------------
/packages/contracts/test/StreamUtilities/processWithdrawal.js:
--------------------------------------------------------------------------------
1 | const { waffle } = require('@nomiclabs/buidler');
2 | const { use } = require('chai');
3 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
4 | const { StreamUtilitiesFixture } = require('../fixtures');
5 |
6 | use(solidity);
7 |
8 | describe('StreamUtilities - processWithdrawal', function () {
9 | const { provider } = waffle;
10 | const [sender, recipient] = provider.getWallets();
11 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
12 |
13 | // eslint-disable-next-line no-unused-vars
14 | let streamUtilitiesMock;
15 | beforeEach(async function () {
16 | ({ streamUtilitiesMock } = await loadFixture(StreamUtilitiesFixture));
17 | });
18 |
19 | it('reverts if new streamNote is not owned by NoteStream contract');
20 | it('reverts if withdraw note is not owned by recipient');
21 | it('reverts if sender does not have view access to the new streamNote');
22 | it('reverts if recipient does not have view access to the new streamNote');
23 | it('emits a confidentialTransfer event');
24 | it('returns the hash of the first output note');
25 | });
26 |
--------------------------------------------------------------------------------
/packages/contracts/test/StreamUtilities/validateJoinSplitProof.js:
--------------------------------------------------------------------------------
1 | const { waffle } = require('@nomiclabs/buidler');
2 | const { use } = require('chai');
3 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
4 | const { StreamUtilitiesFixture } = require('../fixtures');
5 |
6 | use(solidity);
7 |
8 | describe('StreamUtilities - validateJoinSplitProof', function () {
9 | const { provider } = waffle;
10 | const [sender, recipient] = provider.getWallets();
11 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
12 |
13 | // eslint-disable-next-line no-unused-vars
14 | let streamUtilitiesMock;
15 | beforeEach(async function () {
16 | ({ streamUtilitiesMock } = await loadFixture(StreamUtilitiesFixture));
17 | });
18 |
19 | it('reverts if proof has a non-zero public value transfer');
20 | it('reverts if proof does not have one input note only');
21 | it('reverts if proof does not have two output notes only');
22 | it('reverts if proof does not use same withdraw note as dividend proof');
23 | it('reverts if proof does not use stream note as input');
24 | it('returns output notes of proof');
25 | });
26 |
--------------------------------------------------------------------------------
/packages/contracts/test/StreamUtilities/validateRatioProof.js:
--------------------------------------------------------------------------------
1 | const { waffle } = require('@nomiclabs/buidler');
2 | const { use } = require('chai');
3 | const { solidity, createFixtureLoader } = require('ethereum-waffle');
4 | const { StreamUtilitiesFixture } = require('../fixtures');
5 |
6 | use(solidity);
7 |
8 | describe('StreamUtilities - validateRatioProof', function () {
9 | const { provider } = waffle;
10 | const [sender, recipient] = provider.getWallets();
11 | const loadFixture = createFixtureLoader(provider, [sender, recipient]);
12 |
13 | // eslint-disable-next-line no-unused-vars
14 | let streamUtilitiesMock;
15 | beforeEach(async function () {
16 | ({ streamUtilitiesMock } = await loadFixture(StreamUtilitiesFixture));
17 | });
18 |
19 | it('reverts if proof ratio does not match withdrawal duration');
20 | it('reverts if proof does not use stream note as source');
21 | it('returns input and output notes of proof');
22 | });
23 |
--------------------------------------------------------------------------------
/packages/contracts/test/fixtures.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('ethers');
2 |
3 | const { deployContract } = require('ethereum-waffle');
4 |
5 | const bn128 = require('@aztec/bn128');
6 | const { proofs } = require('@aztec/dev-utils');
7 |
8 | const { JOIN_SPLIT_PROOF, DIVIDEND_PROOF } = proofs;
9 |
10 | const {
11 | ACE,
12 | FactoryBase201907,
13 | JoinSplit,
14 | Dividend,
15 | ZkAsset,
16 | } = require('@aztec/contract-artifacts');
17 | const ERC20Mintable = require('../build/ERC20Mintable.json');
18 | const NoteStream = require('../build/NoteStream.json');
19 | const StreamUtilitiesMock = require('../build/StreamUtilitiesMock.json');
20 |
21 | const generateFactoryId = (epoch, cryptoSystem, assetType) => {
22 | return epoch * 256 ** 2 + cryptoSystem * 256 ** 1 + assetType * 256 ** 0;
23 | };
24 |
25 | async function aztecFixture(provider, [wallet]) {
26 | ethers.errors.setLogLevel('error');
27 |
28 | // console.log('Starting deployment');
29 | const ace = await deployContract(wallet, ACE, [], { gasLimit: 5000000 });
30 | await ace.setCommonReferenceString(bn128.CRS);
31 | // console.log('Deployed ACE');
32 |
33 | const joinSplitValidator = await deployContract(wallet, JoinSplit, []);
34 | await ace.setProof(JOIN_SPLIT_PROOF, joinSplitValidator.address);
35 | // console.log('Deployed JoinSplit');
36 |
37 | const dividendValidator = await deployContract(wallet, Dividend, []);
38 | await ace.setProof(DIVIDEND_PROOF, dividendValidator.address);
39 | // console.log('Deployed Dividend');
40 |
41 | const baseFactory = await deployContract(wallet, FactoryBase201907, [
42 | ace.address,
43 | ]);
44 | await ace.setFactory(generateFactoryId(1, 1, 1), baseFactory.address);
45 | // console.log('Deployed Factory');
46 |
47 | // ethers.errors.setLogLevel('warn');
48 | return { ace, joinSplitValidator, dividendValidator, baseFactory };
49 | }
50 |
51 | async function zkAssetFixture(provider, [wallet]) {
52 | ethers.errors.setLogLevel('error');
53 |
54 | // deploy ace and initialise
55 | const {
56 | ace,
57 | joinSplitValidator,
58 | dividendValidator,
59 | baseFactory,
60 | } = await aztecFixture(provider, [wallet]);
61 |
62 | // Deploy ERC20 token and linked ZkAsset
63 | const token = await deployContract(wallet, ERC20Mintable, [
64 | 'TESTCOIN',
65 | 'TEST',
66 | 18,
67 | ]);
68 | const zkAsset = await deployContract(wallet, ZkAsset, [
69 | ace.address,
70 | token.address,
71 | 1,
72 | ]);
73 |
74 | // ethers.errors.setLogLevel('warn');
75 |
76 | return {
77 | ace,
78 | joinSplitValidator,
79 | dividendValidator,
80 | baseFactory,
81 | token,
82 | zkAsset,
83 | };
84 | }
85 |
86 | async function noteStreamFixture(provider, [wallet]) {
87 | ethers.errors.setLogLevel('error');
88 |
89 | // deploy ace and initialise
90 | const {
91 | ace,
92 | joinSplitValidator,
93 | dividendValidator,
94 | baseFactory,
95 | token,
96 | zkAsset,
97 | } = await zkAssetFixture(provider, [wallet]);
98 |
99 | const noteStream = await deployContract(wallet, NoteStream, [ace.address]);
100 |
101 | return {
102 | ace,
103 | joinSplitValidator,
104 | dividendValidator,
105 | baseFactory,
106 | token,
107 | zkAsset,
108 | noteStream,
109 | };
110 | }
111 |
112 | async function StreamUtilitiesFixture(provider, [wallet]) {
113 | ethers.errors.setLogLevel('error');
114 |
115 | // deploy ace and initialise
116 | const {
117 | ace,
118 | joinSplitValidator,
119 | dividendValidator,
120 | baseFactory,
121 | token,
122 | zkAsset,
123 | } = await zkAssetFixture(provider, [wallet]);
124 |
125 | const streamUtilitiesMock = await deployContract(
126 | wallet,
127 | StreamUtilitiesMock
128 | );
129 |
130 | return {
131 | ace,
132 | joinSplitValidator,
133 | dividendValidator,
134 | baseFactory,
135 | token,
136 | zkAsset,
137 | streamUtilitiesMock,
138 | };
139 | }
140 |
141 | module.exports = {
142 | aztecFixture,
143 | zkAssetFixture,
144 | noteStreamFixture,
145 | StreamUtilitiesFixture,
146 | };
147 |
--------------------------------------------------------------------------------
/packages/contracts/test/runTests.js:
--------------------------------------------------------------------------------
1 | require('./StreamUtilities/index.js');
2 | require('./NoteStream/index.js');
3 |
--------------------------------------------------------------------------------
/packages/dev-utils/.eslintignore:
--------------------------------------------------------------------------------
1 | lib/*.js
2 |
--------------------------------------------------------------------------------
/packages/dev-utils/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "mocha": true
4 | },
5 | "extends": ["airbnb-base", "plugin:prettier/recommended"]
6 | }
7 |
--------------------------------------------------------------------------------
/packages/dev-utils/.gitignore:
--------------------------------------------------------------------------------
1 | lib/
--------------------------------------------------------------------------------
/packages/dev-utils/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.js": [
3 | "eslint --fix"
4 | ]
5 | }
--------------------------------------------------------------------------------
/packages/dev-utils/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | trailingComma: "all",
4 | singleQuote: true,
5 | tabWidth: 2
6 | };
--------------------------------------------------------------------------------
/packages/dev-utils/README.md:
--------------------------------------------------------------------------------
1 | ## Dev Utils
2 |
3 | Dev utils to be shared across NoteStream projects and packages.
4 |
5 | ## Usage
6 |
7 | Install the module:
8 |
9 | ```bash
10 | $ yarn add @notestream/dev-utils
11 | ```
12 |
13 | And import it in your project:
14 |
15 | ```js
16 | const devUtils = require("@notestream/dev-utils");
17 | ```
18 |
19 | ### Install Modules
20 |
21 | ```bash
22 | $ yarn install
23 | ```
24 |
25 | ### Build
26 |
27 | ```bash
28 | $ yarn build
29 | ```
30 |
31 | ### Lint
32 |
33 | ```bash
34 | $ yarn lint
35 | ```
36 |
37 | ### Clean
38 |
39 | ```bash
40 | $ yarn clean
41 | ```
42 |
--------------------------------------------------------------------------------
/packages/dev-utils/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['@babel/env'],
3 | plugins: [
4 | '@babel/plugin-transform-runtime',
5 | '@babel/plugin-proposal-object-rest-spread',
6 | ],
7 | };
8 |
--------------------------------------------------------------------------------
/packages/dev-utils/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@notestream/dev-utils",
3 | "description": "Dev utils to be shared across NoteStream packages",
4 | "version": "0.1.0",
5 | "author": {
6 | "name": "Tom French"
7 | },
8 | "bugs": {
9 | "url": "https://github.com/TomAFrench/NoteStream/issues"
10 | },
11 | "dependencies": {
12 | "bignumber.js": "^9.0.0",
13 | "ether-time-traveler": "^1.0.0",
14 | "ethers": "^4.0.47",
15 | "ganache-time-traveler": "^1.0.14",
16 | "moment": "^2.25.3"
17 | },
18 | "devDependencies": {
19 | "@babel/cli": "^7.5.5",
20 | "@babel/core": "^7.5.5",
21 | "@babel/plugin-proposal-object-rest-spread": "^7.4.0",
22 | "@babel/plugin-transform-runtime": "^7.6.0",
23 | "@babel/preset-env": "^7.5.5",
24 | "@babel/runtime": "^7.7.6",
25 | "eslint": "^6.1.0",
26 | "eslint-config-airbnb-base": "^14.0.0",
27 | "eslint-config-prettier": "^6.7.0",
28 | "eslint-plugin-import": "^2.18.2",
29 | "lint-staged": "^10.2.2",
30 | "mocha": "^6.2.0",
31 | "shx": "^0.3.2"
32 | },
33 | "files": [
34 | "/lib"
35 | ],
36 | "homepage": "https://github.com/TomAFrench/NoteStream/tree/develop/packages/dev-utils#readme",
37 | "license": "LGPL-3.0",
38 | "main": "./lib",
39 | "publishConfig": {
40 | "access": "public"
41 | },
42 | "repository": {
43 | "type": "git",
44 | "url": "https://github.com/TomAFrench/NoteStream.git",
45 | "directory": "packages/dev-utils"
46 | },
47 | "scripts": {
48 | "precommit": "lint-staged",
49 | "commit": "git-cz",
50 | "build": "yarn clean && babel --copy-files --out-dir ./lib --root-mode upward ./src",
51 | "clean": "shx rm -rf ./lib",
52 | "has:changed": "bash ../monorepo-scripts/ci/hasChanged.sh dev-utils",
53 | "lint": "eslint --ignore-path ../../.eslintignore .",
54 | "watch": "yarn build --watch"
55 | },
56 | "config": {
57 | "commitizen": {
58 | "path": "./node_modules/cz-conventional-changelog"
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/packages/dev-utils/src/chaiPlugin.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable func-names, no-else-return, no-param-reassign */
2 | const BigNumber = require('bignumber.js');
3 |
4 | const devConstants = require('./constants');
5 |
6 | module.exports = (chai) => {
7 | // See https://twitter.com/nicksdjohnson/status/1132394932361023488
8 | const convert = (value) => {
9 | let number;
10 |
11 | if (typeof value === 'string' || typeof value === 'number') {
12 | number = new BigNumber(value);
13 | } else if (BigNumber.isBigNumber(value)) {
14 | number = value;
15 | } else {
16 | new chai.Assertion(value).assert(
17 | false,
18 | `expected ${value} to be an instance of string, number or BigNumber`,
19 | );
20 | }
21 |
22 | return number;
23 | };
24 |
25 | /**
26 | * Performs a boundary check instead of an equality check.
27 | * In real life circumstances,it can take up to 14 seconds for a block
28 | * to be broadcast on the Ethereum network, so we have to account for this.
29 | *
30 | * Note that we make two assumptions:
31 | *
32 | * 1. The payment rate is 1 token/ second, which is true for all tests in this repo.
33 | * 2. By default, the token has 18 decimals
34 | */
35 | chai.Assertion.addMethod('tolerateTheBlockTimeVariation', function (
36 | expected,
37 | scale = devConstants.STANDARD_SCALE,
38 | tolerateByAddition = true,
39 | ) {
40 | // eslint-disable-next-line no-underscore-dangle
41 | const actual = convert(this._obj);
42 | expected = convert(expected);
43 | scale = convert(scale);
44 |
45 | const blockTimeAverage = new BigNumber(14).multipliedBy(scale);
46 | if (tolerateByAddition) {
47 | const expectedCeiling = expected.plus(blockTimeAverage);
48 |
49 | return this.assert(
50 | actual.isGreaterThanOrEqualTo(expected) &&
51 | actual.isLessThanOrEqualTo(expectedCeiling),
52 | `expected ${actual.toString()} to be >= than ${expected.toString()} and <= ${expectedCeiling.toString()}`,
53 | );
54 | } else {
55 | const expectedFloor = expected.minus(blockTimeAverage);
56 |
57 | return this.assert(
58 | actual.isLessThanOrEqualTo(expected) &&
59 | actual.isGreaterThanOrEqualTo(expectedFloor),
60 | `expected ${actual.toString()} to be <= than ${expected.toString()} and >= ${expectedFloor.toString()}`,
61 | );
62 | }
63 | });
64 | };
65 |
--------------------------------------------------------------------------------
/packages/dev-utils/src/constants.js:
--------------------------------------------------------------------------------
1 | const BigNumber = require('bignumber.js');
2 |
3 | const STANDARD_SALARY = new BigNumber(3600).multipliedBy(1e18);
4 |
5 | module.exports = {
6 | FIVE_UNITS: new BigNumber(5).multipliedBy(1e18),
7 | GAS_LIMIT: 6721975,
8 | INITIAL_SUPPLY: STANDARD_SALARY.multipliedBy(1000),
9 | ONE_UNIT: new BigNumber(1).multipliedBy(1e18),
10 | RPC_URL: 'http://127.0.0.1:8545',
11 | RPC_PORT: 8545,
12 | STANDARD_SALARY,
13 | STANDARD_SCALE: new BigNumber(1e18),
14 | STANDARD_TIME_DELTA: new BigNumber(3600),
15 | STANDARD_TIME_OFFSET: new BigNumber(300),
16 | ZERO_ADDRESS: '0x0000000000000000000000000000000000000000',
17 | };
18 |
--------------------------------------------------------------------------------
/packages/dev-utils/src/errors.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | AUTH_BOTH:
3 | 'only the sender or the recipient of the stream can perform this action',
4 | AUTH_RECIPIENT: 'only the stream recipient is allowed to perform this action',
5 | AUTH_SENDER: 'only the stream sender is allowed to perform this action',
6 | BLOCK_DELTA:
7 | 'the block difference needs to be higher than the payment interval',
8 | BLOCK_DELTA_MULTIPLICITY:
9 | 'the block difference needs to be a multiple of the payment interval',
10 | BLOCK_START:
11 | 'the start block needs to be higher than the current block number',
12 | BLOCK_STOP: 'the stop block needs to be higher than the start block',
13 | CONTRACT_ALLOWANCE: 'contract not allowed to transfer enough tokens',
14 | CONTRACT_EXISTENCE: 'token contract address needs to be provided',
15 | INSOLVENCY: 'not enough funds',
16 | STREAM_EXISTENCE: "stream doesn't exist",
17 | TERMS_NOT_CHANGED: 'stream has these terms already',
18 | };
19 |
--------------------------------------------------------------------------------
/packages/dev-utils/src/index.js:
--------------------------------------------------------------------------------
1 | const chaiPlugin = require('./chaiPlugin');
2 | const devConstants = require('./constants');
3 | const errors = require('./errors');
4 | const mochaContexts = require('./mochaContexts');
5 |
6 | module.exports = {
7 | chaiPlugin,
8 | devConstants,
9 | errors,
10 | mochaContexts,
11 | };
12 |
--------------------------------------------------------------------------------
/packages/dev-utils/src/mochaContexts.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable func-names */
2 | const { bigNumberify } = require('ethers/utils');
3 | const moment = require('moment');
4 | const traveler = require('ether-time-traveler');
5 |
6 | const devConstants = require('./constants');
7 |
8 | const { STANDARD_TIME_OFFSET, STANDARD_TIME_DELTA } = devConstants;
9 |
10 | function contextForSpecificTime(
11 | contextText,
12 | timeDuration,
13 | provider,
14 | functions,
15 | ) {
16 | const now = bigNumberify(moment().format('X'));
17 | let snapshot;
18 |
19 | describe(contextText, function () {
20 | beforeEach(async function () {
21 | snapshot = await traveler.takeSnapshot(provider);
22 | await traveler.advanceBlockAndSetTime(
23 | provider,
24 | now.add(timeDuration.toString()).toNumber(),
25 | );
26 | });
27 |
28 | functions();
29 |
30 | afterEach(async function () {
31 | await traveler.revertToSnapshot(provider, snapshot);
32 | });
33 | });
34 | }
35 |
36 | function contextForStreamDidStartButNotEnd(provider, functions) {
37 | const timeDuration = STANDARD_TIME_OFFSET.plus(5);
38 | contextForSpecificTime(
39 | 'when the stream did start but not end',
40 | timeDuration,
41 | provider,
42 | functions,
43 | );
44 | }
45 |
46 | function contextForStreamDidEnd(provider, functions) {
47 | const timeDuration = STANDARD_TIME_OFFSET.plus(STANDARD_TIME_DELTA).plus(5);
48 | contextForSpecificTime(
49 | 'when the stream did end',
50 | timeDuration,
51 | provider,
52 | functions,
53 | );
54 | }
55 |
56 | module.exports = {
57 | contextForStreamDidStartButNotEnd,
58 | contextForStreamDidEnd,
59 | };
60 |
--------------------------------------------------------------------------------
/packages/monorepo-scripts/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.js": [
3 | "eslint --fix"
4 | ]
5 | }
--------------------------------------------------------------------------------
/packages/monorepo-scripts/ci/hasChanged.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [[ -z "$CIRCLE_TOKEN" ]]; then
4 | exit 0
5 | fi
6 |
7 | LAST_SUCCESSFUL_BUILD_URL="https://circleci.com/api/v1.1/project/github/TomAFrench/NoteStream/tree/dev?filter=successful&limit=1"
8 | LAST_SUCCESSFUL_COMMIT=`curl -Ss -u "$CIRCLE_TOKEN:" $LAST_SUCCESSFUL_BUILD_URL | jq -r '.[0]["vcs_revision"]'`
9 | CHANGED_MODULES=$(echo $(git diff --name-only $LAST_SUCCESSFUL_COMMIT | grep ^packages\/.*\/ || true) | tr " " "\n" | cut -d\/ -f2 | uniq | paste -sd\| -)
10 |
11 | if [[ $1 =~ $CHANGED_MODULES ]]; then
12 | exit 0
13 | else
14 | exit 1
15 | fi
--------------------------------------------------------------------------------
/packages/monorepo-scripts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@notestream/monorepo-scripts",
3 | "version": "0.1.0",
4 | "description": "NoteStream monorepo scripts",
5 | "private": true,
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/TomAFrench/NoteStream.git"
9 | },
10 | "author": "Tom French",
11 | "license": "ISC",
12 | "bugs": {
13 | "url": "https://github.com/TomAFrench/NoteStream/issues"
14 | },
15 | "homepage": "https://github.com/TomAFrench/NoteStream#readme",
16 | "scripts": {
17 | "precommit": "lint-staged",
18 | "commit": "git-cz",
19 | "has:changed": "bash ../monorepo-scripts/ci/hasChanged.sh monorepo-scripts",
20 | "lint": "eslint --ignore-path ../../.eslintignore ./"
21 | },
22 | "config": {
23 | "commitizen": {
24 | "path": "./node_modules/cz-conventional-changelog"
25 | }
26 | },
27 | "devDependencies": {
28 | "lint-staged": "^10.2.2"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/packages/react-app/.env:
--------------------------------------------------------------------------------
1 | REACT_APP_SUBGRAPH_URL='https://api.thegraph.com/subgraphs/name/tomafrench/notestream-rinkeby'
2 | REACT_APP_AZTEC_API_KEY = '9HRKN7S-JSZMRJM-KWSDWSY-B2VSRD9'
3 | REACT_APP_TRANSAK_API_KEY = '7acc4227-1611-4787-8349-8b32194b6dc1'
4 | REACT_APP_NETWORK_ID=4
--------------------------------------------------------------------------------
/packages/react-app/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | es6: true,
4 | browser: true
5 | },
6 | extends: [
7 | '../../.eslintrc.js',
8 | "plugin:react/recommended",
9 | "plugin:@typescript-eslint/recommended",
10 | "plugin:@typescript-eslint/recommended-requiring-type-checking",
11 | "prettier/@typescript-eslint", // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
12 | "plugin:prettier/recommended" // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
13 | ],
14 | ignorePatterns: [],
15 | parser: "@typescript-eslint/parser",
16 | parserOptions: {
17 | project: "./tsconfig.json",
18 | tsconfigRootDir: __dirname,
19 | sourceType: "module",
20 | ecmaFeatures: {
21 | jsx: true
22 | }
23 | },
24 | plugins: [
25 | "@typescript-eslint",
26 | // "@typescript-eslint/tslint"
27 | ],
28 | rules: {
29 | "spaced-comment": ["error", "always", { "markers": ["/"] }],
30 | "import/extensions": [
31 | "error",
32 | "ignorePackages",
33 | {
34 | "js": "never",
35 | "jsx": "never",
36 | "ts": "never",
37 | "tsx": "never"
38 | }
39 | ],
40 | "react/jsx-uses-react": "error",
41 | "react/jsx-uses-vars": "error",
42 | "no-console": "off"
43 | },
44 | settings: {
45 | react: {
46 | version: "detect"
47 | },
48 | 'import/resolver': {
49 | node: {
50 | paths: ["src", "node_modules"],
51 | extensions: ['.js', '.jsx', '.ts', '.tsx']
52 | },
53 | },
54 | }
55 | };
56 |
--------------------------------------------------------------------------------
/packages/react-app/.lintstagedrc:
--------------------------------------------------------------------------------
1 | {
2 | "*.ts": [
3 | "eslint --fix"
4 | ],
5 | "*.tsx": [
6 | "eslint --fix"
7 | ]
8 | }
--------------------------------------------------------------------------------
/packages/react-app/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | semi: true,
3 | trailingComma: "all",
4 | singleQuote: true,
5 | tabWidth: 2
6 | };
--------------------------------------------------------------------------------
/packages/react-app/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
2 |
3 | ## Available Scripts
4 |
5 | In the project directory, you can run:
6 |
7 | ### `yarn start`
8 |
9 | Runs the app in the development mode.
10 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
11 |
12 | The page will reload if you make edits.
13 | You will also see any lint errors in the console.
14 |
15 | ### `yarn test`
16 |
17 | Launches the test runner in the interactive watch mode.
18 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
19 |
20 | ### `yarn build`
21 |
22 | Builds the app for production to the `build` folder.
23 | It correctly bundles React in production mode and optimizes the build for the best performance.
24 |
25 | The build is minified and the filenames include the hashes.
26 | Your app is ready to be deployed!
27 |
28 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
--------------------------------------------------------------------------------
/packages/react-app/now.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "build": {
4 | "env": {
5 | "REACT_APP_SUBGRAPH_URL": "https://api.thegraph.com/subgraphs/name/tomafrench/notestream-rinkeby",
6 | "REACT_APP_NETWORK_ID": "4"
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/packages/react-app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@notestream/react-app",
3 | "version": "0.1.0",
4 | "repository": {
5 | "type": "git",
6 | "url": "git+https://github.com/TomAFrench/NoteStream.git"
7 | },
8 | "author": "Tom French",
9 | "license": "ISC",
10 | "bugs": {
11 | "url": "https://github.com/TomAFrench/NoteStream/issues"
12 | },
13 | "dependencies": {
14 | "@apollo/client": "^3.0.0-beta.41",
15 | "@aztec/secp256k1": "^1.2.0",
16 | "@material-ui/core": "^4.9.5",
17 | "@material-ui/icons": "^4.9.1",
18 | "@notestream/contract-artifacts": "^1.0.1",
19 | "@transak/transak-sdk": "^1.0.17",
20 | "@types/testing-library__dom": "^7.5.0",
21 | "aztec.js": "^0.17.0",
22 | "bn.js": "^5.1.1",
23 | "bnc-onboard": "^1.9.0",
24 | "ethers": "^4.0.46",
25 | "graphql": "^14.6.0",
26 | "moment": "^2.24.0",
27 | "prop-types": "^15.7.2",
28 | "react": "^16.13.0",
29 | "react-blockies": "^1.4.1",
30 | "react-copy-to-clipboard": "^5.0.2",
31 | "react-dom": "^16.13.0",
32 | "react-router": "^5.1.2",
33 | "react-router-dom": "^5.2.0",
34 | "react-scripts": "^3.4.1",
35 | "zkasset-metadata": "^0.2.0"
36 | },
37 | "devDependencies": {
38 | "@babel/cli": "^7.8.4",
39 | "@babel/core": "^7.8.4",
40 | "@babel/node": "^7.8.4",
41 | "@babel/preset-env": "^7.8.4",
42 | "@babel/preset-typescript": "^7.9.0",
43 | "@testing-library/jest-dom": "^4.2.4",
44 | "@testing-library/react": "^9.3.2",
45 | "@testing-library/user-event": "^7.1.2",
46 | "@types/bn.js": "^4.11.6",
47 | "@types/react-copy-to-clipboard": "^4.3.0",
48 | "@types/react-router-dom": "^5.1.5",
49 | "@typescript-eslint/eslint-plugin-tslint": "^2.27.0",
50 | "eslint": "^6.8.0",
51 | "eslint-config-airbnb-base": "^14.1.0",
52 | "eslint-config-prettier": "^6.10.1",
53 | "eslint-plugin-import": "^2.20.2",
54 | "eslint-plugin-prettier": "^3.1.2",
55 | "eslint-plugin-react": "^7.19.0",
56 | "lint-staged": "^10.2.2",
57 | "prettier": "^2.0.4",
58 | "shx": "^0.3.2",
59 | "typescript": "^3.8.3"
60 | },
61 | "scripts": {
62 | "precommit": "lint-staged",
63 | "commit": "git-cz",
64 | "prestart": "yarn clean && yarn lint --fix",
65 | "start": "react-scripts start",
66 | "build": "react-scripts build",
67 | "eject": "react-scripts eject",
68 | "clean": "shx rm -rf ./build",
69 | "has:changed": "bash ../monorepo-scripts/ci/hasChanged.sh react-app",
70 | "lint": "eslint --config .eslintrc.js ./src --ext .js,.jsx,.ts,.tsx"
71 | },
72 | "eslintConfig": {
73 | "extends": "react-app"
74 | },
75 | "browserslist": {
76 | "production": [
77 | ">0.2%",
78 | "not dead",
79 | "not op_mini all"
80 | ],
81 | "development": [
82 | "last 1 chrome version",
83 | "last 1 firefox version",
84 | "last 1 safari version"
85 | ]
86 | },
87 | "config": {
88 | "commitizen": {
89 | "path": "./node_modules/cz-conventional-changelog"
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/packages/react-app/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TomAFrench/NoteStream/ab1e24dad291a19283938d4e9d560e95c9173303/packages/react-app/public/favicon.ico
--------------------------------------------------------------------------------
/packages/react-app/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |