Skip to content
This repository was archived by the owner on Jul 6, 2022. It is now read-only.

Commit b6b19ca

Browse files
committed
initial
0 parents  commit b6b19ca

13 files changed

Lines changed: 755 additions & 0 deletions

File tree

.babelrc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"presets": ["es2015", "flow"],
3+
"plugins": [
4+
"transform-object-rest-spread",
5+
"transform-class-properties",
6+
"transform-react-jsx"
7+
]
8+
}

.eslintrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
extends: ['plugin:polymath/recommended']
3+
}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.idea
3+
.DS_Store

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Introducing Polymath.js v2.0
2+
3+
TODO Update
4+
5+
```
6+
await SecurityTokenRegistrar.createSecurityToken(token)
7+
```
8+
This is all you need to create new security token using Polymath.js v2.0. It will:
9+
1. Format data into the blockchain types (e.g. add decimals for token values).
10+
2. Properly estimate gas via Web3 1.0.
11+
3. Make dry run to validate inputs before transaction sending.
12+
4. Notify callbacks with transaction hash and receipt.
13+
5. Check whether the transaction was mined without errors or not.
14+
6. Send necessary requests to the `polymath-api`.
15+
16+
## Key advantages
17+
1. Web3 1.0. It means that we don't need truffle-contract package anymore and we can use async-await, websockets for events (there was bug with disconnection from them, but now it's fixed), proper auto gas estimation.
18+
2. No need to wrap each contract function since v2.0 uses JavaScript Proxy API, which in a simplified manner calls original method if it's not overridden.
19+
```
20+
await PolyToken.symbol()
21+
```
22+
There is no `symbol` entry within the `PolyToken` class, but string above will return you ticker of the Polymath token.
23+
This is how it works.
24+
25+
No excess wrappers means no excess documentation and tests.
26+
27+
## Needs from polymath-core
28+
1. Versioned npm package (with changelog for each new version) with built-in contracts artifacts, which should contain contracts addresses for each network.
29+
2. Complete and up-to-date documentation since Polymath.js will inherit it in many ways.

dist/contracts/Contract.js

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8+
9+
var _web3EthContract = require('web3-eth-contract');
10+
11+
var _web3EthContract2 = _interopRequireDefault(_web3EthContract);
12+
13+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14+
15+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
16+
17+
var Contract = function () {
18+
function Contract(_artifact) {
19+
var _this = this;
20+
21+
_classCallCheck(this, Contract);
22+
23+
this._artifact = null;
24+
this._contract = null;
25+
this._methods = null;
26+
this.address = null;
27+
28+
this._artifact = _artifact;
29+
return new Proxy(this, {
30+
get: function get(target, field) {
31+
try {
32+
target._init();
33+
} catch (e) {
34+
// eslint-disable-next-line
35+
console.error('Contract init failed', e);
36+
return undefined;
37+
}
38+
if (field in target) {
39+
return target[field];
40+
}
41+
var method = target._contract.methods[field];
42+
if (_this._isView(field)) {
43+
return function () {
44+
return method.apply(undefined, arguments).call();
45+
};
46+
}
47+
return function () {
48+
return _this._tx(method.apply(undefined, arguments));
49+
};
50+
}
51+
});
52+
}
53+
54+
_createClass(Contract, [{
55+
key: '_newContract',
56+
57+
58+
/** @private */
59+
value: function _newContract() {
60+
var isWebSockets = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
61+
62+
return new (isWebSockets ? Contract.params.web3WS : Contract.params.web3).eth.Contract(this._artifact.abi, this.address);
63+
}
64+
65+
/** @private */
66+
67+
}, {
68+
key: '_init',
69+
value: function _init() {
70+
var address = this._artifact.networks[Contract.params.id].address;
71+
72+
if (this._contract && this.address === address) {
73+
return;
74+
}
75+
this.address = address;
76+
this._contract = this._newContract();
77+
this._methods = this._contract.methods;
78+
}
79+
80+
/**
81+
* Checks whether a contract function is constant (view) or not.
82+
* @param name
83+
* @returns {boolean}
84+
* @private
85+
*/
86+
87+
}, {
88+
key: '_isView',
89+
value: function _isView(name) {
90+
for (var i = 0; i < this._artifact.abi.length; i++) {
91+
var method = this._artifact.abi[i];
92+
if (method.name === name) {
93+
return method.stateMutability === 'view';
94+
}
95+
}
96+
throw new Error('_isView: no method with "' + name + '" found');
97+
}
98+
99+
/**
100+
* Checks whether a contract function has boolean output or not.
101+
* @param name
102+
* @returns {boolean}
103+
* @private
104+
*/
105+
106+
}, {
107+
key: '_isBoolOutput',
108+
value: function _isBoolOutput(name) {
109+
for (var i = 0; i < this._artifact.abi.length; i++) {
110+
var method = this._artifact.abi[i];
111+
if (method.name === name) {
112+
if (!method.outputs.length) {
113+
return false;
114+
}
115+
return method.outputs[0].name === '' && method.outputs[0].type === 'bool';
116+
}
117+
}
118+
throw new Error('_isBoolOutput: no method with "' + name + '" found');
119+
}
120+
121+
/**
122+
* @param method
123+
* @returns {Promise.<Object>}
124+
* @protected
125+
*/
126+
127+
}, {
128+
key: '_tx',
129+
value: async function _tx(method) {
130+
var params = { from: this.account };
131+
params.gas = await method.estimateGas(params);
132+
133+
// dry run
134+
try {
135+
var okCode = this._isBoolOutput(method._method.name);
136+
var dryResult = await method.call(params);
137+
if (okCode && dryResult !== okCode) {
138+
throw new Error('Expected ' + okCode + ', but received ' + dryResult);
139+
}
140+
} catch (e) {
141+
throw new Error('Transaction dry run failed: ' + e.message);
142+
}
143+
144+
var receipt = await method.send(params, function (error, hash) {
145+
if (!error) {
146+
Contract.params.txHashCallback(hash);
147+
}
148+
});
149+
Contract.params.txEndCallback(receipt);
150+
151+
if (receipt.status === '0x0') {
152+
throw new Error('Transaction failed');
153+
}
154+
155+
return receipt;
156+
}
157+
}, {
158+
key: 'subscribe',
159+
value: async function subscribe(eventName, filter, callback) {
160+
try {
161+
await this._newContract(true).events[eventName]({ filter: filter }, function (error, event) {
162+
if (error) {
163+
// eslint-disable-next-line
164+
console.error('Event "' + eventName + '" subscription error', error);
165+
callback();
166+
return;
167+
}
168+
// eslint-disable-next-line
169+
console.log('Emitted ' + eventName + ' event', event);
170+
callback(event);
171+
});
172+
return true;
173+
} catch (e) {
174+
// eslint-disable-next-line
175+
console.error('Event "' + eventName + '" subscription failed', e);
176+
return false;
177+
}
178+
}
179+
180+
/**
181+
* @param v
182+
* @returns {string}
183+
* @protected
184+
*/
185+
186+
}, {
187+
key: '_toBytes',
188+
value: function _toBytes(v) {
189+
return Contract._web3.utils.asciiToHex(v);
190+
}
191+
192+
/**
193+
* @param v
194+
* @returns {boolean}
195+
* @protected
196+
*/
197+
198+
}, {
199+
key: '_isEmptyAddress',
200+
value: function _isEmptyAddress(v) {
201+
return v === '0x0000000000000000000000000000000000000000';
202+
}
203+
}, {
204+
key: 'account',
205+
get: function get() {
206+
return Contract.params.account;
207+
}
208+
}]);
209+
210+
return Contract;
211+
}();
212+
213+
Contract.params = null;
214+
exports.default = Contract;

dist/contracts/PolyToken.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
'use strict';
2+
3+
Object.defineProperty(exports, "__esModule", {
4+
value: true
5+
});
6+
7+
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
8+
9+
var _bignumber = require('bignumber.js');
10+
11+
var _bignumber2 = _interopRequireDefault(_bignumber);
12+
13+
var _PolyToken = require('../../tmp/PolyToken.json');
14+
15+
var _PolyToken2 = _interopRequireDefault(_PolyToken);
16+
17+
var _Contract2 = require('./Contract');
18+
19+
var _Contract3 = _interopRequireDefault(_Contract2);
20+
21+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
22+
23+
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
24+
25+
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
26+
27+
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } // TODO @bshevchenko: will be replaced with artifact from polymath-core_v2 npm package
28+
29+
30+
var PolyToken = function (_Contract) {
31+
_inherits(PolyToken, _Contract);
32+
33+
function PolyToken() {
34+
var _ref;
35+
36+
var _temp, _this, _ret;
37+
38+
_classCallCheck(this, PolyToken);
39+
40+
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
41+
args[_key] = arguments[_key];
42+
}
43+
44+
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = PolyToken.__proto__ || Object.getPrototypeOf(PolyToken)).call.apply(_ref, [this].concat(args))), _this), _this.decimals = 18, _temp), _possibleConstructorReturn(_this, _ret);
45+
}
46+
47+
_createClass(PolyToken, [{
48+
key: 'addDecimals',
49+
value: function addDecimals(n) {
50+
return new _bignumber2.default(10).toPower(this.decimals).times(n);
51+
}
52+
}, {
53+
key: 'removeDecimals',
54+
value: function removeDecimals(n) {
55+
return new _bignumber2.default(n).div(new _bignumber2.default(10).toPower(this.decimals));
56+
}
57+
}, {
58+
key: 'balanceOf',
59+
value: async function balanceOf(account) {
60+
return this.removeDecimals((await this._methods.balanceOf(account).call()));
61+
}
62+
}, {
63+
key: 'myBalance',
64+
value: async function myBalance() {
65+
return this.balanceOf(this.account);
66+
}
67+
}, {
68+
key: 'allowance',
69+
value: async function allowance(owner, spender) {
70+
return this.removeDecimals((await this._methods.allowance(owner, spender).call()));
71+
}
72+
}, {
73+
key: 'getTokens',
74+
value: async function getTokens(amount) {
75+
await this._tx(this._methods.getTokens(this.addDecimals(amount)));
76+
}
77+
}, {
78+
key: 'approve',
79+
value: async function approve(spender, amount) {
80+
await this._tx(this._methods.approve(spender, this.addDecimals(amount)));
81+
}
82+
}]);
83+
84+
return PolyToken;
85+
}(_Contract3.default);
86+
87+
exports.default = new PolyToken(_PolyToken2.default);

0 commit comments

Comments
 (0)