UNPKG

4.58 kBJavaScriptView Raw
1const lodash = require('lodash');
2const ContractABI = require('./ContractABI');
3const ContractConstructor = require('./method/ContractConstructor');
4const ContractMethod = require('./method/ContractMethod');
5const ContractMethodOverride = require('./method/ContractMethodOverride');
6const ContractEvent = require('./event/ContractEvent');
7const ContractEventOverride = require('./event/ContractEventOverride');
8
9/**
10 * Contract with all its methods and events defined in its abi.
11 */
12class Contract {
13 /**
14 * @param options {object}
15 * @param options.abi {array} - The json interface for the contract to instantiate
16 * @param [options.address] {string} - The address of the smart contract to call, can be added later using `contract.address = '0x1234...'`
17 * @param [options.bytecode] {string} - The byte code of the contract, can be added later using `contract.constructor.code = '0x1234...'`
18 * @param conflux {Conflux} - Conflux instance.
19 * @return {object}
20 *
21 * @example
22 * > const contract = conflux.Contract({ abi, bytecode });
23 {
24 constructor: [Function: bound call],
25 abi: ContractABI { * },
26 address: undefined,
27 count: [Function: bound call],
28 inc: [Function: bound call],
29 'count()': [Function: bound call],
30 '0x06661abd': [Function: bound call],
31 'inc(uint256)': [Function: bound call],
32 '0x812600df': [Function: bound call],
33 }
34
35 * > contract.constructor.bytecode; // input code
36 "0x6080604052600080..."
37
38 * @example
39 * > const contract = conflux.Contract({ abi, address });
40 * > contract.address
41 "0xc3ed1a06471be1d3bcd014051fbe078387ec0ad8"
42
43 * > await contract.count(); // call a method without parameter, get decoded return value.
44 "100"
45 * > await contract.inc(1); // call a method with parameters, get decoded return value.
46 "101"
47 * > await contract.count().options({ from: account }); // call a method from a account.
48 "100"
49
50 * > transaction = await conflux.getTransactionByHash('0x8a5f48c2de0f1bdacfe90443810ad650e4b327a0d19ce49a53faffb224883e42');
51 * > await contract.abi.decodeData(transaction.data)
52 {
53 name: 'inc',
54 fullName: 'inc(uint256 num)',
55 type: 'inc(uint256)',
56 signature: '0x7f98a45e',
57 array: [ JSBI.BigInt(101) ],
58 object: { num: JSBI.BigInt(101) }
59 }
60
61 * > await contract.count(); // data in block chain changed by transaction.
62 JSBI.BigInt(101)
63
64 * > receipt = await conflux.getTransactionReceipt('0x8a5f48c2de0f1bdacfe90443810ad650e4b327a0d19ce49a53faffb224883e42');
65 * > contract.abi.decodeLog(receipt.logs[0]);
66 {
67 name: 'SelfEvent',
68 fullName: 'SelfEvent(address indexed sender, uint256 current)',
69 type: 'SelfEvent(address,uint256))',
70 signature: '0xc4c01f6de493c58245fb681341f3a76bba9551ce81b11cbbb5d6d297844594df',
71 array: [ '0xbbd9e9be525ab967e633bcdaeac8bd5723ed4d6b', JSBI.BigInt(100) ],
72 object: {
73 sender: '0xbbd9e9be525ab967e633bcdaeac8bd5723ed4d6b',
74 current: JSBI.BigInt(100),
75 },
76 }
77 */
78 constructor({ abi, address, bytecode }, conflux) {
79 const abiTable = lodash.groupBy(abi, 'type');
80 this.abi = new ContractABI(this); // XXX: Create a method named `abi` in solidity is a `Warning`.
81
82 this.address = address; // XXX: Create a method named `address` in solidity is a `ParserError`
83
84 // constructor
85 this.constructor = new ContractConstructor(lodash.first(abiTable.constructor), bytecode, this, conflux);
86
87 // method
88 const methodArray = lodash.map(abiTable.function, fragment => new ContractMethod(fragment, this, conflux));
89 lodash.forEach(lodash.groupBy(methodArray, 'name'), (array, name) => {
90 this[name] = array.length === 1 ? lodash.first(array) : new ContractMethodOverride(array, this, conflux);
91
92 array.forEach(method => {
93 this[method.type] = method;
94 this[method.signature] = method; // signature for contract abi decoder to decode
95 });
96 });
97
98 // event
99 const eventArray = lodash.map(abiTable.event, fragment => new ContractEvent(fragment, this, conflux));
100 lodash.forEach(lodash.groupBy(eventArray, 'name'), (array, name) => {
101 this[name] = array.length === 1 ? lodash.first(array) : new ContractEventOverride(array, this, conflux);
102
103 array.forEach(event => {
104 this[event.type] = event;
105 this[event.signature] = event; // signature for contract abi decoder to decode
106 });
107 });
108 }
109}
110
111module.exports = Contract;