├── packages ├── oo7-react │ ├── .babelrc │ ├── test │ │ └── index.js │ ├── conf.json │ ├── .gitignore │ ├── package.json │ ├── README.md │ └── LICENSE ├── oo7-substrate │ ├── README.md │ ├── src │ │ ├── metadata.js │ │ ├── srml │ │ │ ├── balances.js │ │ │ ├── session.js │ │ │ ├── democracy.js │ │ │ ├── indices.js │ │ │ └── staking.js │ │ ├── denominationInfo.js │ │ ├── subscriptionBond.js │ │ ├── storageBond.js │ │ ├── addressBook.js │ │ ├── pretty.js │ │ ├── index.js │ │ ├── ss58.js │ │ ├── types.js │ │ ├── transact.js │ │ ├── utils.js │ │ ├── nodeService.js │ │ ├── bonds.js │ │ └── secretStore.js │ ├── test │ │ └── ss58.js │ ├── package.json │ └── LICENSE ├── polkadot-identicon │ ├── .babelrc │ ├── .editorconfig │ ├── types.d.ts │ ├── README.md │ ├── package.json │ └── src │ │ └── index.jsx ├── oo7 │ ├── bump.sh │ ├── .eslintrc.json │ ├── conf.json │ ├── index.js │ ├── package.json │ ├── src │ │ ├── index.js │ │ ├── readyBond.js │ │ ├── notReadyBond.js │ │ ├── defaultBond.js │ │ ├── reactivePromise.js │ │ ├── timeBond.js │ │ ├── latchBond.js │ │ ├── bondProxy.js │ │ ├── transformBond.js │ │ └── bondCache.js │ ├── README.md │ ├── test │ │ └── ipc.js │ └── LICENSE └── oo7-parity │ ├── .eslintrc.json │ ├── test │ └── index.js │ ├── src │ ├── abis │ │ ├── githubhint.json │ │ ├── badge.json │ │ ├── token.json │ │ ├── index.js │ │ ├── badgereg.json │ │ ├── tokenreg.json │ │ ├── registry.json │ │ └── operations.json │ └── utils │ │ └── index.js │ ├── README.md │ ├── package.json │ └── LICENSE ├── lerna.json ├── .travis.yml ├── .editorconfig ├── package.json ├── .esdoc.json ├── .gitignore └── README.md /packages/oo7-react/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015", "react"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/oo7-substrate/README.md: -------------------------------------------------------------------------------- 1 | # oo7-substrate 2 | Polkadot Bonds library 3 | -------------------------------------------------------------------------------- /packages/polkadot-identicon/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "react" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "2.9.1", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "npmClient": "yarn", 7 | "version": "independent" 8 | } 9 | -------------------------------------------------------------------------------- /packages/oo7-react/test/index.js: -------------------------------------------------------------------------------- 1 | var should = require('chai').should(), 2 | oo7react = require('../src/index'), 3 | ReactiveComponent = oo7react.ReactiveComponent; 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: false 3 | language: node_js 4 | node_js: 5 | - 'stable' 6 | cache: 7 | directories: 8 | - node_modules 9 | script: 10 | - yarn lint 11 | - yarn test 12 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/metadata.js: -------------------------------------------------------------------------------- 1 | let _metadata = null; 2 | 3 | function setMetadata(m) { 4 | _metadata = m 5 | } 6 | 7 | function metadata() { 8 | return _metadata 9 | } 10 | 11 | module.exports = { metadata, setMetadata } -------------------------------------------------------------------------------- /packages/polkadot-identicon/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style=tab 4 | indent_size=tab 5 | tab_width=4 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=120 10 | insert_final_newline=true 11 | -------------------------------------------------------------------------------- /packages/oo7/bump.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | patch=$(grep version package.json | sed 's/.*: ".*\..*\.\(.*\)",/\1/') 4 | patch=$((patch + 1)) 5 | sed "s/\(\"version\": \".*\..*\.\)[0-9]*/\\1$patch/" package.json.new & mv -f package.json.new package.json 6 | -------------------------------------------------------------------------------- /packages/oo7/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["semistandard"], 3 | "env": { 4 | "browser": true, 5 | "mocha": true, 6 | "node": true 7 | }, 8 | "globals": { 9 | }, 10 | "rules": { 11 | "indent": ["error", "tab"], 12 | "no-tabs": 0 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/oo7-parity/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["semistandard"], 3 | "env": { 4 | "browser": true, 5 | "mocha": true, 6 | "node": true 7 | }, 8 | "globals": { 9 | }, 10 | "rules": { 11 | "indent": ["error", "tab"], 12 | "no-tabs": 0 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/oo7-parity/test/index.js: -------------------------------------------------------------------------------- 1 | var should = require('chai').should(); 2 | var oo7parity = require('../src/index'); 3 | 4 | describe('bonds', () => { 5 | it('should be constructable', () => { 6 | let t = new oo7parity.Bonds(); 7 | 8 | t.should.be.a('object'); 9 | }); 10 | }); 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style=tab 4 | indent_size=tab 5 | tab_width=2 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=120 10 | insert_final_newline=true 11 | [.travis.yml] 12 | indent_style=space 13 | indent_size=2 14 | tab_width=8 15 | end_of_line=lf 16 | 17 | -------------------------------------------------------------------------------- /packages/polkadot-identicon/types.d.ts: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export type IdenticonProps = { 4 | className?: string, 5 | account: string | Uint8Array, 6 | sixPoint?: boolean, 7 | size: number, 8 | style?: { [index: string]: any } 9 | }; 10 | 11 | export default class Identicon extends React.Component { 12 | } 13 | -------------------------------------------------------------------------------- /packages/oo7-substrate/test/ss58.js: -------------------------------------------------------------------------------- 1 | require('chai').should() 2 | 3 | const { ss58Encode, ss58Decode } = require('../src/ss58'); 4 | 5 | describe('ss58', () => { 6 | it('should encode & decode back', () => { 7 | const encoded = ss58Encode(1); 8 | encoded.should.equal('F7NZ'); 9 | const decoded = ss58Decode(encoded); 10 | decoded.should.equal(1); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/oo7/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true, 4 | "dictionaries": ["jsdoc","closure"] 5 | }, 6 | "source": { 7 | "includePattern": ".+\\.js(doc|x)?$", 8 | "excludePattern": "(^|\\/|\\\\)_" 9 | }, 10 | "plugins": ["plugins/markdown"], 11 | "templates": { 12 | "cleverLinks": true, 13 | "monospaceLinks": false 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/oo7-react/conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true, 4 | "dictionaries": ["jsdoc","closure"] 5 | }, 6 | "source": { 7 | "includePattern": ".+\\.js(doc|x)?$", 8 | "excludePattern": "(^|\\/|\\\\)_" 9 | }, 10 | "plugins": ["plugins/markdown"], 11 | "templates": { 12 | "cleverLinks": true, 13 | "monospaceLinks": false 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "postinstall": "lerna bootstrap", 4 | "bootstrap": "lerna bootstrap", 5 | "publish": "lerna publish", 6 | "lint": "lerna run lint", 7 | "test": "lerna run test", 8 | "lerna": "lerna", 9 | "esdoc": "esdoc" 10 | }, 11 | "devDependencies": { 12 | "lerna": "^3.4.3", 13 | "esdoc": "^1.0.4", 14 | "esdoc-node": "^1.0.3", 15 | "esdoc-standard-plugin": "^1.0.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.esdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": "./packages", 3 | "destination": "./docs", 4 | "excludes": ["/node_modules/", "/test/", "oo7-react/lib/index.js"], 5 | "plugins": [ 6 | { "name": "esdoc-node" }, 7 | { 8 | "name": "esdoc-standard-plugin", 9 | "option": { 10 | "undocumentIdentifier": {"enable": true}, 11 | "unexportedIdentifier": {"enable": false} 12 | }, 13 | "test": { 14 | "source": "./test" 15 | } 16 | } 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/srml/balances.js: -------------------------------------------------------------------------------- 1 | const { Bond } = require('oo7') 2 | const { Balance } = require('../types') 3 | 4 | function augment(runtime, chain) { 5 | let balances = runtime.balances 6 | if (balances._extras) { 7 | return 8 | } else { 9 | balances._extras = true 10 | } 11 | 12 | balances.balance = who => Bond 13 | .all([balances.freeBalance(who), balances.reservedBalance(who)]) 14 | .map(([f, r]) => new Balance(f + r)); 15 | balances.totalBalance = balances.balance; 16 | } 17 | 18 | module.exports = { augment } -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/githubhint.json: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"name":"_content","type":"bytes32"},{"name":"_url","type":"string"}],"name":"hintURL","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"_content","type":"bytes32"},{"name":"_accountSlashRepo","type":"string"},{"name":"_commit","type":"bytes20"}],"name":"hint","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"entries","outputs":[{"name":"accountSlashRepo","type":"string"},{"name":"commit","type":"bytes20"},{"name":"owner","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"_content","type":"bytes32"}],"name":"unhint","outputs":[],"type":"function"}] 2 | -------------------------------------------------------------------------------- /packages/polkadot-identicon/README.md: -------------------------------------------------------------------------------- 1 | # polkadot-identicon 2 | 3 | A Polkadot-themed SS58 identicon 4 | 5 | ## usage 6 | 7 | To install the component, do `npm install --save polkadot-identicon` 8 | 9 | Inside a React component, you can now render any Polkadot account with the associated icon - 10 | 11 | ```js 12 | import Identicon from 'polkadot-identicon'; 13 | 14 | ... 15 | render () { 16 | // address is either string (ss58-encoded address) or Uint8Array (publicKey) 17 | const { address } = this.props; 18 | // size is a number, indicating the size (in pixels) 19 | const size = 32; 20 | 21 | return ( 22 | 27 | ); 28 | } 29 | ... 30 | ``` 31 | -------------------------------------------------------------------------------- /packages/oo7/index.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const oo7 = require('./src'); 16 | 17 | module.exports = oo7; 18 | -------------------------------------------------------------------------------- /packages/oo7-react/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Babel 7 | lib 8 | 9 | # Runtime data 10 | pids 11 | *.pid 12 | *.seed 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # node-waf configuration 27 | .lock-wscript 28 | 29 | # Compiled binary addons (http://nodejs.org/api/addons.html) 30 | build/Release 31 | 32 | # Dependency directories 33 | node_modules 34 | jspm_packages 35 | 36 | # Optional npm cache directory 37 | .npm 38 | 39 | # Optional REPL history 40 | .node_repl_history 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /docs 2 | 3 | *.tgz 4 | 5 | # Logs 6 | logs 7 | *.log 8 | npm-debug.log* 9 | 10 | # Babel 11 | lib 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | 24 | # nyc test coverage 25 | .nyc_output 26 | 27 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 28 | .grunt 29 | 30 | # node-waf configuration 31 | .lock-wscript 32 | 33 | # Compiled binary addons (http://nodejs.org/api/addons.html) 34 | build/Release 35 | 36 | # Dependency directories 37 | node_modules 38 | jspm_packages 39 | 40 | # Optional npm cache directory 41 | .npm 42 | 43 | # Optional REPL history 44 | .node_repl_history 45 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/denominationInfo.js: -------------------------------------------------------------------------------- 1 | const { siPrefix } = require('./utils') 2 | 3 | let denominationInfo = { 4 | denominations: { unit: 0 }, 5 | primary: 'unit', 6 | unit: 'unit', 7 | ticker: 'UNIT' 8 | } 9 | 10 | let denominations = [ 'unit' ] 11 | 12 | function init (di) { 13 | if (!di.denominations[di.primary]) { 14 | throw new Error(`Denominations must include primary as key`) 15 | } 16 | 17 | let name = di.unit 18 | let denom = 0 19 | let ds = [] 20 | for (let i = 0; i <= di.denominations[di.primary] + 6; i += 3) { 21 | let n = Object.keys(di.denominations).find(k => di.denominations[k] == i) 22 | if (n) { 23 | name = n 24 | denom = i 25 | } 26 | ds.push(siPrefix(i - denom) + name) 27 | } 28 | 29 | denominations.length = 0 30 | Object.assign(denominations, ds) 31 | Object.assign(denominationInfo, di) 32 | } 33 | 34 | module.exports = { init, denominationInfo, denominations } -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/badge.json: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"},{"name":"_field","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_who","type":"address"}],"name":"certified","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Confirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"who","type":"address"}],"name":"Revoked","type":"event"}] 2 | -------------------------------------------------------------------------------- /packages/oo7-parity/README.md: -------------------------------------------------------------------------------- 1 | oo7-parity 2 | ========= 3 | 4 | A library to provide [`Bond`](https://github.com/ethcore/oo7#oo7)-related functionality for the Parity Ethereum 5 | implementation and other compatible systems. 6 | 7 | See the [oo7-parity reference](https://github.com/paritytech/parity/wiki/oo7-Parity-Reference) 8 | for more information on usage. 9 | 10 | ## Installation 11 | 12 | ```sh 13 | npm install oo7-parity --save 14 | ``` 15 | 16 | ## Usage 17 | 18 | ```javascript 19 | var oo7parity = require('oo7-parity'), 20 | bonds = oo7parity.bonds, 21 | formatBlockNumber = oo7parity.formatBlockNumber; 22 | 23 | // Prints a nicely formatted block number each time there's a new block. 24 | bonds.blockNumber.map(formatBlockNumber).tie(console.log); 25 | ``` 26 | 27 | ## Tests 28 | 29 | ```sh 30 | npm test 31 | ``` 32 | 33 | ## Contributing 34 | 35 | In lieu of a formal style guide, take care to maintain the existing coding style. 36 | Add unit tests for any new or changed functionality. Lint and test your code. 37 | 38 | ## Release History 39 | 40 | * 0.1.2 Add contract reading bonds 41 | * 0.1.1 Initial release 42 | -------------------------------------------------------------------------------- /packages/oo7/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oo7", 3 | "version": "0.7.12", 4 | "description": "The Bond API", 5 | "main": "index.js", 6 | "jsnext:main": "index.js", 7 | "files": [ 8 | "src/*" 9 | ], 10 | "scripts": { 11 | "test": "mocha --reporter spec", 12 | "lint": "eslint ./src" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/paritytech/oo7.git" 17 | }, 18 | "keywords": [ 19 | "Promise", 20 | "Parity", 21 | "Bond" 22 | ], 23 | "author": "Parity Technologies (https://parity.io/)", 24 | "license": "Apache-2.0", 25 | "bugs": { 26 | "url": "https://github.com/paritytech/oo7/issues" 27 | }, 28 | "homepage": "https://github.com/paritytech/oo7#readme", 29 | "devDependencies": { 30 | "chai": "^4.2.0", 31 | "eslint": "^5.6.1", 32 | "eslint-config-semistandard": "^13.0.0", 33 | "eslint-config-standard": "^12.0.0", 34 | "eslint-plugin-import": "^2.7.0", 35 | "eslint-plugin-node": "^8.0.0", 36 | "eslint-plugin-promise": "^4.0.1", 37 | "eslint-plugin-standard": "^4.0.0", 38 | "mocha": "^5.2.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/srml/session.js: -------------------------------------------------------------------------------- 1 | const { Bond, TransformBond } = require('oo7') 2 | const { ss58Encode } = require('../ss58') 3 | 4 | function augment (runtime, chain) { 5 | let timestamp = runtime.timestamp 6 | let session = runtime.session 7 | if (session._extras) { 8 | return 9 | } else { 10 | session._extras = true 11 | } 12 | 13 | session.blocksRemaining = Bond // 1..60 14 | .all([chain.height, session.lastLengthChange, session.sessionLength]) 15 | .map(([h, c, l]) => { 16 | c = (c || 0); 17 | return l - (h - c + l) % l; 18 | }); 19 | session.lateness = Bond 20 | .all([ 21 | timestamp.blockPeriod, 22 | timestamp.now, 23 | session.blocksRemaining, 24 | session.sessionLength, 25 | session.currentStart, 26 | ]).map(([p, n, r, l, s]) => (n.number + p.number * r - s.number) / (p.number * l)); 27 | session.percentLate = session.lateness.map(l => Math.round(l * 100 - 100)); 28 | 29 | session.validatorIndexOf = id => 30 | new TransformBond((i, id) => { 31 | let ss58 = ss58Encode(id); 32 | return i.findIndex(a => ss58Encode(a) === ss58); 33 | }, [session.validators, id]) 34 | } 35 | 36 | module.exports = { augment } -------------------------------------------------------------------------------- /packages/oo7/src/index.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const Bond = require('./bond'); 16 | const BondCache = require('./bondCache'); 17 | const BondProxy = require('./bondProxy'); 18 | const ReactiveBond = require('./reactiveBond'); 19 | const ReactivePromise = require('./reactivePromise'); 20 | const TimeBond = require('./timeBond'); 21 | const TransformBond = require('./transformBond'); 22 | 23 | module.exports = { 24 | Bond, 25 | BondCache, 26 | BondProxy, 27 | ReactiveBond, 28 | ReactivePromise, 29 | TimeBond, 30 | TransformBond 31 | }; 32 | -------------------------------------------------------------------------------- /packages/oo7-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oo7-react", 3 | "version": "0.8.13", 4 | "description": "The Reactive Bond API", 5 | "main": "lib/index.js", 6 | "files": [ 7 | "lib/*" 8 | ], 9 | "scripts": { 10 | "lint": "echo todo", 11 | "test": "npm run compile && mocha --compilers js:babel-core/register --reporter spec", 12 | "compile": "babel --presets react -d lib/ src/", 13 | "prepare": "npm run compile" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/paritytech/oo7-react.git" 18 | }, 19 | "keywords": [ 20 | "Promise", 21 | "Parity", 22 | "Bond", 23 | "React", 24 | "Reactive" 25 | ], 26 | "author": "Parity Technologies (https://parity.io/)", 27 | "license": "Apache-2.0", 28 | "bugs": { 29 | "url": "https://github.com/paritytech/oo7-react/issues" 30 | }, 31 | "homepage": "https://github.com/paritytech/oo7-react#readme", 32 | "dependencies": { 33 | "oo7": "^0.7.12", 34 | "react": "^16.5.2" 35 | }, 36 | "devDependencies": { 37 | "babel-cli": "^6.22.2", 38 | "babel-preset-es2015": "^6.24.1", 39 | "babel-preset-react": "^6.22.0", 40 | "chai": "^4.2.0", 41 | "mocha": "^5.2.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/oo7/src/readyBond.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const Bond = require('./bond'); 16 | 17 | /** 18 | * Derivative {@link Bond} representing the readiness of another {@link Bond}. 19 | */ 20 | class ReadyBond extends Bond { 21 | constructor (targetBond) { 22 | super(false); 23 | 24 | this._poll = () => this.changed(targetBond._ready); 25 | this._targetBond = targetBond; 26 | } 27 | 28 | initialise () { 29 | this._notifyId = this._targetBond.notify(this._poll); 30 | this._poll(); 31 | } 32 | 33 | finalise () { 34 | this._targetBond.unnotify(this._notifyId); 35 | } 36 | } 37 | 38 | module.exports = ReadyBond; 39 | -------------------------------------------------------------------------------- /packages/oo7/src/notReadyBond.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const Bond = require('./bond'); 16 | 17 | /** 18 | * Derivative {@link Bond} representing the non-readiness of another {@link Bond}. 19 | */ 20 | class NotReadyBond extends Bond { 21 | constructor (targetBond) { 22 | super(false); 23 | 24 | this._poll = () => this.changed(!targetBond._ready); 25 | this._targetBond = targetBond; 26 | } 27 | 28 | initialise () { 29 | this._notifyId = this._targetBond.notify(this._poll); 30 | this._poll(); 31 | } 32 | 33 | finalise () { 34 | this._targetBond.unnotify(this._notifyId); 35 | } 36 | } 37 | 38 | module.exports = NotReadyBond; 39 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/srml/democracy.js: -------------------------------------------------------------------------------- 1 | 2 | function augment (runtime, chain) { 3 | let democracy = runtime.democracy 4 | if (democracy._extras) { 5 | return 6 | } else { 7 | democracy._extras = true 8 | } 9 | /* //TODO 10 | let referendumInfoOf = storageMap('dem:pro:', (r, index) => { 11 | if (r == null) return null; 12 | let [ends, proposal, voteThreshold] = decode(r, ['BlockNumber', 'Proposal', 'VoteThreshold']); 13 | return { index, ends, proposal, voteThreshold }; 14 | }, i => toLE(i, 4), x => x.map(x => 15 | Object.assign({votes: democracy.votersFor(x.index) 16 | .map(r => r || []) 17 | .mapEach(v => Bond.all([ 18 | democracy.voteOf([x.index, v]), 19 | balances.balance(v) 20 | ])) 21 | .map(tallyAmounts) 22 | }, x), 1)); 23 | 24 | this.democracy = { 25 | proposed: storageValue('dem:pub', r => r ? decode(r, 'Vec<(PropIndex, Proposal, AccountId)>') : []).map(is => is.map(i => { 26 | let d = depositOf(i[0]); 27 | return { index: i[0], proposal: i[1], proposer: i[2], sponsors: d.map(v => v ? v.sponsors : null), bond: d.map(v => v ? v.bond : null) }; 28 | }), 2), 29 | active: Bond.all([nextTally, referendumCount]).map(([f, t]) => [...Array(t - f)].map((_, i) => referendumInfoOf(f + i)), 1), 30 | };*/ 31 | } 32 | 33 | module.exports = { augment } -------------------------------------------------------------------------------- /packages/oo7-parity/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oo7-parity", 3 | "version": "0.7.9", 4 | "description": "The Parity Bond API", 5 | "main": "src/index.js", 6 | "jsnext:main": "src/index.js", 7 | "files": [ 8 | "src/*" 9 | ], 10 | "scripts": { 11 | "test": "mocha --reporter spec", 12 | "lint": "eslint ./src" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/paritytech/oo7-parity.git" 17 | }, 18 | "keywords": [ 19 | "Promise", 20 | "Parity", 21 | "Bond" 22 | ], 23 | "author": "Parity Technologies (https://parity.io/)", 24 | "license": "Apache-2.0", 25 | "bugs": { 26 | "url": "https://github.com/paritytech/oo7-parity/issues" 27 | }, 28 | "homepage": "https://github.com/paritytech/oo7-parity#readme", 29 | "dependencies": { 30 | "@parity/api": "^5", 31 | "bignumber.js": "^8.0.2", 32 | "oo7": "^0.5.9" 33 | }, 34 | "devDependencies": { 35 | "chai": "^4.2.0", 36 | "eslint": "^5.7.0", 37 | "eslint-config-semistandard": "^13.0.0", 38 | "eslint-config-standard": "^12.0.0", 39 | "eslint-plugin-import": "^2.7.0", 40 | "eslint-plugin-node": "^8.0.0", 41 | "eslint-plugin-promise": "^4.0.1", 42 | "eslint-plugin-standard": "^4.0.0", 43 | "mocha": "^3.2.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/subscriptionBond.js: -------------------------------------------------------------------------------- 1 | const { Bond } = require('oo7') 2 | const { nodeService } = require('./nodeService') 3 | 4 | class SubscriptionBond extends Bond { 5 | constructor (name, params = [], xform = null, def = undefined, cache = { id: null, stringify: JSON.stringify, parse: JSON.parse }, mayBeNull) { 6 | super(mayBeNull, cache) 7 | this._name = name 8 | this._params = params 9 | this._xform = xform 10 | if (typeof def !== 'undefined' && (def !== null || mayBeNull)) { 11 | this._value = def 12 | this._ready = true 13 | } 14 | } 15 | 16 | initialise () { 17 | let that = this 18 | let callback = result => { 19 | if (that._xform) { 20 | result = that._xform(result) 21 | } 22 | that.trigger(result) 23 | } 24 | // promise instead of id because if a dependency triggers finalise() before id's promise is resolved the unsubscribing would call with undefined 25 | this.subscription = nodeService().subscribe(this._name, this._params, callback, error => { 26 | that.trigger({failed: error}) 27 | console.warn('Failed subscription:', error) 28 | delete that.subscription 29 | }) 30 | } 31 | 32 | finalise () { 33 | let x = this.subscription 34 | delete this.subscription 35 | x.then(id => nodeService().unsubscribe(id)); 36 | } 37 | } 38 | 39 | module.exports = { SubscriptionBond } -------------------------------------------------------------------------------- /packages/oo7/src/defaultBond.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const Bond = require('./bond'); 16 | 17 | /** 18 | * Derivative {@link Bond} representing the another {@link Bond} except defaulting 19 | * to same given `default` when not ready. 20 | */ 21 | class DefaultBond extends Bond { 22 | constructor (defaultValue, targetBond) { 23 | super(false); 24 | 25 | this._poll = () => this.changed(targetBond._ready ? targetBond._value : defaultValue); 26 | this._targetBond = targetBond; 27 | } 28 | 29 | initialise () { 30 | this._notifyId = this._targetBond.notify(this._poll); 31 | this._poll(); 32 | } 33 | 34 | finalise () { 35 | this._targetBond.unnotify(this._notifyId); 36 | } 37 | } 38 | 39 | module.exports = DefaultBond; 40 | -------------------------------------------------------------------------------- /packages/polkadot-identicon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "polkadot-identicon", 3 | "version": "1.1.45", 4 | "description": "A Polkadot-themed SS58 identicon Bonded React component", 5 | "main": "lib/index.js", 6 | "files": [ 7 | "lib/*", 8 | "types.d.ts" 9 | ], 10 | "scripts": { 11 | "compile": "babel --presets react -d lib/ src/", 12 | "prepare": "npm run compile", 13 | "test": "echo \"Error: no test specified yet\"" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/paritytech/oo7.git" 18 | }, 19 | "keywords": [ 20 | "polkadot", 21 | "substrate", 22 | "ss58", 23 | "identicon" 24 | ], 25 | "author": "Parity Technologies ", 26 | "license": "Apache-2.0", 27 | "bugs": { 28 | "url": "https://github.com/paritytech/oo7/issues" 29 | }, 30 | "homepage": "https://github.com/paritytech/oo7/tree/master/packages/polkadot-identicon#readme", 31 | "types": "types.d.ts", 32 | "dependencies": { 33 | "blakejs": "^1.1.0", 34 | "oo7": "^0.7.12", 35 | "oo7-react": "^0.8.13", 36 | "oo7-substrate": "^0.8.0", 37 | "react": "^16.4.2", 38 | "ss58": "^1.0.0" 39 | }, 40 | "devDependencies": { 41 | "babel-cli": "^6.26.0", 42 | "babel-preset-react": "^6.24.1", 43 | "watch": "^1.0.2" 44 | }, 45 | "gitHead": "c2608abd7bca953cdb058053b35b105a9ecf0d5a" 46 | } 47 | -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/token.json: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}] 2 | -------------------------------------------------------------------------------- /packages/oo7/src/reactivePromise.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const ReactiveBond = require('./reactiveBond'); 16 | 17 | // Exactly like ReactiveBond, except only calls `execute` once. Further changes 18 | // to members of `args` or `dependencies` have no effect. 19 | class ReactivePromise extends ReactiveBond { 20 | constructor ( 21 | args, 22 | dependencies, 23 | execute = args => this.changed(args), 24 | mayBeNull = true, 25 | resolveDepth = 1, 26 | cache = { id: null, stringify: JSON.stringify, parse: JSON.parse } 27 | ) { 28 | var done = false; 29 | super(args, dependencies, resolvedArguments => { 30 | if (!done) { 31 | done = true; 32 | execute.bind(this)(resolvedArguments); 33 | } 34 | }, mayBeNull, resolveDepth, cache); 35 | } 36 | } 37 | 38 | module.exports = ReactivePromise; 39 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/storageBond.js: -------------------------------------------------------------------------------- 1 | const XXH = require('xxhashjs'); 2 | const { blake2b } = require('blakejs') 3 | const { SubscriptionBond } = require('./subscriptionBond') 4 | const { VecU8 } = require('./types') 5 | const { stringToBytes, hexToBytes, toLEHex, bytesToHex } = require('./utils') 6 | const { decode } = require('./codec'); 7 | 8 | function storageKey(prefixString, arg, hasher = 'Twox128') { 9 | let loc = new Uint8Array([...stringToBytes(prefixString), ...arg]); 10 | switch (hasher) { 11 | case "Blake2_128": return '0x' + bytesToHex(blake2b(loc, null, 16)); 12 | case "Blake2_256": return '0x' + bytesToHex(blake2b(loc, null, 32)); 13 | case "Twox128": return '0x' + toLEHex(XXH.h64(loc.buffer, 0), 8) + toLEHex(XXH.h64(loc.buffer, 1), 8); 14 | case "Twox256": return '0x' + toLEHex(XXH.h64(loc.buffer, 0), 8) + toLEHex(XXH.h64(loc.buffer, 1), 8) + toLEHex(XXH.h64(loc.buffer, 2), 8) + toLEHex(XXH.h64(loc.buffer, 3), 8); 15 | case "Twox64Concat": return '0x' + toLEHex(XXH.h64(loc.buffer), 8) + bytesToHex(loc.buffer); 16 | default: throw 'Invalid hasher'; 17 | } 18 | } 19 | 20 | class StorageBond extends SubscriptionBond { 21 | constructor (prefix, type, args = [], defaultValue = null, hasher = 'Twox128') { 22 | super('state_storage', [[ storageKey(prefix, args, hasher) ]], r => { 23 | let raw = hexToBytes(r.changes[0][1]); 24 | return raw.length > 0 ? type == null ? raw : decode(raw, type) : defaultValue 25 | }) 26 | } 27 | } 28 | 29 | module.exports = { storageKey, StorageBond } -------------------------------------------------------------------------------- /packages/oo7-substrate/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "oo7-substrate", 3 | "version": "0.8.0", 4 | "description": "Substrate Bonds library", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "test": "mocha --reporter spec" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/paritytech/oo7.git" 12 | }, 13 | "keywords": [ 14 | "polkadot", 15 | "substrate", 16 | "bonds", 17 | "oo7" 18 | ], 19 | "author": "Parity Technologies ", 20 | "license": "Apache-2.0", 21 | "bugs": { 22 | "url": "https://github.com/paritytech/oo7/issues" 23 | }, 24 | "homepage": "https://github.com/paritytech/oo7/tree/master/packages/oo7-substrate#readme", 25 | "dependencies": { 26 | "@polkadot/util": "^0.41.1", 27 | "@polkadot/wasm-crypto": "^0.5.1", 28 | "@polkadot/wasm-schnorrkel": "^0.3.1", 29 | "base-x": "^3.0.4", 30 | "bip39": "^2.5.0", 31 | "blakejs": "^1.1.0", 32 | "bs58": "^4.0.1", 33 | "buffer": "^5.2.1", 34 | "change-case": "^3.0.2", 35 | "isomorphic-fetch": "^2.2.1", 36 | "isomorphic-ws": "^4.0.1", 37 | "jdenticon": "^2.1.1", 38 | "oo7": "^0.7.12", 39 | "pbkdf2": "^3.0.17", 40 | "ss58": "^1.0.2", 41 | "text-encoding": "^0.7.0", 42 | "text-encoding-polyfill": "^0.6.7", 43 | "tweetnacl": "^1.0.0", 44 | "ws": "^6.1.2", 45 | "xxhashjs": "^0.2.2" 46 | }, 47 | "devDependencies": { 48 | "chai": "^4.2.0", 49 | "mocha": "^5.2.0" 50 | }, 51 | "gitHead": "c2608abd7bca953cdb058053b35b105a9ecf0d5a" 52 | } 53 | -------------------------------------------------------------------------------- /packages/oo7/src/timeBond.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /* global setInterval,clearInterval */ 16 | 17 | const Bond = require('./bond'); 18 | 19 | var privateTestIntervals = {}; 20 | 21 | /** 22 | * @summary {@link Bond} object which represents the current time rounded down 23 | * to the second. 24 | * 25 | * @example 26 | * let b = new TimeBond; 27 | * b.log(); // logs 1497080209000 28 | * setTimeout(() => b.log(), 1000); // logs 1497080210000 29 | */ 30 | class TimeBond extends Bond { 31 | constructor () { 32 | super(); 33 | this.poll(); 34 | } 35 | poll () { 36 | this.trigger(Math.floor(Date.now() / 1000) * 1000); 37 | } 38 | initialise () { 39 | if (!TimeBond.useTestIntervals) { 40 | this.interval = setInterval(this.poll.bind(this), 1000); 41 | } else { 42 | this.interval = Object.keys(privateTestIntervals).length + 1; 43 | privateTestIntervals[this.interval] = this.poll.bind(this); 44 | } 45 | } 46 | finalise () { 47 | if (!TimeBond.useTestIntervals) { 48 | clearInterval(this.interval); 49 | } else { 50 | if (!privateTestIntervals[this.interval]) { 51 | throw new Error(`finalise() called multiple time on same timer!`); 52 | } 53 | delete privateTestIntervals[this.interval]; 54 | } 55 | } 56 | 57 | static testIntervals () { return privateTestIntervals; } 58 | } 59 | 60 | TimeBond.useTestIntervals = false; 61 | 62 | module.exports = TimeBond; 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # oo7 Suite 2 | 3 | [![Build Status](https://travis-ci.org/paritytech/oo7.svg?branch=master)](https://travis-ci.org/paritytech/oo7) 4 | 5 | [![npm:oo7](https://img.shields.io/npm/v/oo7.svg)](https://www.npmjs.com/package/oo7) 6 | [![npm:oo7-parity](https://img.shields.io/npm/v/oo7-parity.svg)](https://www.npmjs.com/package/oo7-parity) 7 | [![npm:oo7-react](https://img.shields.io/npm/v/oo7-react.svg)](https://www.npmjs.com/package/oo7-react) 8 | 9 | 10 | The `oo7` suite consists of three independent packages: 11 | 12 | - [oo7](./packages/oo7/) - Reactive Bonds 13 | - [oo7-parity](./packages/oo7-parity) - Bonds bindings for Ethereum objects 14 | - [oo7-react](./packages/oo7-react) - React components to display Bonds 15 | 16 | # Documentation 17 | 18 | [Documentation](https://paritytech.github.io/oo7/class/packages/oo7-parity/src/index.js~Bonds.html#instance-member-accounts) to all three packages can be found [here](https://paritytech.github.io/oo7/) 19 | 20 | # Examples 21 | 22 | ### oo7 23 | ```js 24 | // npm i oo7 25 | import {TimeBond} from 'oo7' 26 | 27 | 28 | // Initialize the bond 29 | const bond = new TimeBond() 30 | bond 31 | .map(t => new Date(t)) 32 | .tie(date => console.log(`${date}`)) 33 | // Wed Oct 11 2017 12:14:56 GMT+0200 (CEST) 34 | 35 | ``` 36 | 37 | ### oo7-parity 38 | ```js 39 | // npm i oo7-parity 40 | import {Bonds, formatBalance} from 'oo7-parity' 41 | 42 | const bonds = Bonds() 43 | 44 | bonds.balance(bonds.me) 45 | .map(formatBalance) 46 | .tie(console.log) // 4.45 ETH 47 | ``` 48 | 49 | ### oo7-react 50 | ```js 51 | import ReactDOM from 'react-dom' 52 | import React, { Component } from 'react' 53 | 54 | // Import reactive element 55 | import {Rspan} from 'oo7-react' 56 | import {Bonds, formatBalance} from 'oo7-parity' 57 | 58 | const bonds = new Bonds() 59 | 60 | class App extends Component { 61 | render() { 62 | // Simply render bonds 63 | return ( 64 |
65 | 66 | {bonds.me} has 67 | {bonds.balance(bonds.me).map(formatBalance)} 68 | 69 |
70 | ); 71 | } 72 | } 73 | 74 | ReactDOM.render(, document.querySelector('body')) 75 | ``` 76 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/addressBook.js: -------------------------------------------------------------------------------- 1 | const { Bond } = require('oo7') 2 | const { ss58Encode } = require('./ss58') 3 | const { AccountId } = require('./types') 4 | 5 | class AddressBook extends Bond { 6 | constructor () { 7 | super() 8 | this._accounts = [] 9 | this._load() 10 | } 11 | 12 | submit (account, name) { 13 | this._accounts.push({account, name}) 14 | this._sync() 15 | } 16 | 17 | accounts () { 18 | return this._accounts.map(i => i.account) 19 | } 20 | 21 | find (identifier) { 22 | if (this._accounts.indexOf(identifier) !== -1) { 23 | return identifier 24 | } 25 | if (identifier instanceof Uint8Array && identifier.length == 32 || identifier instanceof AccountId) { 26 | identifier = ss58Encode(identifier) 27 | } 28 | return this._byAddress[identifier] ? this._byAddress[identifier] : this._byName[identifier] 29 | } 30 | 31 | forget (identifier) { 32 | let item = this.find(identifier) 33 | if (item) { 34 | console.info(`Forgetting account ${item.name} (${item.address})`) 35 | this._accounts = this._accounts.filter(i => i !== item) 36 | this._sync() 37 | } 38 | } 39 | 40 | _load () { 41 | if (localStorage.addressBook) { 42 | this._accounts = JSON.parse(localStorage.addressBook) 43 | } else { 44 | this._accounts = [] 45 | } 46 | this._sync() 47 | } 48 | 49 | _sync () { 50 | let byAddress = {} 51 | let byName = {} 52 | this._accounts = this._accounts.map(({address, account, name}) => { 53 | account = account || ss58Decode(address) 54 | address = address || ss58Encode(account) 55 | let item = {name, account, address} 56 | byAddress[address] = item 57 | byName[name] = item 58 | return item 59 | }) 60 | this._byAddress = byAddress 61 | this._byName = byName 62 | localStorage.addressBook = JSON.stringify(this._accounts.map(k => ({address: k.address, name: k.name}))) 63 | this.trigger({accounts: this._accounts, byAddress: this._byAddress, byName: this._byName}) 64 | } 65 | } 66 | 67 | let s_addressBook = null; 68 | 69 | function addressBook() { 70 | if (s_addressBook === null) { 71 | s_addressBook = new AddressBook; 72 | } 73 | return s_addressBook; 74 | } 75 | 76 | module.exports = { addressBook, AddressBook }; -------------------------------------------------------------------------------- /packages/oo7/README.md: -------------------------------------------------------------------------------- 1 | oo7 2 | ========= 3 | 4 | A small library providing what might be termed as reactive expressions, `Bond`s 5 | (hence the name). Classes deriving from `Bond` are expected to determine when 6 | their value has changed and call `trigger` accordingly. 7 | 8 | `TimeBond` is provided as a simple expression type which evaluates to the 9 | current time and triggers an update once per second. 10 | 11 | Expressions can be composed through `TransformBond`, which allows both argument 12 | dependencies (that get passed into the combination transform) and non-argument 13 | dependencies (which do not). For its dependencies, `TransformBond` is able to 14 | work with basic values, `Promise`s and other `Bonds` abstractly. 15 | 16 | ## Installation 17 | 18 | ```sh 19 | npm install oo7 --save 20 | ``` 21 | 22 | ## Usage 23 | 24 | ```javascript 25 | var oo7 = require('oo7'), 26 | Bond = oo7.Bond, 27 | TimeBond = oo7.TimeBond, 28 | TransformBond = oo7.TransformBond; 29 | 30 | let t = new TimeBond; 31 | 32 | // Prints the Unix time every second. 33 | t.tie(console.log); 34 | 35 | // Prints the formatted date every second. 36 | new TransformBond(x => new Date(x), [t]).tie(console.log); 37 | ``` 38 | 39 | ## Tests 40 | 41 | ```sh 42 | npm test 43 | ``` 44 | 45 | ## Contributing 46 | 47 | In lieu of a formal styleguide, take care to maintain the existing coding style. 48 | Add unit tests for any new or changed functionality. Lint and test your code. 49 | 50 | For development, a number of git hooks are provides that allow you to ensure tightly 51 | couple packages remain locally referenced at development time and switched to the 52 | proper version at commit/publish time. Simply copy all files from hooks into the git 53 | hook path: 54 | 55 | cp hooks/* .git/hooks 56 | 57 | NPM's publishing functionality automatically ensures packages reference the latest 58 | of their dependencies in the tightly-coupled group, and bumps the patch version after 59 | publication. 60 | 61 | For all of this to work, ensure this, `oo7-parity`, `oo7-react` and `parity-reactive-ui` 62 | all exist in the same parent directory. 63 | 64 | ## Release History 65 | 66 | * 0.1.2 67 | * 0.1.1 Minor fix. 68 | * 0.1.0 Initial release 69 | -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/index.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const ParityApi = require('@parity/api'); 16 | 17 | const sha3 = ParityApi.util.sha3; 18 | 19 | /** @type {ABI} */ 20 | const RegistryABI = require('./registry.json'); 21 | const RegistryExtras = [ 22 | { name: 'lookupData', method: 'getData', args: [n => sha3(n.toLowerCase()), null] }, 23 | { name: 'lookupAddress', method: 'getAddress', args: [n => sha3(n.toLowerCase()), null] }, 24 | { name: 'lookupUint', method: 'getUint', args: [n => sha3(n.toLowerCase()), null] }, 25 | { name: 'lookupOwner', method: 'getOwner', args: [n => sha3(n.toLowerCase())] } 26 | ]; 27 | /** 28 | * Github Hint ABI definition. 29 | * 30 | * @type {ABI} 31 | */ 32 | const GitHubHintABI = (() => require('./githubhint.json'))(); 33 | /** @type {ABI} */ 34 | const OperationsABI = (() => require('./operations.json'))(); 35 | /** @type {ABI} */ 36 | const BadgeRegABI = (() => require('./badgereg.json'))(); 37 | /** @type {ABI} */ 38 | const TokenRegABI = (() => require('./tokenreg.json'))(); 39 | /** @type {ABI} */ 40 | const BadgeABI = (() => require('./badge.json'))(); 41 | /** @type {ABI} */ 42 | const TokenABI = (() => require('./token.json'))(); 43 | 44 | /** 45 | * Deprecated. 46 | */ 47 | function abiPolyfill () { 48 | return { 49 | registry: RegistryABI, 50 | registryExtras: RegistryExtras, 51 | githubhint: GitHubHintABI, 52 | operations: OperationsABI, 53 | badgereg: BadgeRegABI, 54 | tokenreg: TokenRegABI, 55 | badge: BadgeABI, 56 | erc20token: TokenABI 57 | }; 58 | } 59 | 60 | module.exports = { 61 | abiPolyfill, 62 | RegistryABI, 63 | RegistryExtras, 64 | GitHubHintABI, 65 | OperationsABI, 66 | BadgeRegABI, 67 | TokenRegABI, 68 | BadgeABI, 69 | TokenABI 70 | }; 71 | -------------------------------------------------------------------------------- /packages/oo7/src/latchBond.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License") 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const Bond = require('./bond'); 16 | 17 | /** 18 | * Derivative {@link Bond} resolving to a default value when not ready. 19 | * Once inputBond is ready, its value remains fixed indefinitely. 20 | */ 21 | class LatchBond extends Bond { 22 | constructor (targetBond, def = undefined, mayBeNull = undefined, cache = null) { 23 | super(typeof mayBeNull === 'undefined' ? targetBond._mayBeNull : mayBeNull, cache); 24 | 25 | if (typeof (def) !== 'undefined') { 26 | this._ready = true; 27 | this._value = def; 28 | } 29 | 30 | let that = this; 31 | this._targetBond = targetBond; 32 | this._poll = () => { 33 | if (that._targetBond) { 34 | if (that._targetBond._ready) { 35 | that.changed(targetBond._value); 36 | if (that._notifyId) { 37 | that._targetBond.unnotify(that._notifyId); 38 | delete that._targetBond; 39 | } 40 | delete that._poll; 41 | } 42 | } else { 43 | console.warn('poll called when targetBond is not set. This cannot happen.'); 44 | } 45 | }; 46 | } 47 | 48 | initialise () { 49 | if (this._poll) { 50 | let notifyId = this._targetBond.notify(this._poll); 51 | // line above might have killed it (if the target is already ready): 52 | // we should only save it that wasn't the case 53 | if (this._poll) { 54 | // It didn't delete it. Carry on. 55 | this._notifyId = notifyId; 56 | this._poll(); 57 | } else { 58 | // It did delete it; unnotify immediately. 59 | this._targetBond.unnotify(notifyId); 60 | delete this._targetBond; 61 | } 62 | } 63 | } 64 | 65 | finalise () { 66 | if (this._targetBond) { 67 | this._targetBond.unnotify(this._notifyId); 68 | } 69 | } 70 | } 71 | 72 | module.exports = LatchBond; 73 | -------------------------------------------------------------------------------- /packages/oo7-react/README.md: -------------------------------------------------------------------------------- 1 | oo7-react 2 | ========= 3 | 4 | A small library to provide integration between React and `Bond`s. 5 | 6 | Provides the Reactive base component `ReactiveComponent` and a number of 7 | convenience components derived from it `Reactive`. The first 8 | provides an alternative to `React.Component` for classes whose state shall 9 | depend on `Bond`ed expressions. It allows `Bond`s and `Promise`s 10 | and plain data to be passed in as one or more named props (the names are passed 11 | in the constructor) or explicitly as fields in the constructors. In both cases, 12 | these reactive values show up as plain values of the same name in `this.state`. 13 | 14 | `Rspan` is an alternative to `span` but allows you to provide reactive values 15 | rather than plain data. For the child element, 16 | `className` and `id` props, the value can be a `Bond`, `Promise` or plain data. 17 | The element will stay updated to the latest value of each expression. 18 | 19 | ## Installation 20 | 21 | ```sh 22 | npm install oo7-react --save 23 | ``` 24 | 25 | ## Usage 26 | 27 | ```javascript 28 | // Assume React is already required. 29 | var oo7 = require('oo7'), 30 | TimeBond = oo7.TimeBond, 31 | oo7react = require('oo7-react'), 32 | Rspan = oo7react.Rspan; 33 | 34 | class DateFormatter extends ReactiveComponent { 35 | constructor() { 36 | // Tell the object to look out for 'date' prop and keep the 'date' 37 | // state up to date. 38 | super(['date']); 39 | } 40 | render() { 41 | return this.state.date === null ? 42 |
Date unknown
: 43 |
The date is {this.state.date}
; 44 | } 45 | } 46 | 47 | class App extends React.Component { 48 | render() { 49 | // Evaluates to a pretty datetime. 50 | let b = (new TimeBond).map(t => new Date(t) + ''); 51 | // Prints two clocks. They both print the time and stay up to date. 52 | return (
53 | 54 |
The date is: {b}
55 |
) 56 | } 57 | } 58 | ``` 59 | 60 | ## Tests 61 | 62 | ```sh 63 | npm test 64 | ``` 65 | 66 | ## Contributing 67 | 68 | In lieu of a formal style guide, take care to maintain the existing coding style. 69 | Add unit tests for any new or changed functionality. Lint and test your code. 70 | 71 | ## Release History 72 | 73 | * 0.4.0 Remove material-ui dependency 74 | * 0.1.2 Add components 75 | * 0.1.1 Initial release 76 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/pretty.js: -------------------------------------------------------------------------------- 1 | const { ss58Encode } = require('./ss58') 2 | const { bytesToHex } = require('./utils') 3 | const { VecU8, AccountId, Hash, SlashPreference, VoteThreshold, Moment, Balance, BlockNumber, AccountIndex, Tuple, reviver } = require('./types') 4 | const { denominationInfo } = require('./denominationInfo') 5 | 6 | const numberWithCommas = n => { 7 | let x = n.toString(); 8 | if (x.indexOf('.') > -1) { 9 | let [a, b] = x.split('.'); 10 | return numberWithCommas(a) + '.' + b; 11 | } else { 12 | return x.replace(/\B(?=(\d{3})+(?!\d))/g, ","); 13 | } 14 | } 15 | 16 | //TODO: AccountIndex 17 | 18 | function pretty(expr) { 19 | if (expr === null) { 20 | return 'null'; 21 | } 22 | if (expr instanceof VoteThreshold) { 23 | return 'VoteThreshold.' + expr; 24 | } 25 | if (expr instanceof SlashPreference) { 26 | return 'SlashPreference{unstake_threshold=' + expr + '}'; 27 | } 28 | if (expr instanceof Balance) { 29 | let di = denominationInfo 30 | 31 | let denomincationSearch = [di.primary, Object.keys(di.denominations)] 32 | let unit = null 33 | let dp = 0 34 | for (ii in denomincationSearch) { 35 | let i = denomincationSearch[ii] 36 | let denom = di.denominations[i] 37 | let divisor = Math.pow(10, denom) 38 | let lower = divisor / 30 39 | let upper = divisor * 30000 40 | if (expr > lower && expr < upper) { 41 | unit = i 42 | expr /= divisor 43 | for (; expr < 3000 / Math.pow(10, dp); dp++) {} 44 | break; 45 | } 46 | } 47 | 48 | if (unit === null) { 49 | // default 50 | if (expr < Math.pow(10, di.denominations[di.primary]) / 30 && expr !== 0) { 51 | unit = di.unit 52 | } else { 53 | unit = di.primary 54 | expr /= Math.pow(10, di.denominations[unit]) 55 | expr = Math.round(expr) 56 | } 57 | } 58 | 59 | return numberWithCommas(Math.round(expr * Math.pow(10, dp)) / Math.pow(10, dp)) + ' ' + unit 60 | } 61 | if (expr instanceof BlockNumber) { 62 | return numberWithCommas(expr); 63 | } 64 | if (expr instanceof Hash) { 65 | return '0x' + bytesToHex(expr); 66 | } 67 | if (expr instanceof Moment) { 68 | return expr.toLocaleString() + " (" + expr.number + " seconds)"; 69 | } 70 | if (expr instanceof AccountId) { 71 | return ss58Encode(expr); 72 | } 73 | if (expr instanceof Tuple) { 74 | return '(' + expr.map(pretty).join(', ') + ')'; 75 | } 76 | if (expr instanceof VecU8 || expr instanceof Uint8Array) { 77 | if (expr.length <= 256) { 78 | return '[' + bytesToHex(expr) + ']'; 79 | } else { 80 | return `[${bytesToHex(expr.slice(0, 256))}...] (${expr.length} bytes)`; 81 | } 82 | } 83 | if (expr instanceof Array) { 84 | return '[' + expr.map(pretty).join(', ') + ']'; 85 | } 86 | if (typeof expr === 'object') { 87 | return '{' + Object.keys(expr).map(k => k + ': ' + pretty(expr[k])).join(', ') + '}'; 88 | } 89 | return '' + expr; 90 | } 91 | 92 | module.exports = { pretty }; -------------------------------------------------------------------------------- /packages/oo7-substrate/src/srml/indices.js: -------------------------------------------------------------------------------- 1 | const { Bond, TransformBond } = require('oo7') 2 | const { ss58Encode, ss58Decode } = require('../ss58') 3 | const { AccountId, AccountIndex } = require('../types') 4 | 5 | function fixedBond(b) { 6 | r = new Bond 7 | r.trigger(b) 8 | return r 9 | } 10 | 11 | function isId(id) { 12 | return id instanceof AccountId || (id instanceof Uint8Array && id.length == 32) 13 | } 14 | 15 | function isIndex(index) { 16 | return index instanceof AccountIndex || typeof index === 'number' 17 | } 18 | 19 | function augment(runtime, chain) { 20 | let indices = runtime.indices 21 | if (indices._extras) { 22 | return 23 | } else { 24 | indices._extras = true 25 | } 26 | 27 | indices.lookup = indexBond => new TransformBond(index => 28 | isIndex(index) || typeof(index) === 'number' 29 | ? indices.enumSet(new AccountIndex(Math.floor(index / 64))).map(items => items[index % 64]) 30 | : null, 31 | [indexBond] 32 | ) 33 | 34 | indices.accounts = indices.nextEnumSet.map(last => 35 | [...new Array(last + 1)].map((_, i) => indices.enumSet(i)) 36 | ).map(sets => { 37 | let res = {} 38 | sets.forEach((items, i) => 39 | items.forEach((item, j) => 40 | res[ss58Encode(item)] = i * 64 + j 41 | ) 42 | ) 43 | return res 44 | }).subscriptable() 45 | 46 | indices.tryIndex = (id, whenNone = id) => { 47 | if (!id) { 48 | console.warn("bad identity passed to tryIndex", id) 49 | return undefined 50 | } 51 | return new TransformBond((accounts, id, whenNone) => { 52 | if (!id) { 53 | console.warn("bad identity resolved to tryIndex", id) 54 | return undefined 55 | } 56 | if (typeof id === 'string') { 57 | id = ss58Decode(id) 58 | } 59 | if (isId(id)) { 60 | let i = accounts[ss58Encode(id)] 61 | return isIndex(i) 62 | ? new AccountIndex(i) 63 | : whenNone 64 | } else { 65 | return whenNone 66 | } 67 | }, [indices.accounts, id, whenNone], [], 3, 3, undefined, false) 68 | } 69 | 70 | indices.ss58Encode = (address, type, csLength, length) => new TransformBond((address, id, index, type, csLength, length) => { 71 | if (isIndex(address)) { 72 | index = address 73 | } 74 | if (isId(address)) { 75 | id = address 76 | } 77 | if (!isId(id) || !(isIndex(index) || isId(index))) { 78 | return null 79 | } 80 | return ss58Encode(index, type || undefined, csLength || undefined, length || undefined, id) 81 | }, [address, indices.lookup(address), indices.tryIndex(address), type || null, csLength || null, length || null], [], 3, 3, undefined, false) 82 | 83 | indices.ss58Decode = address => { 84 | try { 85 | let indexOrId = ss58Decode(address, index => { throw {index} }) 86 | if (isId(indexOrId)) { 87 | return fixedBond(indexOrId) 88 | } else { 89 | return indices.lookup(indexOrId) 90 | } 91 | } 92 | catch (indexToLookup) { 93 | return indices.lookup(indexToLookup.index).map(id => { 94 | return ss58Decode(address, id) === null ? null : id 95 | }) 96 | } 97 | } 98 | } 99 | 100 | module.exports = { augment } -------------------------------------------------------------------------------- /packages/oo7-substrate/src/index.js: -------------------------------------------------------------------------------- 1 | const nacl = require('tweetnacl') 2 | const { ss58Decode, ss58Encode, setNetworkDefault } = require('./ss58') 3 | const { VecU8, AccountId, Hash, VoteThreshold, Moment, Balance, BlockNumber, AccountIndex, TransactionEra, Tuple, Permill, Perbill, reviver } = require('./types') 4 | const { decode, encode, addCodecTransform } = require('./codec') 5 | const { pretty } = require('./pretty') 6 | const { post, composeTransaction, TransactionBond } = require('./transact') 7 | const { secretStore } = require('./secretStore') 8 | const { addressBook } = require('./addressBook') 9 | const { stringToSeed, stringToBytes, hexToBytes, bytesToHex, toLEHex, toLE, leToNumber, leHexToNumber, siPrefix } = require('./utils') 10 | const { storageKey, StorageBond } = require('./storageBond') 11 | const { initRuntime, runtime, calls, runtimePromise, callsPromise, chain, system, state, runtimeUp } = require('./bonds') 12 | const { nodeService, setNodeUri } = require('./nodeService') 13 | const denominationInfo = require('./denominationInfo') 14 | const { metadata } = require('./metadata') 15 | 16 | function tally(x) { 17 | var r = [0, 0] 18 | x.forEach(v => r[v ? 1 : 0]++) 19 | return {aye: r[1], nay: r[0]} 20 | } 21 | 22 | function tallyAmounts(x) { 23 | var r = [0, 0] 24 | x.forEach(([v, b]) => r[v ? 1 : 0] += b) 25 | return {aye: r[1], nay: r[0]} 26 | } 27 | 28 | // TODO: receipts from tx 29 | // TODO: compact transactions (switch out account for index when possible) 30 | 31 | if (typeof window !== 'undefined') { 32 | window.ss58Encode = ss58Encode 33 | window.ss58Decode = ss58Decode 34 | window.bytesToHex = bytesToHex 35 | window.stringToBytes = stringToBytes 36 | window.hexToBytes = hexToBytes 37 | window.toLE = toLE 38 | window.leToNumber = leToNumber 39 | window.storageKey = storageKey 40 | window.encode = encode 41 | window.decode = decode 42 | window.pretty = pretty 43 | window.addCodecTransform = addCodecTransform 44 | window.setNetworkDefault = setNetworkDefault 45 | window.nodeService = nodeService 46 | window.secretStore = secretStore 47 | window.nacl = nacl 48 | window.post = post 49 | window.TransactionEra = TransactionEra 50 | window.composeTransaction = composeTransaction 51 | window.AccountId = AccountId 52 | window.AccountIndex = AccountIndex 53 | window.storageKey = storageKey 54 | window.StorageBond = StorageBond 55 | window.TransactionBond = TransactionBond 56 | window.lookup = query => { 57 | let q = secretStore().find(query) 58 | if (q) { 59 | return q.account 60 | } else { 61 | return runtime.indices.ss58Decode(query) 62 | } 63 | } 64 | } 65 | 66 | module.exports = { 67 | ss58Decode, ss58Encode, setNetworkDefault, 68 | // utils 69 | stringToSeed, stringToBytes, hexToBytes, bytesToHex, toLEHex, leHexToNumber, toLE, leToNumber, reviver, 70 | // types 71 | AccountId, AccountIndex, TransactionEra, Hash, VoteThreshold, Moment, Balance, BlockNumber, Tuple, VecU8, 72 | Permill, Perbill, 73 | pretty, encode, decode, addCodecTransform, 74 | secretStore, addressBook, 75 | post, TransactionBond, 76 | denominationInfo, 77 | nodeService, setNodeUri, 78 | metadata, 79 | // bonds 80 | initRuntime, runtime, calls, runtimePromise, callsPromise, chain, system, state, runtimeUp 81 | } -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/badgereg.json: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"fromName","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"badgeCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_newAddr","type":"address"}],"name":"setAddress","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"badge","outputs":[{"name":"addr","type":"address"},{"name":"name","type":"bytes32"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_name","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"}],"name":"AddressChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] 2 | -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/tokenreg.json: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[{"name":"_id","type":"uint256"}],"name":"token","outputs":[{"name":"addr","type":"address"},{"name":"tla","type":"string"},{"name":"base","type":"uint256"},{"name":"name","type":"string"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_tla","type":"string"},{"name":"_base","type":"uint256"},{"name":"_name","type":"string"}],"name":"register","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_fee","type":"uint256"}],"name":"setFee","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"}],"name":"meta","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_addr","type":"address"},{"name":"_tla","type":"string"},{"name":"_base","type":"uint256"},{"name":"_name","type":"string"},{"name":"_owner","type":"address"}],"name":"registerAs","outputs":[{"name":"","type":"bool"}],"payable":true,"type":"function"},{"constant":true,"inputs":[{"name":"_tla","type":"string"}],"name":"fromTLA","outputs":[{"name":"id","type":"uint256"},{"name":"addr","type":"address"},{"name":"base","type":"uint256"},{"name":"name","type":"string"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"tokenCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unregister","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_addr","type":"address"}],"name":"fromAddress","outputs":[{"name":"id","type":"uint256"},{"name":"tla","type":"string"},{"name":"base","type":"uint256"},{"name":"name","type":"string"},{"name":"owner","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"},{"name":"_key","type":"bytes32"},{"name":"_value","type":"bytes32"}],"name":"setMeta","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tla","type":"string"},{"indexed":true,"name":"id","type":"uint256"},{"indexed":false,"name":"addr","type":"address"},{"indexed":false,"name":"name","type":"string"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"tla","type":"string"},{"indexed":true,"name":"id","type":"uint256"}],"name":"Unregistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"key","type":"bytes32"},{"indexed":false,"name":"value","type":"bytes32"}],"name":"MetaChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] 2 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/ss58.js: -------------------------------------------------------------------------------- 1 | const bs58 = require('bs58') 2 | const { blake2b } = require('blakejs') 3 | const { toLE, leToNumber, stringToBytes } = require('./utils') 4 | const { AccountIndex, AccountId } = require('./types') 5 | 6 | let defaultType = 42 7 | const KNOWN_TYPES = [0, 1, 42, 43, 68, 69] 8 | 9 | const PREFIX = stringToBytes('SS58PRE') 10 | 11 | function setNetworkDefault(type) { 12 | defaultType = type 13 | } 14 | 15 | function ss58Encode(a, type = defaultType, checksumLength = null, length = null, accountId) { 16 | let payload 17 | if (KNOWN_TYPES.indexOf(type) === -1) { 18 | throw new Error('Unknown ss58 address type', type) 19 | } 20 | if (typeof a === 'number' || a instanceof AccountIndex) { 21 | let minLength = (a < (1 << 8) ? 1 : a < (1 << 16) ? 2 : a < (1 << 32) ? 4 : 8) 22 | length = length ? length : minLength 23 | if ([1, 2, 4, 8].indexOf(length) === -1) { 24 | throw new Error('Invalid length') 25 | } 26 | length = Math.max(minLength, length) 27 | if (checksumLength && typeof checksumLength !== 'number') { 28 | throw new Error('Invalid checksum length') 29 | } 30 | switch (length) { 31 | case 1: { checksumLength = 1; break; } 32 | case 2: { checksumLength = ([1, 2].indexOf(checksumLength) + 1) || 1; break; } 33 | case 4: { checksumLength = ([1, 2, 3, 4].indexOf(checksumLength) + 1) || 1; break; } 34 | case 8: { checksumLength = ([1, 2, 3, 4, 5, 6, 7, 8].indexOf(checksumLength) + 1) || 1; break; } 35 | } 36 | payload = toLE(a, length) 37 | } else if ((a instanceof AccountId || a instanceof Uint8Array) && a.length === 32) { 38 | checksumLength = 2 39 | payload = a 40 | accountId = a 41 | } else { 42 | throw new Error('Unknown item to encode as ss58. Passing back.', a) 43 | } 44 | let hash = blake2b(new Uint8Array([...PREFIX, ...((type & 1) ? accountId : new Uint8Array([type, ...payload]))])) 45 | let complete = new Uint8Array([type, ...payload, ...hash.slice(0, checksumLength)]) 46 | return bs58.encode(Buffer.from(complete)) 47 | } 48 | 49 | /// `lookupIndex` must be synchronous. If you can do that, then throw, catch outside the 50 | /// invocation and then retry once you have the result to hand. 51 | function ss58Decode(ss58, lookupIndex) { 52 | let a 53 | try { 54 | a = bs58.decode(ss58) 55 | } 56 | catch (e) { 57 | return null 58 | } 59 | 60 | let type = a[0] 61 | if (KNOWN_TYPES.indexOf(type) === -1) { 62 | return null 63 | } 64 | 65 | if (a.length < 3) { 66 | return null 67 | //throw new Error('Invalid length of payload for address', a.length) 68 | } 69 | let length = a.length <= 3 70 | ? 1 71 | : a.length <= 5 72 | ? 2 73 | : a.length <= 9 74 | ? 4 75 | : a.length <= 17 76 | ? 8 77 | : 32 78 | let checksumLength = a.length - 1 - length 79 | 80 | let payload = a.slice(1, 1 + length) 81 | let checksum = a.slice(1 + a.length) 82 | 83 | let accountId 84 | if (length === 32) { 85 | accountId = payload 86 | } 87 | 88 | let result = length < 32 89 | ? new AccountIndex(leToNumber(payload)) 90 | : new AccountId(payload) 91 | 92 | if (a[0] % 1 && !accountId && !lookupIndex) { 93 | return null 94 | } 95 | let hash = blake2b(new Uint8Array([...PREFIX , ... (a[0] % 1 ? (accountId || lookupIndex(result)) : a.slice(0, 1 + length))])) 96 | 97 | for (var i = 0; i < checksumLength; ++i) { 98 | if (hash[i] !== a[1 + length + i]) { 99 | // invalid checksum 100 | return null 101 | } 102 | } 103 | 104 | return result 105 | } 106 | 107 | module.exports = { ss58Decode, ss58Encode, setNetworkDefault } 108 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/types.js: -------------------------------------------------------------------------------- 1 | const { toLE } = require('./utils') 2 | 3 | class VecU8 extends Uint8Array { 4 | toJSON() { 5 | return { _type: 'VecU8', data: Array.from(this) } 6 | } 7 | } 8 | 9 | class AccountId extends Uint8Array { 10 | toJSON() { 11 | return { _type: 'AccountId', data: Array.from(this) } 12 | } 13 | compare (other) { 14 | return this.length === other.length && this.every((v, i) => other[i] === v) 15 | } 16 | memberOf (set) { 17 | return set.find(item => this.compare(item)) !== undefined 18 | } 19 | } 20 | 21 | class Hash extends Uint8Array { 22 | toJSON() { 23 | return { _type: 'Hash', data: Array.from(this) } 24 | } 25 | } 26 | 27 | class Signature extends Uint8Array { 28 | toJSON() { 29 | return { _type: "Signature", data: Array.from(this) } 30 | } 31 | } 32 | 33 | class VoteThreshold extends String { 34 | toJSON() { 35 | return { _type: 'VoteThreshold', data: this + ''} 36 | } 37 | } 38 | 39 | class RewardDestination extends String { 40 | toJSON() { 41 | return { _type: 'RewardDestination', data: this + ''} 42 | } 43 | } 44 | 45 | class BlockNumber extends Number { 46 | toJSON() { 47 | return { _type: 'BlockNumber', data: this+0 } 48 | } 49 | } 50 | 51 | class AccountIndex extends Number { 52 | toJSON() { 53 | return { _type: 'AccountIndex', data: this+0 } 54 | } 55 | } 56 | 57 | class Tuple extends Array { 58 | toJSON() { 59 | return { _type: 'Tuple', data: Array.from(this) } 60 | } 61 | } 62 | 63 | class SlashPreference extends Number { 64 | toJSON() { return { _type: 'SlashPreference', data: this+0 } } 65 | } 66 | 67 | class Perbill extends Number { 68 | toJSON() { return { _type: 'Perbill', data: this+0 } } 69 | } 70 | 71 | class Permill extends Number { 72 | toJSON() { return { _type: 'Permill', data: this+0 } } 73 | } 74 | 75 | class Moment extends Date { 76 | constructor(seconds) { 77 | super(seconds * 1000) 78 | this.number = seconds 79 | } 80 | toJSON() { 81 | return { _type: 'Moment', data: this.number } 82 | } 83 | } 84 | 85 | class Balance extends Number { 86 | toJSON() { return { _type: 'Balance', data: this+0 } } 87 | add(b) { return new Balance(this + b) } 88 | sub(b) { return new Balance(this - b) } 89 | } 90 | 91 | class TransactionEra { 92 | constructor (period, phase) { 93 | if (typeof period === 'number' && typeof phase === 'number') { 94 | this.period = 2 << Math.min(15, Math.max(1, Math.ceil(Math.log2(period)) - 1)) 95 | this.phase = phase % this.period 96 | } 97 | } 98 | 99 | encode() { 100 | if (typeof this.period === 'number' && typeof this.phase === 'number') { 101 | let l = Math.min(15, Math.max(1, Math.ceil(Math.log2(this.period)) - 1)) 102 | let factor = Math.max(1, this.period >> 12) 103 | let res = toLE((Math.floor(this.phase / factor) << 4) + l, 2) 104 | return res 105 | } else { 106 | return new Uint8Array([0]) 107 | } 108 | } 109 | } 110 | 111 | function reviver(key, bland) { 112 | if (typeof bland == 'object' && bland) { 113 | switch (bland._type) { 114 | case 'VecU8': return new VecU8(bland.data); 115 | case 'AccountId': return new AccountId(bland.data); 116 | case 'Hash': return new Hash(bland.data); 117 | case 'Signature': return new Signature(bland.data); 118 | case 'VoteThreshold': return new VoteThreshold(bland.data); 119 | case 'SlashPreference': return new SlashPreference(bland.data); 120 | case 'Perbill': return new Perbill(bland.data); 121 | case 'Permill': return new Permill(bland.data); 122 | case 'Moment': return new Moment(bland.data); 123 | case 'Tuple': return new Tuple(bland.data); 124 | case 'Balance': return new Balance(bland.data); 125 | case 'BlockNumber': return new BlockNumber(bland.data); 126 | case 'AccountIndex': return new AccountIndex(bland.data); 127 | case 'Payee': return new Payee(bland.data); 128 | } 129 | } 130 | return bland; 131 | } 132 | 133 | module.exports = { VecU8, AccountId, Hash, Signature, VoteThreshold, SlashPreference, Moment, Balance, 134 | BlockNumber, AccountIndex, Tuple, TransactionEra, Perbill, Permill, reviver, RewardDestination } 135 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/transact.js: -------------------------------------------------------------------------------- 1 | const { Bond } = require('oo7') 2 | const { blake2b } = require('blakejs') 3 | const { SubscriptionBond } = require('./subscriptionBond') 4 | const { encode } = require('./codec') 5 | const { secretStore } = require('./secretStore') 6 | const { TransactionEra, AccountIndex } = require('./types') 7 | const { runtimeUp, runtime, chain } = require('./bonds') 8 | const { bytesToHex } = require('./utils') 9 | 10 | class TransactionBond extends SubscriptionBond { 11 | constructor (data) { 12 | super('author_submitAndWatchExtrinsic', ['0x' + bytesToHex(data)], null, {sending: true}) 13 | } 14 | } 15 | 16 | function composeTransaction (sender, call, index, era, checkpoint, senderAccount, compact) { 17 | return new Promise((resolve, reject) => { 18 | if (typeof sender == 'string') { 19 | sender = ss58Decode(sender) 20 | } 21 | if (sender instanceof Uint8Array && sender.length == 32) { 22 | senderAccount = sender 23 | } else if (!senderAccount) { 24 | reject(`Invalid senderAccount when sender is account index`) 25 | } 26 | console.log("composing transaction", senderAccount, index, call, era, checkpoint); 27 | let e = encode([ 28 | index, call, era, checkpoint 29 | ], [ 30 | 'Compact', 'Call', 'TransactionEra', 'Hash' 31 | ]) 32 | 33 | let legacy = runtime.version.isReady() && ( 34 | runtime.version._value.specName == 'node' && runtime.version._value.specVersion < 17 35 | || runtime.version._value.specName == 'polkadot' && runtime.version._value.specVersion < 107 36 | ) 37 | if (!legacy && e.length > 256) { 38 | console.log(`Oversize transaction (length ${e.length} bytes). Hashing.`) 39 | e = blake2b(e, null, 32) 40 | } 41 | 42 | let signature = secretStore().sign(senderAccount, e) 43 | console.log("encoding transaction", sender, index, era, call); 44 | let signedData = encode(encode({ 45 | _type: 'Transaction', 46 | version: 0x81, 47 | sender, 48 | signature, 49 | index, 50 | era, 51 | call 52 | }), 'Vec') 53 | console.log("signed:", bytesToHex(signedData)) 54 | setTimeout(() => resolve(signedData), 1000) 55 | }) 56 | } 57 | 58 | // tx = { 59 | // sender 60 | // call 61 | // longevity? 62 | // index? 63 | // } 64 | function post(tx) { 65 | return Bond.all([tx, chain.height, runtimeUp]).map(([o, height, unused]) => { 66 | if (o instanceof Uint8Array) { 67 | // already assembled and signed 68 | return o 69 | } 70 | 71 | console.log("Posting:", o, height) 72 | 73 | let {sender, call, index, longevity, compact} = o 74 | // defaults 75 | longevity = typeof longevity === 'undefined' ? 256 : longevity 76 | compact = typeof compact === 'undefined' ? true : compact 77 | 78 | let senderIsIndex = typeof sender === 'number' || sender instanceof AccountIndex 79 | 80 | let senderAccount = senderIsIndex 81 | ? runtime.indices.lookup(sender) 82 | : sender 83 | if (senderIsIndex && !compact) { 84 | sender = senderAccount 85 | } 86 | 87 | let era 88 | let eraHash 89 | if (longevity === true) { 90 | era = new TransactionEra; 91 | eraHash = chain.hash(0) 92 | } else { 93 | // use longevity with height to determine era and eraHash 94 | let l = Math.min(15, Math.max(1, Math.ceil(Math.log2(longevity)) - 1)) 95 | let period = 2 << l 96 | let factor = Math.max(1, period >> 12) 97 | let Q = (n, d) => Math.floor(n / d) * d 98 | let eraNumber = Q(height, factor) 99 | let phase = eraNumber % period 100 | era = new TransactionEra(period, phase) 101 | eraHash = chain.hash(eraNumber) 102 | } 103 | return { 104 | sender, 105 | call, 106 | era, 107 | eraHash, 108 | index: index || runtime.system.accountNonce(senderAccount), 109 | senderAccount, 110 | compact 111 | } 112 | }, 2).latched(false).map(o => 113 | o && (o instanceof Uint8Array ? o : composeTransaction(o.sender, o.call, o.index, o.era, o.eraHash, o.senderAccount, o.compact)) 114 | ).map(composed => { 115 | return composed ? new TransactionBond(composed) : { signing: true } 116 | }) 117 | } 118 | 119 | module.exports = { composeTransaction, post, TransactionBond }; -------------------------------------------------------------------------------- /packages/oo7-substrate/src/utils.js: -------------------------------------------------------------------------------- 1 | function stringToSeed(s) { 2 | if (s.match(/^0x[0-9a-fA-F]{64}$/)) { 3 | return hexToBytes(s) 4 | } 5 | var data = new Uint8Array(32); 6 | data.fill(32); 7 | for (var i = 0; i < s.length; i++){ 8 | data[i] = s.charCodeAt(i); 9 | } 10 | return data; 11 | } 12 | function stringToBytes(s) { 13 | var data = new Uint8Array(s.length); 14 | for (var i = 0; i < s.length; i++){ 15 | data[i] = s.charCodeAt(i); 16 | } 17 | return data; 18 | } 19 | function hexToBytes(str) { 20 | if (!str) { 21 | return new Uint8Array(); 22 | } 23 | var a = []; 24 | for (var i = str.startsWith('0x') ? 2 : 0, len = str.length; i < len; i += 2) { 25 | a.push(parseInt(str.substr(i, 2), 16)); 26 | } 27 | 28 | return new Uint8Array(a); 29 | } 30 | function bytesToHex(uint8arr) { 31 | if (!uint8arr) { 32 | return ''; 33 | } 34 | var hexStr = ''; 35 | for (var i = 0; i < uint8arr.length; i++) { 36 | var hex = (uint8arr[i] & 0xff).toString(16); 37 | hex = (hex.length === 1) ? '0' + hex : hex; 38 | hexStr += hex; 39 | } 40 | 41 | return hexStr.toLowerCase(); 42 | } 43 | function toLEHex(val, bytes) { 44 | let be = ('00'.repeat(bytes) + val.toString(16)).slice(-bytes * 2); 45 | var le = ''; 46 | for (var i = 0; i < be.length; i += 2) { 47 | le = be.substr(i, 2) + le; 48 | } 49 | return le; 50 | } 51 | function leHexToNumber(le) { 52 | var be = ''; 53 | for (var i = le.startsWith('0x') ? 2 : 0; i < le.length; i += 2) { 54 | be = le.substr(i, 2) + be; 55 | } 56 | return Number.parseInt(be, 16); 57 | } 58 | 59 | function toLE(val, bytes) { 60 | let flip = false; 61 | if (val < 0) { 62 | val = -val - 1; 63 | flip = true; 64 | } 65 | 66 | let r = new Uint8Array(bytes); 67 | for (var o = 0; o < bytes; ++o) { 68 | r[o] = val % 256; 69 | if (flip) { 70 | r[o] = ~r[o] & 0xff; 71 | } 72 | val /= 256; 73 | } 74 | return r; 75 | } 76 | 77 | function leToNumber(le) { 78 | let r = 0; 79 | let a = 1; 80 | le.forEach(x => { r += x * a; a *= 256; }); 81 | return r; 82 | } 83 | 84 | function leToSigned(_le) { 85 | let le = _le.slice(); 86 | let sign = 1; 87 | let r = 0; 88 | if ((le[le.length - 1] & 128) === 128) { 89 | // biggest bit of biggest byte is on - we're negative - invert and add one 90 | le = le.map(n => ~n & 0xff); 91 | r = 1; 92 | sign = -1; 93 | } 94 | let a = 1; 95 | le.forEach(x => { r += x * a; a *= 256; }); 96 | return r * sign; 97 | } 98 | 99 | function injectChunkUtils() { 100 | String.prototype.chunks = function(size) { 101 | var r = []; 102 | var count = this.length / size; 103 | for (var i = 0; i < count; ++i) { 104 | r.push(this.substr(i * size, size)); 105 | } 106 | return r; 107 | } 108 | 109 | String.prototype.mapChunks = function(sizes, f) { 110 | var r = []; 111 | var count = this.length / sizes.reduce((a, b) => a + b, 0); 112 | var offset = 0; 113 | for (var i = 0; i < count; ++i) { 114 | r.push(f(sizes.map(s => { 115 | let r = this.substr(offset, s); 116 | offset += s; 117 | return r; 118 | }))); 119 | } 120 | return r; 121 | } 122 | 123 | Uint8Array.prototype.mapChunks = function(sizes, f) { 124 | var r = []; 125 | var count = this.length / sizes.reduce((a, b) => a + b, 0); 126 | var offset = 0; 127 | for (var i = 0; i < count; ++i) { 128 | r.push(f(sizes.map(s => { 129 | offset += s; 130 | return this.slice(offset - s, offset); 131 | }))); 132 | } 133 | return r; 134 | } 135 | } 136 | 137 | function siPrefix(pot) { 138 | switch (pot) { 139 | case -24: return 'y' 140 | case -21: return 'z' 141 | case -18: return 'a' 142 | case -15: return 'f' 143 | case -12: return 'p' 144 | case -9: return 'n' 145 | case -6: return 'µ' 146 | case -3: return 'm' 147 | case 0: return '' 148 | case 3: return 'k' 149 | case 6: return 'M' 150 | case 9: return 'G' 151 | case 12: return 'T' 152 | case 15: return 'P' 153 | case 18: return 'E' 154 | case 21: return 'Z' 155 | case 24: return 'Y' 156 | } 157 | } 158 | 159 | module.exports = { stringToSeed, stringToBytes, hexToBytes, bytesToHex, toLEHex, leHexToNumber, toLE, leToNumber, leToSigned, injectChunkUtils, siPrefix } 160 | -------------------------------------------------------------------------------- /packages/oo7/test/ipc.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-return-assign */ 2 | 3 | require('chai').should(); 4 | 5 | const { Bond, BondCache, BondProxy } = require('../index'); 6 | 7 | class Setup { 8 | constructor () { 9 | let messageQueue = []; 10 | let parentWindow = { localStorage: {}, messages: [], listeners: { message: [] } }; 11 | parentWindow.addEventListener = (type, f) => { 12 | if (parentWindow.listeners[type]) { 13 | parentWindow.listeners[type].push(f); 14 | } 15 | }; 16 | let childWindow = { localStorage: {}, parent: parentWindow, messages: [], listeners: { message: [] } }; 17 | childWindow.addEventListener = (type, f) => { 18 | if (childWindow.listeners[type]) { 19 | childWindow.listeners[type].push(f); 20 | } 21 | }; 22 | 23 | parentWindow.postMessage = m => messageQueue.push( 24 | () => (parentWindow.listeners.message || []).forEach(l => 25 | l({source: childWindow, data: m}) 26 | ) 27 | ); 28 | childWindow.postMessage = m => messageQueue.push( 29 | () => (childWindow.listeners.message || []).forEach(l => 30 | l({source: parentWindow, data: m}) 31 | ) 32 | ); 33 | 34 | this.messageQueue = messageQueue; 35 | this.parentWindow = parentWindow; 36 | this.childWindow = childWindow; 37 | } 38 | 39 | play () { 40 | while (this.messageQueue.length > 0) { 41 | this.messageQueue.splice(0, 1)[0](); 42 | } 43 | } 44 | } 45 | 46 | describe('BondCache', function () { 47 | it('should have working scene', () => { 48 | let scene = new Setup(); 49 | 50 | let roundTripsComplete = 0; 51 | scene.parentWindow.addEventListener('message', m => { if (m.data === 'ping') m.source.postMessage('pong'); }); 52 | scene.parentWindow.addEventListener('message', m => { if (m.data === 'ping') m.source.postMessage('pong'); }); 53 | scene.childWindow.addEventListener('message', m => { if (m.data === 'pong') roundTripsComplete++; }); 54 | scene.childWindow.addEventListener('message', m => { if (m.data === 'pong') roundTripsComplete++; }); 55 | scene.parentWindow.postMessage('ping'); 56 | scene.play(); 57 | 58 | roundTripsComplete.should.equal(4); 59 | }); 60 | it('should work', () => { 61 | let scene = new Setup(); 62 | 63 | let fireBonds = {}; 64 | class FireBond extends Bond { 65 | constructor (uuid) { 66 | const cacheConfig = { 67 | id: uuid, 68 | stringify: JSON.stringify, 69 | parse: JSON.parse 70 | }; 71 | super(true, cacheConfig); 72 | } 73 | initialise () { 74 | if (typeof fireBonds[this._uuid] === 'undefined') { 75 | fireBonds[this._uuid] = []; 76 | } 77 | fireBonds[this._uuid].push(this); 78 | } 79 | finalise () { 80 | fireBonds[this._uuid].splice(fireBonds[this._uuid].indexOf(this), 1); 81 | if (fireBonds[this._uuid].length === 0) { 82 | delete fireBonds[this._uuid]; 83 | } 84 | } 85 | } 86 | FireBond.fire = (uuid, value) => fireBonds[uuid].forEach(b => b.trigger(value)); 87 | 88 | let fireInstance = new FireBond('test/fireInstance'); 89 | fireInstance._noCache = true; 90 | function fromUuid(uuid) { 91 | if (uuid === 'test/fireInstance') { return fireInstance; } 92 | return null; 93 | } 94 | 95 | Object.keys(fireBonds).length.should.equal(0); 96 | 97 | let proxy = new BondProxy('test/', fromUuid, scene.parentWindow); 98 | let cache = new BondCache(undefined, 'test/', scene.childWindow); 99 | Bond.cache = cache; 100 | let childBond = new FireBond('test/fireInstance'); 101 | 102 | Object.keys(fireBonds).length.should.equal(0); 103 | 104 | { 105 | let x = 0; 106 | let xt = childBond.tie(n => x = n); 107 | 108 | scene.play(); 109 | 110 | fireBonds['test/fireInstance'].length.should.equal(1); 111 | fireBonds['test/fireInstance'][0].should.equal(fireInstance); 112 | 113 | // Server fires. 114 | FireBond.fire('test/fireInstance', 69); 115 | fireInstance._value.should.equal(69); 116 | 117 | x.should.equal(0); 118 | 119 | scene.play(); 120 | x.should.equal(69); 121 | 122 | childBond.untie(xt); 123 | fireBonds['test/fireInstance'].length.should.equal(1); 124 | 125 | scene.play(); 126 | Object.keys(fireBonds).length.should.equal(0); 127 | } 128 | }); 129 | }); 130 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/srml/staking.js: -------------------------------------------------------------------------------- 1 | const { Bond, TransformBond } = require('oo7') 2 | const { ss58Encode } = require('../ss58') 3 | const { Balance } = require('../types') 4 | const balancesModule = require('./balances') 5 | const sessionModule = require('./session') 6 | 7 | function augment (runtime, chain) { 8 | sessionModule.augment(runtime, chain) 9 | balancesModule.augment(runtime, chain) 10 | let session = runtime.session 11 | let staking = runtime.staking 12 | let balances = runtime.balances 13 | if (staking._extras) { 14 | return 15 | } else { 16 | staking._extras = true 17 | } 18 | 19 | oldStakers = staking.stakers 20 | staking.stakers = who => oldStakers(who, false) 21 | oldValidators = staking.validators 22 | staking.validators = who => oldValidators(who, false) 23 | staking.validators.all = oldValidators.all 24 | staking.validators.head = oldValidators.head 25 | oldNominators = staking.nominators 26 | staking.nominators = who => oldNominators(who, false) 27 | staking.nominators.all = oldNominators.all 28 | staking.nominators.head = oldNominators.head 29 | 30 | staking.thisSessionReward = new TransformBond( 31 | (r, l) => Math.round(r / l), 32 | [ 33 | staking.sessionReward, 34 | session.lateness 35 | ] 36 | ) 37 | 38 | staking.bonding = either => new TransformBond( 39 | (ledger, controller) => { 40 | if (ledger) { // was controller 41 | return { 42 | ledger, 43 | controller: either, 44 | key: 'controller' 45 | } 46 | } else if (controller) { // was stash 47 | return { 48 | ledger: staking.ledger(controller), 49 | controller, 50 | key: 'stash' 51 | } 52 | } else { 53 | return undefined 54 | } 55 | }, 56 | [staking.ledger(either), staking.bonded(either)] 57 | ).subscriptable(2) 58 | 59 | staking.info = either => new TransformBond( 60 | ({bonding, vals, noms, slashCount, payee, currentElected, invulnerables}) => bonding && ({ 61 | ledger: bonding.ledger, 62 | controller: bonding.controller, 63 | key: bonding.key, 64 | role: vals ? { validator: vals } : noms ? { nominator: noms } : { idle: 'null' }, 65 | payee 66 | }), 67 | [staking.bonding(either).map(bonding => bonding ? ({ 68 | bonding, 69 | vals: staking.validators(bonding.ledger.stash), 70 | noms: staking.nominators(bonding.ledger.stash), 71 | payee: staking.payee(bonding.ledger.stash), 72 | }) : ({ 73 | bonding: null 74 | }))] 75 | ).subscriptable(2) 76 | 77 | staking.exposure = new TransformBond((validators, invulns) => { 78 | let r = {} 79 | validators.forEach(validator => { 80 | r[ss58Encode(validator)] = new TransformBond((stakers, controller) => Object.assign({ 81 | validator, 82 | controller, 83 | invulnerable: validator.memberOf(invulns), 84 | }, stakers || {others: [], own: new Balance(0), total: new Balance(0)}), [staking.stakers(validator), staking.bonded(validator)]) 85 | }) 86 | return r 87 | }, [staking.currentElected, staking.invulnerables]).subscriptable(2) 88 | 89 | staking.exposureOf = nominator => new TransformBond((exposure, nominator, slotStake) => { 90 | let slot = exposure[ss58Encode(nominator)]; 91 | if (slot) { 92 | // Validator 93 | return { validating: slot } 94 | } else { 95 | // Maybe a nominator? 96 | let nominations = {} 97 | Object.keys(exposure).forEach(k => { 98 | let slot = exposure[k] 99 | let n = slot.others.find(x => x.who.compare(nominator)) 100 | if (n) { 101 | nominations[k] = Object.assign({ 102 | share: n.value 103 | }, slot) 104 | } 105 | }) 106 | if (Object.keys(nominations).length > 0) { 107 | return { nominating: nominations } 108 | } else { 109 | return { idle: true } 110 | } 111 | } 112 | }, [staking.exposure, nominator, staking.slotStake]).subscriptable(2) 113 | 114 | staking.eraLength = new TransformBond( 115 | (a, b) => a * b, 116 | [ 117 | staking.sessionsPerEra, 118 | session.sessionLength 119 | ]) 120 | 121 | staking.eraSessionsRemaining = new TransformBond( 122 | (spe, si, lec) => (spe - 1 - (si - lec) % spe), 123 | [ 124 | staking.sessionsPerEra, 125 | session.currentIndex, 126 | staking.lastEraLengthChange 127 | ]) 128 | 129 | staking.eraBlocksRemaining = new TransformBond( 130 | (sl, sr, br) => br + sl * sr, 131 | [ 132 | session.sessionLength, 133 | staking.eraSessionsRemaining, 134 | session.blocksRemaining 135 | ]) 136 | } 137 | 138 | module.exports = { augment } -------------------------------------------------------------------------------- /packages/polkadot-identicon/src/index.jsx: -------------------------------------------------------------------------------- 1 | const React = require('react') 2 | const {ReactiveComponent} = require('oo7-react') 3 | const {ss58Decode, ss58Encode} = require('oo7-substrate') 4 | const {blake2b} = require('blakejs') 5 | 6 | const zero = blake2b(new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])) 7 | 8 | const copyToClipboard = str => { 9 | const el = document.createElement('textarea'); 10 | el.value = str; 11 | document.body.appendChild(el); 12 | el.select(); 13 | document.execCommand('copy'); 14 | document.body.removeChild(el); 15 | }; 16 | 17 | export default class Identicon extends ReactiveComponent { 18 | constructor () { 19 | super(["account"]) 20 | } 21 | render () { 22 | let s = 64 23 | let c = s / 2 24 | let r = this.props.sixPoint ? s / 2 / 8 * 5 : (s / 2 / 4 * 3) 25 | let rroot3o2 = r * Math.sqrt(3) / 2 26 | let ro2 = r / 2 27 | let rroot3o4 = r * Math.sqrt(3) / 4 28 | let ro4 = r / 4 29 | let r3o4 = r * 3 / 4 30 | 31 | let z = s / 64 * 5 32 | let schema = { 33 | target: { freq: 1, colors: [0, 28, 0, 0, 28, 0, 0, 28, 0, 0, 28, 0, 0, 28, 0, 0, 28, 0, 1] }, 34 | cube: { freq: 20, colors: [0, 1, 3, 2, 4, 3, 0, 1, 3, 2, 4, 3, 0, 1, 3, 2, 4, 3, 5] }, 35 | quazar: { freq: 16, colors: [1, 2, 3, 1, 2, 4, 5, 5, 4, 1, 2, 3, 1, 2, 4, 5, 5, 4, 0] }, 36 | flower: { freq: 32, colors: [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3] }, 37 | cyclic: { freq: 32, colors: [0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6] }, 38 | vmirror: { freq: 128, colors: [0, 1, 2, 3, 4, 5, 3, 4, 2, 0, 1, 6, 7, 8, 9, 7, 8, 6, 10] }, 39 | hmirror: { freq: 128, colors: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 8, 6, 7, 5, 3, 4, 2, 11] } 40 | } 41 | 42 | let total = Object.keys(schema).map(k => schema[k].freq).reduce((a, b) => a + b) 43 | let findScheme = d => { 44 | let cum = 0 45 | let ks = Object.keys(schema) 46 | for (let i in ks) { 47 | let n = schema[ks[i]].freq 48 | cum += n; 49 | if (d < cum) { 50 | return schema[ks[i]] 51 | } 52 | } 53 | throw "Impossible" 54 | } 55 | 56 | let id = typeof this.state.account == 'string' ? ss58Decode(this.state.account) : this.state.account 57 | if (!(typeof id == 'object' && id && id instanceof Uint8Array && id.length == 32)) { 58 | return 67 | } 68 | let ss58 = ss58Encode(id); 69 | id = Array.from(blake2b(id)).map((x, i) => (x + 256 - zero[i]) % 256) 70 | 71 | let sat = (Math.floor(id[29] * 70 / 256 + 26) % 80) + 30 72 | let d = Math.floor((id[30] + id[31] * 256) % total) 73 | let scheme = findScheme(d) 74 | let palette = Array.from(id).map((x, i) => { 75 | let b = (x + i % 28 * 58) % 256 76 | if (b == 0) { 77 | return '#444' 78 | } 79 | if (b == 255) { 80 | return 'transparent' 81 | } 82 | let h = Math.floor(b % 64 * 360 / 64) 83 | let l = [53, 15, 35, 75][Math.floor(b / 64)] 84 | return `hsl(${h}, ${sat}%, ${l}%)` 85 | }) 86 | 87 | let rot = (id[28] % 6) * 3 88 | 89 | let colors = scheme.colors.map((_, i) => palette[scheme.colors[i < 18 ? (i + rot) % 18 : 18]]) 90 | 91 | let i = 0; 92 | return ( { copyToClipboard(ss58); this.props.onCopied && this.props.onCopied(ss58); }} 101 | > 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | ) 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /packages/oo7/src/bondProxy.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // The parent-side cache-server to which child-side BondCaches can connect. 16 | // Will send messages of the form { bondCacheUpdate: { uuid: '...', value: ... }} 17 | // value, if provided is the actual Bond value, not a stringification of it. 18 | // Will try to send these only for UUIDs that it knows the child is interested 19 | // in - child can register interest with a message { useBond: uuid } and 20 | // unregister interest with { dropBond: uuid }. 21 | // 22 | // If you construct BondCache passing a deferParentPrefix arg, then it's up to 23 | // you to ensure that the parent actually has a BondCacheProxy constructed. If 24 | // it doesn't, things will go screwy. 25 | 26 | let consoleDebug = typeof window !== 'undefined' && window.debugging ? console.debug : () => {}; 27 | 28 | // Prepare value `v` for being sent over `window.postMessage`. 29 | function prepUpdate (uuid, bond) { 30 | let value = bond.isReady() ? bond._value : undefined; 31 | 32 | if (typeof value === 'object' && value !== null && bond._stringify) { 33 | return { uuid, valueString: bond._stringify(value) }; 34 | } 35 | 36 | return { uuid, value }; 37 | } 38 | 39 | class BondProxy { 40 | constructor (deferParentPrefix, fromUuid, surrogateWindow = null) { 41 | this.bonds = {}; 42 | this.deferParentPrefix = deferParentPrefix; 43 | this.fromUuid = fromUuid; 44 | this.window = surrogateWindow || (typeof window === 'undefined' ? null : window); 45 | 46 | // set up listener so that we get notified by our child. 47 | this.window.addEventListener('message', this.onMessage.bind(this)); 48 | } 49 | 50 | onMessage (e) { 51 | if (e.source.parent !== this.window) { 52 | console.warn(`BondProxy.onMessage: Unknown client at ${e.origin} attempting to message proxy with ${e.data}. Ignoring.`); 53 | return; 54 | } 55 | if (typeof e.data === 'object' && e.data !== null) { 56 | consoleDebug('BondProxy.onMessage: Received message from child: ', e.data); 57 | if (e.data.helloBondProxy) { 58 | e.source.postMessage({ bondProxyInfo: { deferParentPrefix: this.deferParentPrefix } }, '*'); 59 | } else if (typeof e.data.useBond === 'string') { 60 | let uuid = e.data.useBond; 61 | let entry = this.bonds[uuid]; 62 | consoleDebug('BondProxy.onMessage: useBond ', uuid, entry); 63 | if (entry) { 64 | // already here - increase refs. 65 | if (entry.users.indexOf(e.source) !== -1) { 66 | console.warn(`BondProxy.onMessage: Source using UUID ${uuid} more than once.`); 67 | } 68 | consoleDebug('BondProxy.onMessage: Another user'); 69 | entry.users.push(e.source); 70 | } else { 71 | // create it. 72 | let newBond = this.fromUuid(uuid); 73 | if (newBond) { 74 | consoleDebug('BondProxy.onMessage: Creating new bond'); 75 | entry = this.bonds[uuid] = { bond: newBond, users: [e.source] }; 76 | entry.notifyKey = newBond.notify(() => { 77 | let bondCacheUpdate = prepUpdate(uuid, newBond); 78 | consoleDebug('BondProxy.onMessage: Bond changed. Updating child:', bondCacheUpdate); 79 | entry.users.forEach(u => 80 | u.postMessage({ bondCacheUpdate }, '*') 81 | ); 82 | }); 83 | } else { 84 | console.warn(`BondProxy.onMessage: UUID ${uuid} is unknown - cannot create a Bond for it.`); 85 | e.source.postMessage({ bondUnknown: { uuid } }, '*'); 86 | return; 87 | } 88 | } 89 | let bondCacheUpdate = prepUpdate(uuid, entry.bond); 90 | consoleDebug('BondProxy.onMessage: Posting update back to child', bondCacheUpdate); 91 | e.source.postMessage({ bondCacheUpdate }, '*'); 92 | } else if (typeof e.data.dropBond === 'string') { 93 | let uuid = e.data.dropBond; 94 | let entry = this.bonds[uuid]; 95 | consoleDebug('BondProxy.onMessage: dropBond ', uuid, entry); 96 | if (entry) { 97 | let i = entry.users.indexOf(e.source); 98 | if (i !== -1) { 99 | consoleDebug('BondProxy.onMessage: Removing child from updates list'); 100 | entry.users.splice(i, 1); 101 | } else { 102 | console.warn(`BondProxy.onMessage: Source asking to drop UUID ${uuid} that they do not track. They probably weren't getting updates.`); 103 | } 104 | if (entry.users.length === 0) { 105 | consoleDebug('BondProxy.onMessage: No users - retiring bond'); 106 | entry.bond.unnotify(entry.notifyKey); 107 | delete this.bonds[uuid]; 108 | } 109 | } else { 110 | console.warn(`BondProxy.onMessage: Cannot drop a Bond (${uuid}) that we do not track.`); 111 | } 112 | } 113 | } 114 | } 115 | } 116 | 117 | module.exports = BondProxy; 118 | -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/registry.json: -------------------------------------------------------------------------------- 1 | [{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"canReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_new","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"bytes32"}],"name":"setData","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"}],"name":"confirmReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserve","outputs":[{"name":"success","type":"bool"}],"payable":true,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"}],"name":"drop","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_amount","type":"uint256"}],"name":"setFee","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_to","type":"address"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getData","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"reserved","outputs":[{"name":"reserved","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"drain","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"proposeReverse","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"hasReverse","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"}],"name":"getUint","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"fee","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_name","type":"bytes32"}],"name":"getReverse","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_data","type":"address"}],"name":"reverse","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"uint256"}],"name":"setUint","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"string"},{"name":"_who","type":"address"}],"name":"confirmReverseAs","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"removeReverse","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_name","type":"bytes32"},{"name":"_key","type":"string"},{"name":"_value","type":"address"}],"name":"setAddress","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"Drained","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"amount","type":"uint256"}],"name":"FeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"string"},{"indexed":true,"name":"reverse","type":"address"}],"name":"ReverseRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Reserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"oldOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"owner","type":"address"}],"name":"Dropped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"name","type":"bytes32"},{"indexed":true,"name":"key","type":"string"},{"indexed":false,"name":"plainKey","type":"string"}],"name":"DataChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"current","type":"address"}],"name":"NewOwner","type":"event"}] 2 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/nodeService.js: -------------------------------------------------------------------------------- 1 | const { Bond } = require('oo7') 2 | const WebSocket = require('isomorphic-ws') 3 | 4 | const subscriptionKey = { 5 | author_submitAndWatchExtrinsic: { 6 | notification: 'author_extrinsicUpdate', 7 | subscribe: 'author_submitAndWatchExtrinsic', 8 | unsubscribe: 'author_unwatchExtrinsic' 9 | }, 10 | state_storage: { 11 | notification: 'state_storage', 12 | subscribe: 'state_subscribeStorage', 13 | unsubscribe: 'state_unsubscribeStorage' 14 | }, 15 | chain_newHead: { 16 | notification: 'chain_newHead', 17 | subscribe: 'chain_subscribeNewHead', 18 | unsubscribe: 'chain_unsubscribeNewHead' 19 | }, 20 | chain_finalizedHead: { 21 | notification: 'chain_finalizedHead', 22 | subscribe: 'chain_subscribeFinalizedHeads', 23 | unsubscribe: 'chain_unsubscribeFinalizedHeads' 24 | }, 25 | state_runtimeVersion: { 26 | notification: 'state_runtimeVersion', 27 | subscribe: 'state_subscribeRuntimeVersion', 28 | unsubscribe: 'state_unsubscribeRuntimeVersion' 29 | } 30 | } 31 | 32 | let uri = ['ws://127.0.0.1:9944'] 33 | 34 | function setNodeUri(u) { 35 | if (uri === u) return 36 | uri = u 37 | if (!s_nodeService) return // prevent instanciating 38 | s_nodeService.uri = u 39 | s_nodeService.uriIndex = 0 40 | s_nodeService.uriChanged = true 41 | s_nodeService.start() 42 | } 43 | 44 | class NodeService { 45 | constructor (uri) { 46 | this.subscriptions = {} 47 | this.cancelations = {} 48 | this.pendingCancelations = {} 49 | this.theirIds = {} 50 | this.onReply = {} 51 | this.onceOpen = [] 52 | this.index = 1 53 | this.uriIndex = 0 54 | this.backoff = 0 55 | this.uri = uri 56 | this.status = new Bond 57 | this.start(uri[0]) 58 | } 59 | 60 | start (uri = this.uri[0]) { 61 | if (this.ws) { 62 | this.ws.close() 63 | delete this.ws 64 | } 65 | 66 | let that = this 67 | this.ws = new WebSocket(uri) 68 | this.ws.onopen = function () { 69 | console.log('Connection open') 70 | that.rejig() 71 | that.backoff = 0 72 | let onceOpen = that.onceOpen; 73 | that.onceOpen = [] 74 | setTimeout(() => { 75 | // console.warn("Proceessing deferred requests...") 76 | onceOpen.forEach(f => f()) 77 | }, 0) 78 | that.status.trigger({connected: uri}) 79 | } 80 | this.ws.onmessage = function (msg) { 81 | if (that.reconnect) { 82 | clearTimeout(that.reconnect) 83 | } 84 | 85 | let d = JSON.parse(msg.data) 86 | // console.log('Incoming:', d); 87 | if (d.id) { 88 | that.onReply[d.id](d) 89 | delete that.onReply[d.id]; 90 | } else if (d.method && d.params && that.subscriptions[d.params.subscription]) { 91 | that.subscriptions[d.params.subscription].callback(d.params.result, d.method) 92 | } else if (that.pendingCancelations[d.params.subscription]) { 93 | // Ok; this message was sent by them before they heard that we wanted to unsubscribe. 94 | } else { 95 | console.warn("Subscription reply without recognized ID", d.params.subscription) 96 | } 97 | 98 | // epect a message every 10 seconds or we reconnect. 99 | that.reconnect = setTimeout(() => { console.log('Reconnecting.'); that.start() }, 60000) 100 | } 101 | this.ws.onerror = (err) => { 102 | if (that.uriChanged) { 103 | delete that.uriChanged 104 | return // no reconnection if uri changed 105 | } 106 | setTimeout(() => { 107 | that.uriIndex = (that.uriIndex + 1) % that.uri.length 108 | that.start(that.uri[that.uriIndex]) 109 | }, that.backoff) 110 | that.backoff = Math.min(30000, that.backoff + 1000) 111 | that.status.trigger({error: err}) 112 | } 113 | } 114 | 115 | rejig () { 116 | let that = this 117 | let subs = this.subscriptions 118 | this.subscriptions = {} 119 | let theirIds = this.theirIds 120 | this.theirIds = {} 121 | Object.keys(theirIds).forEach(ourId => { 122 | let sub = subs[theirIds[ourId]] 123 | that.subscribe(sub.what, sub.params, sub.callback, console.warn, ourId) 124 | }) 125 | } 126 | 127 | req (method, params, callback) { 128 | let that = this 129 | let doSend = () => { 130 | let id = '' + this.index++; 131 | // console.warn("Executing request", method, params, id, callback) 132 | let msg = { 133 | "jsonrpc": "2.0", 134 | "id": id, 135 | "method": method, 136 | "params": params 137 | }; 138 | that.ws.send(JSON.stringify(msg)) 139 | 140 | that.onReply[id] = callback 141 | } 142 | 143 | if (this.ws.readyState === 1) { 144 | doSend(callback) 145 | } else { 146 | // console.warn("Defering request until connected", method, params) 147 | that.onceOpen.push(() => { 148 | doSend(callback) 149 | }) 150 | } 151 | } 152 | 153 | request (method, params = []) { 154 | let that = this 155 | return new Promise((resolve, reject) => { 156 | that.req(method, params, msg => { 157 | // console.warn("Processing request reply", method, params, msg) 158 | if (msg.error) { 159 | reject(msg.error) 160 | } else { 161 | resolve(msg.result) 162 | } 163 | }) 164 | }) 165 | } 166 | 167 | subscribe (what, params, callback, errorHandler, ourId = null) { 168 | let that = this 169 | return new Promise((resolve, reject) => { 170 | // console.log('Subscribing', ourId) 171 | this.req(subscriptionKey[what].subscribe, params, msg => { 172 | if (msg.error) { 173 | // console.log('Error subscribing', ourId) 174 | errorHandler(msg.error) 175 | } else { 176 | let theirId = msg.result 177 | // console.log('Subscribed', 'ourId=', ourId, 'theirId=', theirId) 178 | if (that.cancelations[ourId]) { 179 | // console.log('Delayed unsubscription of', ourId) 180 | that.pendingCancelations[theirId] = ourId 181 | this.req(subscriptionKey[what].unsubscribe, [theirId], () => { 182 | delete that.pendingCancelations[theirId] 183 | delete that.cancelations[ourId] 184 | }, errorHandler) 185 | } else { 186 | that.subscriptions[theirId] = { what, params, callback } 187 | ourId = ourId || theirId 188 | that.theirIds[ourId] = theirId 189 | } 190 | // We resolve to our ID regardless which should be safe since 191 | // unsubscribes of old IDs are no-ops. 192 | resolve(ourId) 193 | } 194 | }) 195 | }) 196 | } 197 | 198 | unsubscribe (ourId) { 199 | let that = this 200 | 201 | if (this.theirIds[ourId] == null) { 202 | // console.log('Resubscription not yet complete. Defering unsubscribe', ourId) 203 | this.cancelations[ourId] = true 204 | return 205 | } 206 | let theirId = this.theirIds[ourId] 207 | if (!this.subscriptions[theirId]) { 208 | throw 'Invalid subscription id' 209 | } 210 | let unsubscribe = subscriptionKey[this.subscriptions[theirId].what].unsubscribe 211 | 212 | // console.log('Unsubscribing', ourId, theirId, this.subscriptions[theirId].what, unsubscribe) 213 | this.req(unsubscribe, [theirId], () => { 214 | delete that.theirIds[ourId] 215 | delete that.subscriptions[theirId] 216 | }) 217 | } 218 | 219 | finalise () { 220 | delete this.ws; 221 | } 222 | } 223 | 224 | let s_nodeService = null; 225 | 226 | function nodeService() { 227 | if (!s_nodeService) { 228 | s_nodeService = new NodeService(uri); 229 | } 230 | return s_nodeService; 231 | } 232 | 233 | module.exports = { nodeService, NodeService, setNodeUri }; 234 | -------------------------------------------------------------------------------- /packages/oo7/src/transformBond.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | const Bond = require('./bond'); 16 | const ReactiveBond = require('./reactiveBond'); 17 | 18 | let defaultContext = typeof (global.parity) === 'undefined' ? null : global.parity.api; 19 | 20 | /* Determines whether a `value` is not a {@link Bond} or 21 | * a {@link Promise}, nor a possibly recursive structure that contains such 22 | * a thing up to a depth `depthLeft` into it. 23 | */ 24 | function isPlain (value, depthLeft) { 25 | if (typeof (value) !== 'object' || value === null) { 26 | return true; 27 | } 28 | 29 | if (Bond.instanceOf(value)) { 30 | return false; 31 | } 32 | 33 | if (value instanceof Promise) { 34 | return false; 35 | } 36 | 37 | if (depthLeft > 0 && value.constructor === Array) { 38 | return value.every(index => isPlain(index, depthLeft - 1)); 39 | } 40 | 41 | if (depthLeft > 0 && value.constructor === Object) { 42 | return Object.keys(value).every(key => 43 | isPlain(value[key], depthLeft - 1) 44 | ); 45 | } 46 | 47 | return true; 48 | } 49 | 50 | /** 51 | * @summary Configurable {@link Bond}-derivation representing a functional transformation 52 | * of a number of other items. 53 | * @description This is the underlying class which powers the {@link Bond#map} and {@link Bond#mapAll} 54 | * functions; you'll generally want to use those unless there is some particular 55 | * aspect of this class's configurability that you need. 56 | * 57 | * It is constructed with a transform function and a number of args; this 58 | * {@link Bond} represents the result of the function when applied to those arguemnts' 59 | * representative values. `Bond`s and `Promises`, are resolved automatically at 60 | * a configurable depth within complex structures, both as input items and 61 | * the value resulting from the transform function. 62 | */ 63 | class TransformBond extends ReactiveBond { 64 | /** 65 | * Constructs a new object. 66 | * 67 | * @param {function} transform - The transformation function. It is called with 68 | * values corresponding (in order) to the items of `args`. It may return a 69 | * {@link Bond}, {Promise} or plain value resolving to representative values. 70 | * @param {array} args - A list of items whose representative values should be 71 | * passed to `transform`. 72 | * @defaultValue []. 73 | * @param {array} dependencies - A list of {@link Bond}s on which `transform` indirectly 74 | * depends. 75 | * @defaultValue []. 76 | * @param {number} outResolveDepth - The depth in any returned structure 77 | * that a {@link Bond} may be for it to be resolved. 78 | * @defaultValue 0. 79 | * @param {number} resolveDepth - The depth in a structure (array or object) 80 | * that a {@link Bond} may be in any of `args`'s items for it to be resolved 81 | * (in place) to its representative value. Beyond this depth, {@link Bond}s amd 82 | * {Promise}s will be left alone. 83 | * @defaultValue 1. 84 | * @param {number} latched - If `false`, this object becomes _not ready_ as 85 | * long as there is an output value waiting for resolution. 86 | * @defaultValue `true` 87 | * @param {boolean} mayBeNull - If `false`, a resultant value of `null` from 88 | * `transform` causes this {@link Bond} to become _not ready_. Optional. 89 | * @defaultValue `true` 90 | * @param {object} context - The context (i.e. `this` object) that `transform` 91 | * is bound to. Optional; defaults to the value set by {@link setDefaultTransformBondContext}. 92 | * @defaultValue `null` 93 | */ 94 | constructor ( 95 | transform, 96 | args = [], 97 | dependencies = [], 98 | outResolveDepth = 3, 99 | resolveDepth = 3, 100 | cache = { id: null, stringify: JSON.stringify, parse: JSON.parse }, 101 | latched = false, 102 | mayBeNull = true, 103 | context = defaultContext 104 | ) { 105 | super(args, dependencies, function (resolvedArguments) { 106 | // console.log(`Applying: ${JSON.stringify(args)}`); 107 | // Cancel any previous result-resolving. 108 | this.dropOut(); 109 | 110 | // Apply transform to the resolved argument values. 111 | let result = transform.apply(context, resolvedArguments); 112 | 113 | // Assue an undefined result means "reset". 114 | if (typeof (result) === 'undefined') { 115 | console.warn(`Transformation returned undefined: Applied ${transform} to ${JSON.stringify(resolvedArguments)}.`); 116 | this.reset(); 117 | } else if (result instanceof Promise) { 118 | // If we're not latching, we reset while we resolve the 119 | // resultant promise. 120 | if (!latched) { 121 | this.reset(); 122 | } 123 | // Then resolve the Promise; by calling `changed`, we recurse 124 | // as necessary. 125 | result.then(this.changed.bind(this)); 126 | } else if (!isPlain(result, outResolveDepth)) { 127 | // console.log(`Using ReactiveBond to resolve and trigger non-plain result (at depth ${outResolveDepth})`); 128 | // If we're not latching, we reset while we resolve the 129 | // resultant Bond(s)/Promise(s). 130 | if (!latched) { 131 | this.reset(); 132 | } 133 | // Then create a new `Bond` which we own to maintain the 134 | // resultant complex resolvable structure. 135 | this.useOut(new ReactiveBond([result], [], ([resolvedResult]) => { 136 | // console.log(`Resolved results: ${JSON.stringify(v)}. Triggering...`); 137 | // Call `changed` to recurse as neccessary. 138 | this.changed.bind(this)(resolvedResult); 139 | }, false, outResolveDepth)); 140 | } else { 141 | // Nothing special here - just call changed with the result. 142 | this.changed(result); 143 | } 144 | }, mayBeNull, resolveDepth, cache); 145 | 146 | // the current Bond used to resolve the result (output) value if the 147 | // result of our transform is itself a Bond. 148 | this._outBond = null; 149 | } 150 | 151 | // Register `newOutBond` as our result-resolving bond. Ensures it knows 152 | // we depend on it via `use`. 153 | useOut (newOutBond) { 154 | this._outBond = newOutBond.use(); 155 | } 156 | 157 | // Unregister our current result-resolving bond. Ensures it knows 158 | // we no longer depend on it via `drop`. 159 | dropOut () { 160 | if (this._outBond !== null) { 161 | this._outBond.drop(); 162 | } 163 | this._outBond = null; 164 | } 165 | 166 | // If nobody depends on us (anymore), then drop our result-resolving Bond. 167 | finalise () { 168 | this.dropOut(); 169 | ReactiveBond.prototype.finalise.call(this); 170 | } 171 | 172 | /** 173 | * Set the default context under which {@link Bond} transformations run. 174 | * 175 | * @see {@link Bond#map} {@link Bond#mapAll} {@link TransformBond} 176 | */ 177 | static setDefaultContext (c) { 178 | defaultContext = c; 179 | } 180 | } 181 | 182 | module.exports = TransformBond; 183 | -------------------------------------------------------------------------------- /packages/oo7-parity/src/abis/operations.json: -------------------------------------------------------------------------------- 1 | [{"constant":false,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_newOwner","type":"address"}],"name":"resetClientOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_release","type":"bytes32"}],"name":"isLatest","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_txid","type":"bytes32"}],"name":"rejectTransaction","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_number","type":"uint32"},{"name":"_name","type":"bytes32"},{"name":"_hard","type":"bool"},{"name":"_spec","type":"bytes32"}],"name":"proposeFork","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_client","type":"bytes32"}],"name":"removeClient","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_release","type":"bytes32"}],"name":"release","outputs":[{"name":"o_forkBlock","type":"uint32"},{"name":"o_track","type":"uint8"},{"name":"o_semver","type":"uint24"},{"name":"o_critical","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_checksum","type":"bytes32"}],"name":"build","outputs":[{"name":"o_release","type":"bytes32"},{"name":"o_platform","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"rejectFork","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"client","outputs":[{"name":"owner","type":"address"},{"name":"required","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"setClientOwner","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"}],"name":"fork","outputs":[{"name":"name","type":"bytes32"},{"name":"spec","type":"bytes32"},{"name":"hard","type":"bool"},{"name":"ratified","type":"bool"},{"name":"requiredCount","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_release","type":"bytes32"},{"name":"_platform","type":"bytes32"},{"name":"_checksum","type":"bytes32"}],"name":"addChecksum","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_txid","type":"bytes32"}],"name":"confirmTransaction","outputs":[{"name":"txSuccess","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"proxy","outputs":[{"name":"requiredCount","type":"uint256"},{"name":"to","type":"address"},{"name":"data","type":"bytes"},{"name":"value","type":"uint256"},{"name":"gas","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_owner","type":"address"}],"name":"addClient","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"clientOwner","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_txid","type":"bytes32"},{"name":"_to","type":"address"},{"name":"_data","type":"bytes"},{"name":"_value","type":"uint256"},{"name":"_gas","type":"uint256"}],"name":"proposeTransaction","outputs":[{"name":"txSuccess","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"grandOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_release","type":"bytes32"},{"name":"_forkBlock","type":"uint32"},{"name":"_track","type":"uint8"},{"name":"_semver","type":"uint24"},{"name":"_critical","type":"bool"}],"name":"addRelease","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"acceptFork","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"clientsRequired","outputs":[{"name":"","type":"uint32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_release","type":"bytes32"}],"name":"track","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_r","type":"bool"}],"name":"setClientRequired","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"latestFork","outputs":[{"name":"","type":"uint32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_track","type":"uint8"}],"name":"latestInTrack","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_client","type":"bytes32"},{"name":"_release","type":"bytes32"},{"name":"_platform","type":"bytes32"}],"name":"checksum","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"proposedFork","outputs":[{"name":"","type":"uint32"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"data","type":"bytes"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"txid","type":"bytes32"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"data","type":"bytes"},{"indexed":false,"name":"value","type":"uint256"},{"indexed":false,"name":"gas","type":"uint256"}],"name":"TransactionProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"txid","type":"bytes32"}],"name":"TransactionConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"txid","type":"bytes32"}],"name":"TransactionRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"txid","type":"bytes32"},{"indexed":false,"name":"success","type":"bool"}],"name":"TransactionRelayed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"number","type":"uint32"},{"indexed":true,"name":"name","type":"bytes32"},{"indexed":false,"name":"spec","type":"bytes32"},{"indexed":false,"name":"hard","type":"bool"}],"name":"ForkProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"number","type":"uint32"}],"name":"ForkAcceptedBy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"number","type":"uint32"}],"name":"ForkRejectedBy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"forkNumber","type":"uint32"}],"name":"ForkRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"forkNumber","type":"uint32"}],"name":"ForkRatified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"forkBlock","type":"uint32"},{"indexed":false,"name":"release","type":"bytes32"},{"indexed":false,"name":"track","type":"uint8"},{"indexed":false,"name":"semver","type":"uint24"},{"indexed":true,"name":"critical","type":"bool"}],"name":"ReleaseAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"release","type":"bytes32"},{"indexed":true,"name":"platform","type":"bytes32"},{"indexed":false,"name":"checksum","type":"bytes32"}],"name":"ChecksumAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"ClientAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"}],"name":"ClientRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":true,"name":"old","type":"address"},{"indexed":true,"name":"now","type":"address"}],"name":"ClientOwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"client","type":"bytes32"},{"indexed":false,"name":"now","type":"bool"}],"name":"ClientRequiredChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"old","type":"address"},{"indexed":false,"name":"now","type":"address"}],"name":"OwnerChanged","type":"event"}] 2 | -------------------------------------------------------------------------------- /packages/oo7-parity/src/utils/index.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | /* global parity */ 16 | const BigNumber = require('bignumber.js'); 17 | const oo7 = require('oo7'); 18 | const ParityApi = require('@parity/api'); 19 | 20 | const asciiToHex = ParityApi.util.asciiToHex; 21 | const bytesToHex = ParityApi.util.bytesToHex; 22 | const hexToAscii = ParityApi.util.hexToAscii; 23 | const isAddressValid = h => oo7.Bond.instanceOf(h) ? h.map(ParityApi.util.isAddressValid) : ParityApi.util.isAddressValid(h); 24 | const toChecksumAddress = h => oo7.Bond.instanceOf(h) ? h.map(ParityApi.util.toChecksumAddress) : ParityApi.util.toChecksumAddress(h); 25 | const sha3 = h => oo7.Bond.instanceOf(h) ? h.map(ParityApi.util.sha3) : ParityApi.util.sha3(h); 26 | 27 | const denominations = [ 'wei', 'Kwei', 'Mwei', 'Gwei', 'szabo', 'finney', 'ether', 'grand', 'Mether', 'Gether', 'Tether', 'Pether', 'Eether', 'Zether', 'Yether', 'Nether', 'Dether', 'Vether', 'Uether' ]; 28 | 29 | // Parity Utilities 30 | // TODO: move to parity.js, repackage or repot. 31 | 32 | /** 33 | * Capitalizes the first letter of a string 34 | * 35 | * @param {string} s 36 | * @returns {string} 37 | */ 38 | function capitalizeFirstLetter (s) { 39 | return s.charAt(0).toUpperCase() + s.slice(1); 40 | } 41 | 42 | /** 43 | * Wrap `f` in a function that ensures it's called at most once. 44 | * The value returned from `f` is memoized and returned for all subsequent calls. 45 | * 46 | * @param {F} f 47 | * @returns {function(): F} 48 | */ 49 | function singleton (f) { 50 | var instance = null; 51 | return function () { 52 | if (instance === null) { instance = f(); } 53 | return instance; 54 | }; 55 | } 56 | 57 | /** 58 | * Returns a {@link BigNumber} multiplier for give string denominator 59 | * 60 | * @param {string} denominator denominator (wei, eth, finney, Gwei, etc) 61 | * @returns {BigNumber} multiplier 62 | */ 63 | function denominationMultiplier (s) { 64 | let i = denominations.indexOf(s); 65 | if (i < 0) { throw new Error('Invalid denomination'); } 66 | return (new BigNumber(1000)).pow(i); 67 | } 68 | 69 | function interpretRender (s, defaultDenom = 6) { 70 | try { 71 | let m = s.toLowerCase().match(/([0-9,]+)(\.([0-9]*))? *([a-zA-Z]+)?/); 72 | let di = m[4] ? denominations.indexOf(m[4]) : defaultDenom; 73 | if (di === -1) { 74 | return null; 75 | } 76 | let n = (m[1].replace(',', '').replace(/^0*/, '')) || '0'; 77 | let d = (m[3] || '').replace(/0*$/, ''); 78 | return { denom: di, units: n, decimals: d, origNum: m[1] + (m[2] || ''), origDenom: m[4] || '' }; 79 | } catch (e) { 80 | return null; 81 | } 82 | } 83 | 84 | function combineValue (v) { 85 | let d = (new BigNumber(1000)).pow(v.denom); 86 | let n = v.units; 87 | if (v.decimals) { 88 | n += v.decimals; 89 | d = d.div((new BigNumber(10)).pow(v.decimals.length)); 90 | } 91 | return new BigNumber(n).mul(d); 92 | } 93 | 94 | /** 95 | * Add missing denominator to the value 96 | * 97 | * @param {BigNumber} v value 98 | * @param {string} d denominator 99 | * @returns {Value} 100 | */ 101 | function defDenom (v, d) { 102 | if (v.denom === null) { 103 | v.denom = d; 104 | } 105 | return v; 106 | } 107 | 108 | /** 109 | * Formats a value with denominator 110 | * 111 | * @param {Value} n value with denominator 112 | * @returns {string} 113 | */ 114 | function formatValue (n) { 115 | return `${formatValueNoDenom(n)} ${denominations[n.denom]}`; 116 | } 117 | 118 | /** 119 | * Format value without denominator 120 | * @param {Value} v 121 | * @returns {string} 122 | */ 123 | function formatValueNoDenom (n) { 124 | return `${n.units.toString().replace(/(\d)(?=(\d{3})+$)/g, '$1,')}${n.decimals ? '.' + n.decimals : ''}`; 125 | } 126 | 127 | /** 128 | * Format value without denominator 129 | * 130 | * @param {number|BigNumber} v 131 | * @param {number| exponent 132 | * @returns {string} 133 | */ 134 | function formatToExponential (v, n = 4) { 135 | return new BigNumber(v).toExponential(n); 136 | } 137 | 138 | function interpretQuantity (s) { 139 | try { 140 | let m = s.toLowerCase().match(/([0-9,]+)(\.([0-9]*))? *([a-zA-Z]+)?/); 141 | let d = denominationMultiplier(m[4] || 'ether'); 142 | let n = +m[1].replace(',', ''); 143 | if (m[2]) { 144 | n += m[3]; 145 | for (let i = 0; i < m[3].length; ++i) { 146 | d = d.div(10); 147 | } 148 | } 149 | return new BigNumber(n).mul(d); 150 | } catch (e) { 151 | return null; 152 | } 153 | } 154 | 155 | /** 156 | * Split value into base and denominator 157 | * 158 | * @param {number|BigNumber} a 159 | * @returns {Value} 160 | */ 161 | function splitValue (a) { 162 | var i = 0; 163 | a = new BigNumber('' + a); 164 | if (a.gte(new BigNumber('10000000000000000')) && a.lt(new BigNumber('100000000000000000000000'))) { 165 | i = 6; 166 | } else { 167 | for (var aa = a; aa.gte(1000) && i < denominations.length - 1; aa = aa.div(1000)) { i++; } 168 | } 169 | 170 | for (var j = 0; j < i; ++j) { a = a.div(1000); } 171 | 172 | return { base: a, denom: i }; 173 | } 174 | 175 | /** 176 | * Display balance into human-readable format with denomnator 177 | * 178 | * @param {string|BigNumber} balance 179 | * @returns {string} 180 | */ 181 | function formatBalance (n) { 182 | let a = splitValue(n); 183 | // let b = Math.floor(a.base * 1000) / 1000; 184 | return `${a.base} ${denominations[a.denom]}`; 185 | } 186 | 187 | /** 188 | * Format block number into human-readable representation. 189 | * @param {string|number|BigNumber} blockNumber 190 | * @returns {string} 191 | */ 192 | function formatBlockNumber (n) { 193 | return '#' + ('' + n).replace(/(\d)(?=(\d{3})+$)/g, '$1,'); 194 | } 195 | 196 | function isNullData (a) { 197 | return !a || typeof (a) !== 'string' || a.match(/^(0x)?0+$/) !== null; 198 | } 199 | 200 | function splitSignature (sig) { 201 | if ((sig.substr(2, 2) === '1b' || sig.substr(2, 2) === '1c') && (sig.substr(66, 2) !== '1b' && sig.substr(66, 2) !== '1c')) { 202 | // vrs 203 | return [sig.substr(0, 4), `0x${sig.substr(4, 64)}`, `0x${sig.substr(68, 64)}`]; 204 | } else { 205 | // rsv 206 | return [`0x${sig.substr(130, 2)}`, `0x${sig.substr(2, 64)}`, `0x${sig.substr(66, 64)}`]; 207 | } 208 | } 209 | 210 | function removeSigningPrefix (message) { 211 | if (!message.startsWith('\x19Ethereum Signed Message:\n')) { 212 | throw new Error('Invalid message - doesn\'t contain security prefix'); 213 | } 214 | for (var i = 1; i < 6; ++i) { 215 | if (message.length === 26 + i + +message.substr(26, i)) { 216 | return message.substr(26 + i); 217 | } 218 | } 219 | throw new Error('Invalid message - invalid security prefix'); 220 | } 221 | 222 | function cleanup (value, type = 'bytes32', api = parity.api) { 223 | // TODO: make work with arbitrary depth arrays 224 | if (value instanceof Array && type.match(/bytes[0-9]+/)) { 225 | // figure out if it's an ASCII string hiding in there: 226 | var ascii = ''; 227 | for (var i = 0, ended = false; i < value.length && ascii !== null; ++i) { 228 | if (value[i] === 0) { 229 | ended = true; 230 | } else { 231 | ascii += String.fromCharCode(value[i]); 232 | } 233 | if ((ended && value[i] !== 0) || (!ended && (value[i] < 32 || value[i] >= 128))) { 234 | ascii = null; 235 | } 236 | } 237 | value = ascii === null ? '0x' + value.map(n => ('0' + n.toString(16)).slice(-2)).join('') : ascii; 238 | } 239 | if (type.substr(0, 4) === 'uint' && +type.substr(4) <= 48) { 240 | value = +value; 241 | } 242 | return value; 243 | } 244 | 245 | module.exports = { 246 | asciiToHex, 247 | bytesToHex, 248 | hexToAscii, 249 | isAddressValid, 250 | toChecksumAddress, 251 | sha3, 252 | capitalizeFirstLetter, 253 | singleton, 254 | denominations, 255 | denominationMultiplier, 256 | interpretRender, 257 | combineValue, 258 | defDenom, 259 | formatValue, 260 | formatValueNoDenom, 261 | formatToExponential, 262 | interpretQuantity, 263 | splitValue, 264 | formatBalance, 265 | formatBlockNumber, 266 | isNullData, 267 | splitSignature, 268 | removeSigningPrefix, 269 | cleanup 270 | }; 271 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/bonds.js: -------------------------------------------------------------------------------- 1 | const { camel } = require('change-case'); 2 | const { Bond, TransformBond, TimeBond } = require('oo7') 3 | const { nodeService } = require('./nodeService') 4 | const { SubscriptionBond } = require('./subscriptionBond') 5 | const { BlockNumber, Hash } = require('./types'); 6 | const { decode, encode } = require('./codec'); 7 | const { stringToBytes, hexToBytes, bytesToHex, toLE } = require('./utils') 8 | const { StorageBond } = require('./storageBond') 9 | const { setMetadata } = require('./metadata') 10 | 11 | let chain = (() => { 12 | let head = new SubscriptionBond('chain_newHead').subscriptable() 13 | let finalizedHead = new SubscriptionBond('chain_finalizedHead').subscriptable() 14 | let height = head.map(h => new BlockNumber(h.number)) 15 | let finalizedHeight = finalizedHead.map(h => new BlockNumber(h.number)) 16 | let lag = Bond.all([height, finalizedHeight]).map(([h, f]) => new BlockNumber(h - f)) 17 | let header = hashBond => new TransformBond(hash => nodeService().request('chain_getHeader', [hash]), [hashBond]).subscriptable() 18 | let block = hashBond => new TransformBond(hash => nodeService().request('chain_getBlock', [hash]), [hashBond]).subscriptable() 19 | let hash = numberBond => new TransformBond(number => nodeService().request('chain_getBlockHash', [number]).then(hexToBytes), [numberBond]) 20 | return { head, finalizedHead, height, finalizedHeight, header, hash, block, lag } 21 | })() 22 | 23 | let system = (() => { 24 | let time = new TimeBond 25 | let name = new TransformBond(() => nodeService().request('system_name')).subscriptable() 26 | let version = new TransformBond(() => nodeService().request('system_version')).subscriptable() 27 | let chain = new TransformBond(() => nodeService().request('system_chain')).subscriptable() 28 | let properties = new TransformBond(() => nodeService().request('system_properties')).subscriptable() 29 | let health = new TransformBond(() => nodeService().request('system_health'), [], [time]).subscriptable() 30 | let peers = new TransformBond(() => nodeService().request('system_peers'), [], [time]).subscriptable() 31 | let pendingTransactions = new TransformBond(() => nodeService().request('author_pendingExtrinsics')).subscriptable() 32 | return { name, version, chain, properties, pendingTransactions, health, peers } 33 | })() 34 | 35 | let version = (new SubscriptionBond('state_runtimeVersion', [], r => { 36 | let apis = {} 37 | r.apis.forEach(([id, version]) => { 38 | if (typeof id !== 'string') { 39 | id = String.fromCharCode.apply(null, id) 40 | } 41 | apis[id] = version 42 | }) 43 | return { 44 | authoringVersion: r.authoringVersion, 45 | implName: r.implName, 46 | implVersion: r.implVersion, 47 | specName: r.specName, 48 | specVersion: r.specVersion, 49 | apis 50 | } 51 | })).subscriptable() 52 | 53 | let runtime = { 54 | version, 55 | metadata: new Bond, 56 | core: (() => { 57 | let authorityCount = new SubscriptionBond('state_storage', [['0x' + bytesToHex(stringToBytes(':auth:len'))]], r => decode(hexToBytes(r.changes[0][1]), 'u32')) 58 | let authorities = authorityCount.map( 59 | n => [...Array(n)].map((_, i) => 60 | new SubscriptionBond('state_storage', 61 | [[ '0x' + bytesToHex(stringToBytes(":auth:")) + bytesToHex(toLE(i, 4)) ]], 62 | r => decode(hexToBytes(r.changes[0][1]), 'AccountId') 63 | ) 64 | ), 2) 65 | let code = new SubscriptionBond('state_storage', [['0x' + bytesToHex(stringToBytes(':code'))]], r => hexToBytes(r.changes[0][1])) 66 | let codeHash = new TransformBond(() => nodeService().request('state_getStorageHash', ['0x' + bytesToHex(stringToBytes(":code"))]).then(hexToBytes), [], [version]) 67 | let codeSize = new TransformBond(() => nodeService().request('state_getStorageSize', ['0x' + bytesToHex(stringToBytes(":code"))]), [], [version]) 68 | let heapPages = new SubscriptionBond('state_storage', [['0x' + bytesToHex(stringToBytes(':heappages'))]], r => decode(hexToBytes(r.changes[0][1]), 'u64')) 69 | return { authorityCount, authorities, code, codeHash, codeSize, version, heapPages } 70 | })() 71 | } 72 | 73 | let calls = {} 74 | 75 | class RuntimeUp extends Bond { 76 | initialise() { 77 | let that = this 78 | initRuntime(() => that.trigger(true)) 79 | } 80 | } 81 | let runtimeUp = new RuntimeUp 82 | 83 | let onRuntimeInit = [] 84 | 85 | function initialiseFromMetadata (md) { 86 | console.log("initialiseFromMetadata", md) 87 | setMetadata(md) 88 | let callIndex = 0; 89 | md.modules.forEach((m) => { 90 | let o = {} 91 | let c = {} 92 | if (m.storage) { 93 | let storePrefix = m.prefix 94 | m.storage.forEach(item => { 95 | switch (item.type.option) { 96 | case 'Plain': { 97 | o[camel(item.name)] = new StorageBond(`${storePrefix} ${item.name}`, item.type.value, [], item.modifier.option == 'Default' ? item.default : null, 'Twox128') 98 | break 99 | } 100 | case 'Map': { 101 | let keyType = item.type.value.key 102 | let valueType = item.type.value.value 103 | let hasDefault = item.modifier.option == 'Default' 104 | 105 | o[camel(item.name)] = (keyBond, useDefault = hasDefault) => new TransformBond( 106 | key => new StorageBond(`${storePrefix} ${item.name}`, valueType, encode(key, keyType), useDefault ? item.default : null, item.type.value.hasher.option), 107 | [keyBond] 108 | ).subscriptable() 109 | if (item.type.value.iterable) { 110 | o[camel(item.name)].head = new StorageBond(`head of ${storePrefix} ${item.name}`, keyType) 111 | let prefix = `${storePrefix} ${item.name}`; 112 | let rest 113 | rest = (pre, head) => { 114 | if (head == null) { 115 | return pre 116 | } else { 117 | return new TransformBond( 118 | l => l && l[0] 119 | ? rest([...pre, { key: head, value: l[0][0] }], l[0][2]) 120 | : pre, 121 | [new StorageBond(prefix, [valueType, `Option<${keyType}>`, `Option<${keyType}>`], encode(head, keyType))] 122 | ) 123 | } 124 | } 125 | o[camel(item.name)].all = o[camel(item.name)].head.map(x => rest([], x)) 126 | } 127 | break 128 | } 129 | } 130 | }) 131 | } 132 | if (m.calls) { 133 | let thisCallIndex = callIndex 134 | callIndex++ 135 | m.calls.forEach((item, id) => { 136 | if (item.arguments.length > 0 && item.arguments[0].name == 'origin' && item.arguments[0].type == 'Origin') { 137 | item.arguments = item.arguments.slice(1) 138 | } 139 | c[camel(item.name)] = function (...bondArgs) { 140 | if (bondArgs.length != item.arguments.length) { 141 | throw `Invalid number of argments (${bondArgs.length} given, ${item.arguments.length} expected)` 142 | } 143 | return new TransformBond(args => { 144 | let encoded_args = encode(args, item.arguments.map(x => x.type)) 145 | let res = new Uint8Array([thisCallIndex, id, ...encoded_args]); 146 | // console.log(`Encoding call ${m.name}.${item.name} (${thisCallIndex}.${id}): ${bytesToHex(res)}`) 147 | return res 148 | }, [bondArgs], [], 3, 3, undefined, true) 149 | } 150 | c[camel(item.name)].help = item.arguments.map(a => a.name) 151 | }) 152 | } 153 | runtime[camel(m.name)] = o 154 | calls[camel(m.name)] = c 155 | }) 156 | md.modules.forEach(m => { 157 | if (m.storage) { 158 | try { 159 | require(`./srml/${m.name}`).augment(runtime, chain) 160 | } 161 | catch (e) { 162 | if (!e.toString().startsWith('Error: Cannot find module')) { 163 | throw e 164 | } 165 | } 166 | } 167 | }) 168 | if (onRuntimeInit !== null) { 169 | onRuntimeInit.forEach(f => { if (f) f() }) 170 | onRuntimeInit = null 171 | } 172 | 173 | runtime.metadata.trigger(md) 174 | } 175 | 176 | function decodeMetadata(bytes) { 177 | let input = { data: bytes } 178 | let head = decode(input, 'MetadataHead') 179 | if (head.magic === 0x6174656d) { 180 | if (head.version == 1) { 181 | return decode(input, 'MetadataBodyV1') 182 | } else if (head.version == 2) { 183 | return decode(input, 'MetadataBodyV2') 184 | } else if (head.version == 3) { 185 | return decode(input, 'MetadataBodyV3') 186 | } else if (head.version == 4) { 187 | return decode(input, 'MetadataBody') 188 | } else { 189 | throw `Metadata version ${head.version} not supported` 190 | } 191 | } else { 192 | let md = decode(bytes, 'Legacy_RuntimeMetadata') 193 | md.modules = md.modules.map(m => { 194 | m.name = m.prefix 195 | m.prefix = m.storage ? m.storage.prefix : null 196 | m.storage = m.storage ? m.storage.items : null 197 | m.calls = m.module && m.module.call ? m.module.call.functions : null 198 | return m 199 | }) 200 | return md 201 | } 202 | } 203 | 204 | function initRuntime (callback = null) { 205 | if (onRuntimeInit instanceof Array) { 206 | onRuntimeInit.push(callback) 207 | version.tie(() => { 208 | // console.info("Initialising runtime") 209 | nodeService().request('state_getMetadata') 210 | .then(blob => decodeMetadata(hexToBytes(blob))) 211 | .then(initialiseFromMetadata) 212 | }) 213 | } else { 214 | // already inited runtime 215 | if (callback) { 216 | callback() 217 | } 218 | } 219 | } 220 | 221 | function runtimePromise() { 222 | return new Promise((resolve, reject) => initRuntime(() => resolve(runtime))) 223 | } 224 | 225 | function callsPromise() { 226 | return new Promise((resolve, reject) => initRuntime(() => resolve(calls))) 227 | } 228 | 229 | module.exports = { initRuntime, runtimeUp, runtimePromise, callsPromise, runtime, calls, chain, system } 230 | -------------------------------------------------------------------------------- /packages/oo7-substrate/src/secretStore.js: -------------------------------------------------------------------------------- 1 | const { Bond } = require('oo7') 2 | const nacl = require('tweetnacl'); 3 | const { generateMnemonic, mnemonicToSeed, mnemonicToEntropy } = require('bip39') 4 | const { ss58Encode } = require('./ss58') 5 | const { AccountId } = require('./types') 6 | const { encode } = require('./codec') 7 | const { stringToBytes, bytesToHex, hexToBytes, toLE } = require('./utils') 8 | const { blake2b } = require('blakejs') 9 | const { pbkdf2Sync } = require('pbkdf2') 10 | const { Buffer } = require('buffer') 11 | const { waitReady, isReady, keypairFromSeed, sign, verify, deriveKeypairHard, derivePublicSoft, deriveKeypairSoft } = require('@polkadot/wasm-schnorrkel'); 12 | const wasmCrypto = require('@polkadot/wasm-crypto'); 13 | 14 | const DEV_PHRASE = 'bottom drive obey lake curtain smoke basket hold race lonely fit walk' 15 | 16 | let edCache = {} 17 | let srCache = {} 18 | 19 | function chainCodeFor(x) { 20 | let r = encode(x) 21 | if (r.length <= 32) { 22 | r = [...r] 23 | while (r.length < 32) { 24 | r.push(0) 25 | } 26 | r = new Uint8Array(r) 27 | } else { 28 | r = blake2b(r) 29 | } 30 | return r 31 | } 32 | 33 | function deriveHardJunction(seed, cc) { 34 | return blake2b(encode(["Ed25519HDKD", seed, cc], ['String', '[u8]', '[u8]']), null, 32) 35 | } 36 | 37 | function edSeedFromUri(uri) { 38 | if (!edCache[uri]) { 39 | if (uri.match(/^0x[0-9a-fA-F]{64}$/)) { 40 | edCache[uri] = hexToBytes(uri) 41 | } else { 42 | let m = uri.match(/^([a-z]+( [a-z]+){11})?((\/\/?[^\/]*)*)(\/\/\/(.*))?$/) 43 | if (m) { 44 | let password = m[6] || '' 45 | let phrase = m[1] || DEV_PHRASE 46 | let seed = wasmCrypto.bip39ToMiniSecret(phrase, password) 47 | // let entropy = new Buffer(hexToBytes(mnemonicToEntropy(phrase))) 48 | // let salt = new Buffer(stringToBytes(`mnemonic${password}`)) 49 | // let seed = pbkdf2Sync(entropy, salt, 2048, 64, 'sha512').slice(0, 32); 50 | let rest = m[3]; 51 | while (rest != '') { 52 | let m = rest.match(/^\/(\/?)([^\/]*)(\/.*)?$/) 53 | if (m[2].match(/^[0-9]+$/)) { 54 | m[2] = +m[2] 55 | } 56 | let cc = chainCodeFor(m[2]) 57 | if (m[1] == '/') { 58 | // hard key -all good 59 | seed = deriveHardJunction(seed, cc) 60 | } else { 61 | throw "Soft key" 62 | } 63 | rest = m[3] || '' 64 | } 65 | edCache[uri] = seed 66 | } else { 67 | throw "Invalid secret URI" 68 | } 69 | } 70 | } 71 | return edCache[uri] 72 | } 73 | 74 | function srKeypairToAccountId(pair) { 75 | return new AccountId(srKeypairToPublic(pair)) 76 | } 77 | 78 | function srKeypairToPublic(pair) { 79 | return new Uint8Array(pair.slice(64, 96)) 80 | } 81 | 82 | function srKeypairToSecret(pair) { 83 | return new Uint8Array(pair.slice(0, 64)) 84 | } 85 | 86 | function srKeypairFromUri(uri) { 87 | if (!srCache[uri]) { 88 | if (uri.match(/^0x[0-9a-fA-F]{64}$/)) { 89 | srCache[uri] = keypairFromSeed(hexToBytes(uri)) 90 | } else { 91 | let m = uri.match(/^([a-z]+( [a-z]+){11})?((\/\/?[^\/]*)*)(\/\/\/(.*))?$/) 92 | if (m) { 93 | let password = m[6] || '' 94 | let phrase = m[1] || DEV_PHRASE 95 | 96 | let seed = wasmCrypto.bip39ToMiniSecret(phrase, password) 97 | /* let entropy = new Buffer(hexToBytes(mnemonicToEntropy(phrase))) 98 | let salt = new Buffer(stringToBytes(`mnemonic${password}`)) 99 | let seed = pbkdf2Sync(entropy, salt, 2048, 64, 'sha512').slice(0, 32)*/ 100 | let pair = keypairFromSeed(seed) 101 | 102 | let rest = m[3]; 103 | while (rest != '') { 104 | let m = rest.match(/^\/(\/?)([^\/]*)(\/.*)?$/) 105 | if (m[2].match(/^[0-9]+$/)) { 106 | m[2] = +m[2] 107 | } 108 | let cc = chainCodeFor(m[2]) 109 | if (m[1] == '/') { 110 | pair = deriveKeypairHard(pair, cc) 111 | } else { 112 | pair = deriveKeypairSoft(pair, cc) 113 | } 114 | rest = m[3] || '' 115 | } 116 | 117 | srCache[uri] = pair 118 | } else { 119 | throw "Invalid secret URI" 120 | } 121 | } 122 | } 123 | return srCache[uri] 124 | } 125 | 126 | window.chainCodeFor = chainCodeFor 127 | window.deriveHardJunction = deriveHardJunction 128 | window.edSeedFromUri = edSeedFromUri 129 | window.pbkdf2Sync = pbkdf2Sync 130 | window.Buffer = Buffer 131 | window.mnemonicToEntropy = mnemonicToEntropy 132 | window.isReady = isReady 133 | window.waitReady = waitReady 134 | window.keypairFromSeed = keypairFromSeed 135 | window.sign = sign 136 | window.deriveKeypairHard = deriveKeypairHard 137 | window.derivePublicSoft = derivePublicSoft 138 | window.deriveKeypairSoft = deriveKeypairSoft 139 | window.srKeypairFromUri = srKeypairFromUri 140 | window.srKeypairToPublic = srKeypairToPublic 141 | window.wasmCrypto = wasmCrypto 142 | 143 | const ED25519 = 'ed25519' 144 | const SR25519 = 'sr25519' 145 | 146 | function overrideType(uri, type) { 147 | let m = uri.match(/^((ed25519:)|(sr25519:))?(.*)$/) 148 | if (m) { 149 | switch (m[1]) { 150 | case 'ed25519:': 151 | type = ED25519 152 | break 153 | case 'sr25519:': 154 | type = SR25519 155 | break 156 | default: 157 | } 158 | uri = m[4]; 159 | } 160 | return {uri, type} 161 | } 162 | 163 | class SecretStore extends Bond { 164 | constructor (storage) { 165 | super() 166 | this._storage = storage || typeof localStorage === 'undefined' ? {} : localStorage 167 | this._keys = [] 168 | this._load() 169 | } 170 | 171 | generateMnemonic (wordCount = 12) { 172 | return wasmCrypto.bip39Generate(wordCount) 173 | } 174 | 175 | submit (_uri, name, _type = SR25519) { 176 | let {uri, type} = overrideType(_uri, _type) 177 | this._keys.push({uri, name, type}) 178 | this._sync() 179 | return this.accountFromPhrase(uri, type) 180 | } 181 | 182 | accountFromPhrase (_uri, _type = SR25519) { 183 | try { 184 | let {uri, type} = overrideType(_uri, _type) 185 | if (type == ED25519) { 186 | return new AccountId(nacl.sign.keyPair.fromSeed(edSeedFromUri(uri)).publicKey) 187 | } else if (type == SR25519) { 188 | return srKeypairToAccountId(srKeypairFromUri(uri)) 189 | } 190 | } 191 | catch (e) { 192 | return null 193 | } 194 | } 195 | 196 | accounts () { 197 | return this._keys.map(k => k.account) 198 | } 199 | 200 | find (identifier) { 201 | if (this._keys.indexOf(identifier) !== -1) { 202 | return identifier 203 | } 204 | if (identifier instanceof Uint8Array && identifier.length == 32 || identifier instanceof AccountId) { 205 | identifier = ss58Encode(identifier) 206 | } 207 | return this._byAddress[identifier] ? this._byAddress[identifier] : this._byName[identifier] 208 | } 209 | 210 | sign (from, data) { 211 | let item = this.find(from) 212 | if (item) { 213 | console.info(`Signing data from ${item.name}`, bytesToHex(data)) 214 | let sig 215 | switch (item.type) { 216 | case ED25519: 217 | sig = nacl.sign.detached(data, item.key.secretKey) 218 | if (!nacl.sign.detached.verify(data, sig, item.key.publicKey)) { 219 | console.warn(`Signature is INVALID!`) 220 | return null 221 | } 222 | break 223 | case SR25519: 224 | sig = sign(srKeypairToPublic(item.key), srKeypairToSecret(item.key), data) 225 | if (!verify(sig, data, srKeypairToPublic(item.key))) { 226 | console.warn(`Signature is INVALID!`) 227 | return null 228 | } 229 | break 230 | } 231 | console.info(`Signature is ${bytesToHex(sig)}`) 232 | return sig 233 | } 234 | return null 235 | } 236 | 237 | forget (identifier) { 238 | let item = this.find(identifier) 239 | if (item) { 240 | console.info(`Forgetting key ${item.name} (${item.address}, ${item.uri})`) 241 | this._keys = this._keys.filter(i => i !== item) 242 | this._sync() 243 | } 244 | } 245 | 246 | _load () { 247 | if (this._storage.secretStore) { 248 | this._keys = JSON.parse(this._storage.secretStore) 249 | .map(({keyData, seed, uri, phrase, name, type}) => ({ 250 | name, 251 | keyData: null,//hexToBytes(keyData || seed), 252 | uri: uri || phrase, 253 | type: type || ED25519 254 | })) 255 | } else { 256 | this._keys = [{ 257 | name: 'Default', 258 | uri: generateMnemonic(), 259 | type: SR25519 260 | }] 261 | } 262 | this._sync() 263 | } 264 | 265 | _sync () { 266 | let byAddress = {} 267 | let byName = {} 268 | this._keys = this._keys.map(({key, uri, keyData, name, type}) => { 269 | let item 270 | switch (type) { 271 | case ED25519: { 272 | keyData = keyData || edSeedFromUri(uri) 273 | key = key || nacl.sign.keyPair.fromSeed(keyData) 274 | let account = new AccountId(key.publicKey) 275 | item = {uri, name, type, key, keyData, account} 276 | break 277 | } 278 | case SR25519: { 279 | keyData = keyData || srKeypairFromUri(uri) 280 | key = key || keyData 281 | let account = srKeypairToAccountId(key) 282 | item = {uri, name, type, key, keyData, account} 283 | break 284 | } 285 | } 286 | if (item) { 287 | item.address = ss58Encode(item.account) 288 | byAddress[item.address] = item 289 | byName[item.name] = item 290 | return item 291 | } 292 | }) 293 | this._byAddress = byAddress 294 | this._byName = byName 295 | this._storage.secretStore = JSON.stringify(this._keys.map(k => ({keyData: bytesToHex(k.keyData), uri: k.uri, name: k.name, type: k.type}))) 296 | this.trigger({keys: this._keys, byAddress: this._byAddress, byName: this._byName}) 297 | } 298 | } 299 | 300 | let s_secretStore = null; 301 | 302 | function secretStore(storage) { 303 | if (s_secretStore === null) { 304 | s_secretStore = new SecretStore(storage); 305 | } 306 | return s_secretStore; 307 | } 308 | 309 | module.exports = { secretStore, SecretStore }; 310 | -------------------------------------------------------------------------------- /packages/oo7/src/bondCache.js: -------------------------------------------------------------------------------- 1 | // (C) Copyright 2016-2017 Parity Technologies (UK) Ltd. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // The parent-side cache-server to which child-side BondCaches can connect. 16 | // Will send messages of the form { bondCacheUpdate: { uuid: '...', value: ... }} 17 | // value, if provided is the actual Bond value, not a stringification of it. 18 | // Will try to send these only for UUIDs that it knows the child is interested 19 | // in - child can register interest with a message { useBond: uuid } and 20 | // unregister interest with { dropBond: uuid }. 21 | // 22 | // If you construct BondCache passing a deferParentPrefix arg, then it's up to 23 | // you to ensure that the parent actually has a BondCacheProxy constructed. If 24 | // it doesn't, things will go screwy. 25 | 26 | let consoleDebug = typeof window !== 'undefined' && window.debugging ? console.debug : () => {}; 27 | 28 | class BondCache { 29 | constructor (backupStorage, deferParentPrefix, surrogateWindow = null) { 30 | this.window = surrogateWindow || (typeof window === 'undefined' ? null : window); 31 | if (this.window) { 32 | this.window.addEventListener('storage', this.onStorageChanged.bind(this)); 33 | this.window.addEventListener('unload', this.onUnload.bind(this)); 34 | this.window.addEventListener('message', this.onMessage.bind(this)); 35 | } 36 | 37 | this.deferParentPrefix = this.window && this.window.parent ? deferParentPrefix : null; 38 | 39 | this.regs = {}; 40 | 41 | // TODO: would be nice if this were better. 42 | this.sessionId = Math.floor((1 + Math.random()) * 0x100000000).toString(16).substr(1); 43 | consoleDebug('BondCache: Constructing', this.sessionId); 44 | 45 | try { 46 | this.storage = this.window ? this.window.localStorage : backupStorage; 47 | } catch (e) { 48 | this.storage = backupStorage; 49 | } 50 | } 51 | 52 | initialise (uuid, bond, stringify, parse) { 53 | consoleDebug('BondCache.initialise', this.sessionId, uuid, bond, this.regs); 54 | if (!this.regs[uuid]) { 55 | consoleDebug('BondCache.initialise: creating...'); 56 | this.regs[uuid] = { owned: false, deferred: false, users: [bond], primary: null, stringify, parse }; 57 | let key = '$_Bonds.' + uuid; 58 | if (this.storage[key] !== undefined) { 59 | consoleDebug('BondCache.initialise: restoring from persistent cache'); 60 | bond.changed(parse(this.storage[key])); 61 | } 62 | this.ensureActive(uuid); 63 | consoleDebug('BondCache.initialise: Created reg', this.regs); 64 | } else if (this.regs[uuid].primary === bond) { 65 | consoleDebug('BondCache.initialise: Reactivating an inactive primary.'); 66 | if (this.regs[uuid].owned) { 67 | console.error('BondCache.initialise: initialise called on already-active Bond.'); 68 | } 69 | this.regs[uuid].owned = true; 70 | } else { 71 | consoleDebug('BondCache.initialise: appending to pre-existing entry', JSON.parse(JSON.stringify(this.regs[uuid]))); 72 | if (!this.regs[uuid].primary && !this.regs[uuid].deferred) { 73 | console.error('BondCache.initialise: Registered Bond that has neither primary nor deferred.'); 74 | } 75 | this.regs[uuid].users.push(bond); 76 | let equivBond = (this.regs[uuid].primary || this.regs[uuid].users[0]); 77 | if (equivBond.isReady()) { 78 | consoleDebug('BondCache.initialise: restoring from equivalent active'); 79 | bond.changed(equivBond._value); 80 | } 81 | } 82 | if (typeof window !== 'undefined' && window.debugging) { 83 | this.checkConsistency(); 84 | } 85 | } 86 | 87 | checkConsistency () { 88 | Object.keys(this.regs).forEach(uuid => { 89 | let item = this.regs[uuid]; 90 | if ( 91 | (item.primary === null && 92 | !item.deferred && 93 | item.users.length > 0 && 94 | (this.storage['$_Bonds^' + uuid] === this.sessionId || 95 | !this.storage['$_Bonds^' + uuid]) 96 | ) || (item.primary === null && item.owned) 97 | ) { 98 | console.error('BondCache consistency failed!', this.regs); 99 | } 100 | }); 101 | } 102 | 103 | changed (uuid, value) { 104 | consoleDebug('BondCache.changed', this.sessionId, uuid, value, this.regs); 105 | let item = this.regs[uuid]; 106 | if (item && this.storage['$_Bonds^' + uuid] === this.sessionId) { 107 | let key = '$_Bonds.' + uuid; 108 | if (value === undefined) { 109 | delete this.storage[key]; 110 | item.users.forEach(bond => bond.reset()); 111 | } else { 112 | this.storage[key] = item.stringify(value); 113 | item.users.forEach(bond => bond.changed(value)); 114 | } 115 | } 116 | consoleDebug('BondCache.changed: complete', this.regs[uuid]); 117 | } 118 | 119 | finalise (uuid, bond) { 120 | consoleDebug('BondCache.finalise', uuid, bond, this.regs); 121 | let item = this.regs[uuid]; 122 | if (typeof item === 'undefined') { 123 | console.error(`BondCache.finalise: called for unregistered UUID ${uuid}`, bond); 124 | return; 125 | } 126 | if (item.primary === bond) { 127 | consoleDebug('BondCache.finalise: We own; finalising Bond'); 128 | 129 | // TODO: decide whether to delete directly, or keep around. 130 | let keepAround = true; 131 | 132 | if (keepAround) { 133 | item.owned = false; 134 | // TODO: record the current time as an LRU and place the bond in a map for eventual deletion. 135 | } else { 136 | item.primary.finalise(); 137 | item.primary = null; 138 | if (item.users.length === 0) { 139 | consoleDebug('BondCache.finalise: No users; deleting entry and unreging from storage.'); 140 | // no owner and no users. we shold be the owner in 141 | // storage. if we are, remove our key to signify to other 142 | // tabs we're no longer maintaining this. 143 | let storageKey = '$_Bonds^' + uuid; 144 | let owner = this.storage[storageKey]; 145 | if (owner === this.sessionId) { 146 | delete this.storage[storageKey]; 147 | } 148 | } else { 149 | consoleDebug('BondCache.finalise: Still users; ensuring active.'); 150 | // we removed the owner and there are users, must ensure that 151 | // the bond is maintained. 152 | this.ensureActive(uuid); 153 | } 154 | } 155 | } else { 156 | consoleDebug('BondCache.finalise: Not owner. Removing self from users.'); 157 | // otherwise, just remove the exiting bond from the users. 158 | item.users = item.users.filter(b => b !== bond); 159 | 160 | // If we're the last user from a parent-deferred Bond, then notify 161 | // parent we're no longer bothered about further updates. 162 | if (item.users.length === 0 && this.regs[uuid].deferred) { 163 | consoleDebug('BondCache.finalise: dropping deferral from parent frame', uuid); 164 | this.window.parent.postMessage({ dropBond: uuid }, '*'); 165 | this.regs[uuid].deferred = false; 166 | } 167 | } 168 | if (item.primary === null && !item.deferred && item.users.length === 0) { 169 | delete this.regs[uuid]; 170 | } 171 | if (typeof window !== 'undefined' && window.debugging) { 172 | this.checkConsistency(); 173 | } 174 | } 175 | 176 | ensureActive (uuid, key = '$_Bonds^' + uuid) { 177 | consoleDebug('BondCache.ensureActive', uuid); 178 | let item = this.regs[uuid]; 179 | if (item && item.users.length > 0 && item.primary && !item.owned) { 180 | // would-be owners (users). no need for the primary any more. 181 | consoleDebug('BondCache.ensureActive: Cleaning up orphan primary.'); 182 | item.primary.finalise(); 183 | item.primary = null; 184 | item.owned = false; 185 | } 186 | if (item && item.users.length > 0 && item.primary === null && !item.deferred) { 187 | consoleDebug('BondCache.ensureActive: Activating...'); 188 | if (item.owned) { 189 | console.error('BondCache.ensureActive: INCONSISTENT. Cannot have no primary but be owned.'); 190 | } 191 | if (this.deferParentPrefix && uuid.startsWith(this.deferParentPrefix)) { 192 | consoleDebug('BondCache.ensureActive: deferring to parent frame', uuid); 193 | item.deferred = true; 194 | this.window.parent.postMessage({ useBond: uuid }, '*'); 195 | // One that we use - adopt it if necessary. 196 | } else { 197 | consoleDebug('BondCache.ensureActive: One that we use - adopt it if necessary.', this.storage[key], this.sessionId); 198 | if (!this.storage[key]) { 199 | consoleDebug('BondCache.ensureActive: No registered owner yet. Adopting'); 200 | this.storage[key] = this.sessionId; 201 | } 202 | if (this.storage[key] === this.sessionId) { 203 | consoleDebug('BondCache.ensureActive: We are responsible for this UUID - initialise'); 204 | item.primary = item.users.pop(); 205 | item.owned = true; 206 | item.primary.initialise(); 207 | } 208 | } 209 | } 210 | } 211 | 212 | reconstruct (updateMessage, bond) { 213 | if (updateMessage.valueString) { 214 | return bond._parse(updateMessage.valueString); 215 | } 216 | return updateMessage.value; 217 | } 218 | 219 | onMessage (e) { 220 | // console.log('Received message', e); 221 | if (this.window && e.source === this.window.parent) { 222 | // Comes from parent. 223 | // console.log('Message is from parent'); 224 | if (typeof e.data === 'object' && e.data !== null) { 225 | let up = e.data.bondCacheUpdate; 226 | if (up && this.regs[up.uuid]) { 227 | consoleDebug('BondCache.onMessage: Bond cache update that we care about:', up.uuid); 228 | let item = this.regs[up.uuid]; 229 | if (item.users.length > 0) { 230 | let value = this.reconstruct(up, item.users[0]); 231 | if (typeof value !== 'undefined') { 232 | consoleDebug('BondCache.onMessage: Updating bond:', up.uuid, value, item.users); 233 | item.users.forEach(bond => bond.changed(value)); 234 | } else { 235 | consoleDebug('BondCache.onMessage: Resetting bond:', up.uuid, item.users); 236 | item.users.forEach(bond => bond.reset()); 237 | } 238 | } 239 | } 240 | } 241 | } 242 | } 243 | 244 | onStorageChanged (e) { 245 | if (!e.key.startsWith('$_Bonds')) { 246 | return; 247 | } 248 | let uuid = e.key.substr(8); 249 | let item = this.regs[uuid]; 250 | consoleDebug('BondCache.onStorageChanged', uuid, item); 251 | if (!item) { 252 | return; 253 | } 254 | if (e.key[7] === '.') { 255 | // Bond changed... 256 | if (typeof (this.storage[e.key]) === 'undefined') { 257 | item.users.forEach(bond => bond.reset()); 258 | } else { 259 | let v = item.parse(this.storage[e.key]); 260 | item.users.forEach(bond => bond.changed(v)); 261 | } 262 | } else if (e.key[7] === '^') { 263 | // Owner going offline... 264 | this.ensureActive(uuid, e.key); 265 | } 266 | } 267 | 268 | onUnload () { 269 | consoleDebug('BondCache.onUnload'); 270 | // Like drop for all items, except that we don't care about usage; we 271 | // drop anyway. 272 | Object.keys(this.regs).forEach(uuid => { 273 | if (this.regs[uuid].deferred) { 274 | consoleDebug('BondCache.onUnload: dropping deferral from parent frame', uuid); 275 | this.window.parent.postMessage({ dropBond: uuid }, '*'); 276 | } else { 277 | consoleDebug('BondCache.onUnload: dropping ownership key from storage', uuid); 278 | let storageKey = '$_Bonds^' + uuid; 279 | let owner = this.storage[storageKey]; 280 | if (owner === this.sessionId) { 281 | delete this.storage[storageKey]; 282 | } 283 | } 284 | }); 285 | this.regs = {}; 286 | } 287 | } 288 | 289 | module.exports = BondCache; 290 | -------------------------------------------------------------------------------- /packages/oo7/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /packages/oo7-parity/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /packages/oo7-react/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /packages/oo7-substrate/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------