@aeternity/aepp-sdk 9.0.1 → 10.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/aepp-sdk.browser-script.js +1 -1
  2. package/dist/aepp-sdk.browser-script.js.LICENSE.txt +0 -9
  3. package/dist/aepp-sdk.browser-script.js.map +1 -1
  4. package/dist/aepp-sdk.browser.js +1 -1
  5. package/dist/aepp-sdk.browser.js.map +1 -1
  6. package/dist/aepp-sdk.js +1 -1
  7. package/dist/aepp-sdk.js.map +1 -1
  8. package/es/account/base.js +30 -122
  9. package/es/account/base.js.map +1 -1
  10. package/es/account/memory.js +17 -19
  11. package/es/account/memory.js.map +1 -1
  12. package/es/account/multiple.js +73 -164
  13. package/es/account/multiple.js.map +1 -1
  14. package/es/ae/aens.js +164 -599
  15. package/es/ae/aens.js.map +1 -1
  16. package/es/ae/contract.js +82 -759
  17. package/es/ae/contract.js.map +1 -1
  18. package/es/ae/index.js +78 -315
  19. package/es/ae/index.js.map +1 -1
  20. package/es/ae/oracle.js +130 -498
  21. package/es/ae/oracle.js.map +1 -1
  22. package/es/chain/index.js +1 -1
  23. package/es/chain/index.js.map +1 -1
  24. package/es/chain/node.js +288 -1008
  25. package/es/chain/node.js.map +1 -1
  26. package/es/channel/handlers.js +597 -1086
  27. package/es/channel/handlers.js.map +1 -1
  28. package/es/channel/index.js +203 -451
  29. package/es/channel/index.js.map +1 -1
  30. package/es/channel/internal.js +129 -301
  31. package/es/channel/internal.js.map +1 -1
  32. package/es/contract/aci/index.js +319 -480
  33. package/es/contract/aci/index.js.map +1 -1
  34. package/es/contract/aci/transformation.js +35 -711
  35. package/es/contract/aci/transformation.js.map +1 -1
  36. package/es/contract/compiler.js +129 -203
  37. package/es/contract/compiler.js.map +1 -1
  38. package/es/contract/ga/helpers.js +16 -114
  39. package/es/contract/ga/helpers.js.map +1 -1
  40. package/es/contract/ga/index.js +101 -242
  41. package/es/contract/ga/index.js.map +1 -1
  42. package/es/contract/index.js +1 -1
  43. package/es/contract/index.js.map +1 -1
  44. package/es/index.js +1 -2
  45. package/es/index.js.map +1 -1
  46. package/es/node-pool/index.js +54 -73
  47. package/es/node-pool/index.js.map +1 -1
  48. package/es/node.js +56 -157
  49. package/es/node.js.map +1 -1
  50. package/es/other.d.ts +1 -1
  51. package/es/tx/builder/helpers.js +38 -75
  52. package/es/tx/builder/helpers.js.map +1 -1
  53. package/es/tx/builder/index.js +196 -294
  54. package/es/tx/builder/index.js.map +1 -1
  55. package/es/tx/builder/schema.js +577 -459
  56. package/es/tx/builder/schema.js.map +1 -1
  57. package/es/tx/index.js +1 -1
  58. package/es/tx/index.js.map +1 -1
  59. package/es/tx/tx-object.js +105 -132
  60. package/es/tx/tx-object.js.map +1 -1
  61. package/es/tx/tx.js +808 -1628
  62. package/es/tx/tx.js.map +1 -1
  63. package/es/tx/validator.js +132 -268
  64. package/es/tx/validator.js.map +1 -1
  65. package/es/utils/aepp-wallet-communication/connection/browser-runtime.js +17 -21
  66. package/es/utils/aepp-wallet-communication/connection/browser-runtime.js.map +1 -1
  67. package/es/utils/aepp-wallet-communication/connection/browser-window-message.js +38 -74
  68. package/es/utils/aepp-wallet-communication/connection/browser-window-message.js.map +1 -1
  69. package/es/utils/aepp-wallet-communication/content-script-bridge.js +14 -15
  70. package/es/utils/aepp-wallet-communication/content-script-bridge.js.map +1 -1
  71. package/es/utils/aepp-wallet-communication/helpers.js +60 -105
  72. package/es/utils/aepp-wallet-communication/helpers.js.map +1 -1
  73. package/es/utils/aepp-wallet-communication/rpc/aepp-rpc.js +179 -510
  74. package/es/utils/aepp-wallet-communication/rpc/aepp-rpc.js.map +1 -1
  75. package/es/utils/aepp-wallet-communication/rpc/rpc-client.js +70 -89
  76. package/es/utils/aepp-wallet-communication/rpc/rpc-client.js.map +1 -1
  77. package/es/utils/aepp-wallet-communication/rpc/wallet-rpc.js +353 -600
  78. package/es/utils/aepp-wallet-communication/rpc/wallet-rpc.js.map +1 -1
  79. package/es/utils/aepp-wallet-communication/schema.js +43 -39
  80. package/es/utils/aepp-wallet-communication/schema.js.map +1 -1
  81. package/es/utils/aepp-wallet-communication/wallet-detector.js +32 -58
  82. package/es/utils/aepp-wallet-communication/wallet-detector.js.map +1 -1
  83. package/es/utils/amount-formatter.js +41 -61
  84. package/es/utils/amount-formatter.js.map +1 -1
  85. package/es/utils/async-init.js +28 -64
  86. package/es/utils/async-init.js.map +1 -1
  87. package/es/utils/bignumber.js +3 -11
  88. package/es/utils/bignumber.js.map +1 -1
  89. package/es/utils/bytes.js +5 -9
  90. package/es/utils/bytes.js.map +1 -1
  91. package/es/utils/crypto.js +47 -62
  92. package/es/utils/crypto.js.map +1 -1
  93. package/es/utils/hd-wallet.js +45 -81
  94. package/es/utils/hd-wallet.js.map +1 -1
  95. package/es/utils/json-big.js +16 -49
  96. package/es/utils/json-big.js.map +1 -1
  97. package/es/utils/keystore.js +81 -246
  98. package/es/utils/keystore.js.map +1 -1
  99. package/es/utils/mptree.js +88 -134
  100. package/es/utils/mptree.js.map +1 -1
  101. package/es/utils/other.js +10 -60
  102. package/es/utils/other.js.map +1 -1
  103. package/es/utils/semver-satisfies.js +9 -28
  104. package/es/utils/semver-satisfies.js.map +1 -1
  105. package/es/utils/string.js +4 -13
  106. package/es/utils/string.js.map +1 -1
  107. package/es/utils/swagger.js +85 -224
  108. package/es/utils/swagger.js.map +1 -1
  109. package/package.json +44 -40
  110. package/src/account/multiple.js +18 -19
  111. package/src/ae/aens.js +25 -21
  112. package/src/ae/contract.js +32 -163
  113. package/src/ae/index.js +3 -3
  114. package/src/ae/oracle.js +18 -14
  115. package/src/chain/node.js +2 -4
  116. package/src/channel/handlers.js +0 -1
  117. package/src/channel/index.js +4 -5
  118. package/src/contract/aci/index.js +221 -102
  119. package/src/contract/aci/transformation.js +30 -422
  120. package/src/contract/compiler.js +45 -4
  121. package/src/contract/ga/helpers.js +1 -8
  122. package/src/contract/ga/index.js +13 -11
  123. package/src/index.js +0 -2
  124. package/src/node-pool/index.js +21 -12
  125. package/src/node.js +22 -26
  126. package/src/tx/builder/index.js +2 -1
  127. package/src/tx/builder/schema.js +2 -1
  128. package/src/tx/tx.js +147 -143
  129. package/src/tx/validator.js +9 -7
  130. package/src/utils/aepp-wallet-communication/rpc/aepp-rpc.js +1 -3
  131. package/src/utils/aepp-wallet-communication/rpc/wallet-rpc.js +3 -3
  132. package/src/utils/aepp-wallet-communication/schema.js +1 -3
  133. package/src/utils/bignumber.ts +2 -1
  134. package/src/utils/other.ts +1 -1
  135. package/src/utils/semver-satisfies.ts +1 -1
  136. package/src/utils/swagger.js +14 -7
  137. package/src/contract/aci/helpers.js +0 -140
@@ -24,108 +24,257 @@
24
24
 
25
25
  import * as R from 'ramda'
26
26
  import BigNumber from 'bignumber.js'
27
+ import { Encoder as Calldata } from '@aeternity/aepp-calldata'
28
+ import { decodeEvents } from './transformation'
29
+ import { DRY_RUN_ACCOUNT, DEPOSIT } from '../../tx/builder/schema'
30
+ import TxObject from '../../tx/tx-object'
31
+ import { decode } from '../../tx/builder/helpers'
27
32
 
28
- import {
29
- buildContractMethods,
30
- decodeCallResult,
31
- decodeEvents,
32
- getFunctionACI,
33
- prepareArgsForEncode as prepareArgs
34
- } from './helpers'
33
+ /**
34
+ * Get function schema from contract ACI object
35
+ * @param {Object} aci Contract ACI object
36
+ * @param {String} name Function name
37
+ * @param external
38
+ * @return {Object} function ACI
39
+ */
40
+ function getFunctionACI (aci, name, external) {
41
+ const fn = aci.functions.find(f => f.name === name)
42
+ if (!fn && name !== 'init') throw new Error(`Function ${name} doesn't exist in contract`)
43
+
44
+ return {
45
+ ...fn,
46
+ bindings: [
47
+ {
48
+ state: aci.state,
49
+ type_defs: aci.type_defs,
50
+ name: aci.name
51
+ },
52
+ ...external.map(R.pick(['state', 'type_defs', 'name']))
53
+ ],
54
+ event: aci.event ? aci.event.variant : []
55
+ }
56
+ }
35
57
 
36
58
  /**
37
59
  * Generate contract ACI object with predefined js methods for contract usage - can be used for creating a reference to already deployed contracts
38
60
  * @alias module:@aeternity/aepp-sdk/es/contract/aci
39
- * @param {String} source Contract source code
40
61
  * @param {Object} [options={}] Options object
41
- * @param {String} [options.aci] Contract ACI
62
+ * @param {String} [options.source] Contract source code
63
+ * @param {String} [options.bytecode] Contract bytecode
64
+ * @param {Object} [options.aci] Contract ACI
42
65
  * @param {String} [options.contractAddress] Contract address
43
66
  * @param {Object} [options.filesystem] Contact source external namespaces map
44
- * @param {Object} [options.forceCodeCheck=true] Don't check contract code
45
- * @param {Object} [options.opt] Contract options
67
+ * @param {Boolean} [options.validateBytecode] Compare source code with on-chain version
46
68
  * @return {ContractInstance} JS Contract API
47
69
  * @example
48
- * const contractIns = await client.getContractInstance(sourceCode)
70
+ * const contractIns = await client.getContractInstance({ source })
49
71
  * await contractIns.deploy([321]) or await contractIns.methods.init(321)
50
72
  * const callResult = await contractIns.call('setState', [123]) or await contractIns.methods.setState.send(123, options)
51
73
  * const staticCallResult = await contractIns.call('setState', [123], { callStatic: true }) or await contractIns.methods.setState.get(123, options)
52
74
  * Also you can call contract like: await contractIns.methods.setState(123, options)
53
75
  * Then sdk decide to make on-chain or static call(dry-run API) transaction based on function is stateful or not
54
76
  */
55
- export default async function getContractInstance (source, { aci, contractAddress, filesystem = {}, forceCodeCheck = true, opt } = {}) {
56
- aci = aci || await this.contractGetACI(source, { filesystem })
57
- if (contractAddress) contractAddress = await this.resolveName(contractAddress, 'ct', { resolveByNode: true })
58
- const defaultOptions = {
59
- ...this.Ae.defaults,
60
- skipArgsConvert: false,
61
- skipTransformDecoded: false,
62
- callStatic: false,
63
- filesystem
77
+ export default async function getContractInstance ({
78
+ source,
79
+ bytecode,
80
+ aci,
81
+ contractAddress,
82
+ filesystem = {},
83
+ validateBytecode,
84
+ ...otherOptions
85
+ } = {}) {
86
+ aci = aci || (source && await this.contractGetACI(source, { filesystem }))
87
+ if (!aci) throw new Error('Either ACI or source code is required')
88
+ contractAddress = contractAddress && await this.resolveName(
89
+ contractAddress, 'ct', { resolveByNode: true }
90
+ )
91
+ if (!contractAddress && !source && !bytecode) throw new Error('Can\'t create instance by ACI without address')
92
+
93
+ if (contractAddress) {
94
+ const contract = await this.getContract(contractAddress).catch(() => null)
95
+ if (!contract) throw new Error(`Contract with address ${contractAddress} not found on-chain`)
96
+ if (!contract.active) throw new Error(`Contract with address ${contractAddress} not active`)
64
97
  }
98
+
65
99
  const instance = {
66
100
  interface: R.defaultTo(null, R.prop('interface', aci)),
67
101
  aci: R.defaultTo(null, R.path(['encoded_aci', 'contract'], aci)),
102
+ calldata: new Calldata([aci.encoded_aci, ...aci.external_encoded_aci]),
68
103
  externalAci: aci.external_encoded_aci ? aci.external_encoded_aci.map(a => a.contract || a.namespace) : [],
69
104
  source,
70
- compiled: null,
105
+ bytecode,
71
106
  deployInfo: { address: contractAddress },
72
- options: R.merge(defaultOptions, opt),
73
- compilerVersion: this.compilerVersion,
74
- setOptions (opt) {
75
- this.options = R.merge(this.options, opt)
76
- }
107
+ options: {
108
+ ...this.Ae.defaults,
109
+ callStatic: false,
110
+ filesystem,
111
+ ...otherOptions
112
+ },
113
+ compilerVersion: this.compilerVersion
77
114
  }
78
115
 
79
- // Check for valid contract address and contract code
80
- if (contractAddress) {
81
- const contract = await this.getContract(contractAddress).catch(e => null)
82
- if (!contract || !contract.active) throw new Error(`Contract with address ${contractAddress} not found on-chain or not active`)
83
- if (!forceCodeCheck) {
84
- const onChanByteCode = (await this.getContractByteCode(contractAddress)).bytecode
85
- const isCorrespondingBytecode = await this.validateByteCodeAPI(onChanByteCode, instance.source, instance.options).catch(e => false)
86
- if (!isCorrespondingBytecode) throw new Error('Contract source do not correspond to the contract bytecode deployed on the chain')
87
- }
116
+ if (validateBytecode) {
117
+ if (!contractAddress) throw new Error('Can\'t validate bytecode without contract address')
118
+ const onChanBytecode = (await this.getContractByteCode(contractAddress)).bytecode
119
+ const isValid = (source && await this
120
+ .validateByteCodeAPI(onChanBytecode, source, instance.options).catch(() => false)) ||
121
+ bytecode === onChanBytecode
122
+ if (!isValid) throw new Error(`Contract ${source ? 'source' : 'bytecode'} do not correspond to the bytecode deployed on the chain`)
88
123
  }
89
124
 
90
125
  /**
91
126
  * Compile contract
92
127
  * @alias module:@aeternity/aepp-sdk/es/contract/aci
93
128
  * @rtype () => ContractInstance: Object
94
- * @return {ContractInstance} Contract ACI object with predefined js methods for contract usage
129
+ * @return {String} bytecode bytecode
95
130
  */
96
- instance.compile = compile({ client: this, instance })
131
+ instance.compile = async (options = {}) => {
132
+ if (instance.bytecode) throw new Error('Contract already compiled')
133
+ if (!instance.source) throw new Error('Can\'t compile without source code')
134
+ const { bytecode } = await this.contractCompile(instance.source, { ...instance.options, ...options })
135
+ instance.bytecode = bytecode
136
+ return instance.bytecode
137
+ }
138
+
139
+ const sendAndProcess = async (tx, options) => {
140
+ const txData = await this.send(tx, options)
141
+ const result = {
142
+ hash: txData.hash, tx: TxObject({ tx: txData.rawTx }), txData, rawTx: txData.rawTx
143
+ }
144
+ if (options.waitMined === false) return result
145
+ const txInfo = await this.getTxInfo(txData.hash)
146
+ await handleCallError(txInfo)
147
+ return { ...result, result: txInfo }
148
+ }
149
+
150
+ const handleCallError = ({ returnType, returnValue }) => {
151
+ let message
152
+ // TODO: ensure that it works correctly https://github.com/aeternity/aepp-calldata-js/issues/88
153
+ switch (returnType) {
154
+ case 'ok': return
155
+ case 'revert':
156
+ message = instance.calldata.decodeFateString(returnValue)
157
+ break
158
+ case 'error':
159
+ message = decode(returnValue).toString()
160
+ break
161
+ default: throw new Error(`Unknown returnType: ${returnType}`)
162
+ }
163
+ throw new Error(`Invocation failed${message ? `: "${message}"` : ''}`)
164
+ }
165
+
97
166
  /**
98
167
  * Deploy contract
99
168
  * @alias module:@aeternity/aepp-sdk/es/contract/aci
100
- * @rtype (init: Array, options: Object = { skipArgsConvert: false }) => ContractInstance: Object
101
- * @param {Array} init Contract init function arguments array
102
- * @param {Object} [options={}] options Options object
103
- * @param {Boolean} [options.skipArgsConvert=false] Skip Validation and Transforming arguments before prepare call-data
104
- * @return {ContractInstance} Contract ACI object with predefined js methods for contract usage
169
+ * @rtype (init: Array, options: Object) => ContractInstance: Object
170
+ * @param {Array} params Contract init function arguments array
171
+ * @param {Object} [options] options
172
+ * @return {Object} deploy info
105
173
  */
106
- instance.deploy = deploy({ client: this, instance })
174
+ instance.deploy = async (params = [], options) => {
175
+ const opt = { ...instance.options, ...options, deposit: DEPOSIT }
176
+ if (!instance.bytecode) await instance.compile(opt)
177
+ if (opt.callStatic) return instance.call('init', params, opt)
178
+ if (instance.deployInfo.address) throw new Error('Contract already deployed')
179
+
180
+ const ownerId = await this.address(opt)
181
+ const { tx, contractId } = await this.contractCreateTx({
182
+ ...opt,
183
+ callData: instance.calldata.encode(instance.aci.name, 'init', params),
184
+ code: instance.bytecode,
185
+ ownerId
186
+ })
187
+ const { hash, rawTx, result, txData } = await sendAndProcess(tx, opt)
188
+ instance.deployInfo = Object.freeze({
189
+ result,
190
+ owner: ownerId,
191
+ transaction: hash,
192
+ rawTx,
193
+ txData,
194
+ address: contractId,
195
+ call: (name, args, options) =>
196
+ this.contractCall(instance.source, contractId, name, args, { ...opt, ...options }),
197
+ callStatic: (name, args, options) =>
198
+ this.contractCallStatic(instance.source, contractId, name, args, { ...opt, ...options }),
199
+ createdAt: new Date()
200
+ })
201
+ return instance.deployInfo
202
+ }
203
+
107
204
  /**
108
205
  * Call contract function
109
206
  * @alias module:@aeternity/aepp-sdk/es/contract/aci
110
- * @rtype (init: Array, options: Object = { skipArgsConvert: false, skipTransformDecoded: false, callStatic: false }) => CallResult: Object
207
+ * @rtype (init: Array, options: Object = { callStatic: false }) => CallResult: Object
111
208
  * @param {String} fn Function name
112
209
  * @param {Array} params Array of function arguments
113
210
  * @param {Object} [options={}] Array of function arguments
114
- * @param {Boolean} [options.skipArgsConvert=false] Skip Validation and Transforming arguments before prepare call-data
115
- * @param {Boolean} [options.skipTransformDecoded=false] Skip Transform decoded data to JS type
116
211
  * @param {Boolean} [options.callStatic=false] Static function call
117
212
  * @return {Object} CallResult
118
213
  */
119
- instance.call = call({ client: this, instance })
214
+ instance.call = async (fn, params = [], options = {}) => {
215
+ const opt = { ...instance.options, ...options }
216
+ const fnACI = getFunctionACI(instance.aci, fn, instance.externalAci)
217
+ const contractId = instance.deployInfo.address
218
+
219
+ if (!fn) throw new Error('Function name is required')
220
+ if (fn === 'init' && !opt.callStatic) throw new Error('"init" can be called only via dryRun')
221
+ if (!contractId && fn !== 'init') throw new Error('You need to deploy contract before calling!')
222
+ if (
223
+ BigNumber(opt.amount).gt(0) &&
224
+ (Object.prototype.hasOwnProperty.call(fnACI, 'payable') && !fnACI.payable)
225
+ ) throw new Error(`You try to pay "${opt.amount}" to function "${fn}" which is not payable. Only payable function can accept tokens`)
226
+
227
+ const callerId = await this.address(opt).catch(error => {
228
+ if (opt.callStatic) return DRY_RUN_ACCOUNT.pub
229
+ else throw error
230
+ })
231
+ const callData = instance.calldata.encode(instance.aci.name, fn, params)
232
+
233
+ let res
234
+ if (opt.callStatic) {
235
+ if (typeof opt.top === 'number') {
236
+ opt.top = (await this.getKeyBlock(opt.top)).hash
237
+ }
238
+ const txOpt = {
239
+ ...opt,
240
+ callData,
241
+ nonce: opt.top && (await this.getAccount(callerId, { hash: opt.top })).nonce + 1
242
+ }
243
+ const tx = fn === 'init'
244
+ ? (await this.contractCreateTx({ ...txOpt, code: instance.bytecode, ownerId: callerId })).tx
245
+ : await this.contractCallTx({ ...txOpt, callerId, contractId })
246
+
247
+ const { callObj, ...dryRunOther } = await this.txDryRun(tx, callerId, opt)
248
+ await handleCallError(callObj)
249
+ res = { ...dryRunOther, tx: TxObject({ tx }), result: callObj }
250
+ } else {
251
+ const tx = await this.contractCallTx({ ...opt, callerId, contractId, callData })
252
+ res = await sendAndProcess(tx, opt)
253
+ }
254
+ if (opt.waitMined || opt.callStatic) {
255
+ res.decodedResult = fnACI.returns && fnACI.returns !== 'unit' && fn !== 'init' &&
256
+ instance.calldata.decode(instance.aci.name, fn, res.result.returnValue)
257
+ res.decodedEvents = instance.decodeEvents(res.result.log)
258
+ }
259
+ return res
260
+ }
261
+
120
262
  /**
121
263
  * Decode Events
122
264
  * @alias module:@aeternity/aepp-sdk/es/contract/aci
123
- * @rtype (fn: String, events: Array) => DecodedEvents: Array
124
- * @param {String} fn Function name
265
+ * @rtype (events: Array) => DecodedEvents: Array
125
266
  * @param {Array} events Array of encoded events(callRes.result.log)
126
267
  * @return {Object} DecodedEvents
127
268
  */
128
- instance.decodeEvents = eventDecode({ instance })
269
+ instance.decodeEvents = (events) => {
270
+ const eventsACI = instance.aci.event ? instance.aci.event.variant : []
271
+ const eventsSchema = eventsACI.map(e => {
272
+ const name = Object.keys(e)[0]
273
+ return { name, types: e[name] }
274
+ })
275
+
276
+ return decodeEvents(events, eventsSchema)
277
+ }
129
278
 
130
279
  /**
131
280
  * Generate proto function based on contract function using Contract ACI schema
@@ -135,57 +284,27 @@ export default async function getContractInstance (source, { aci, contractAddres
135
284
  * `await contract.methods.testFunction.get()` -> use call-static(dry-run)
136
285
  * `await contract.methods.testFunction.send()` -> send tx on-chain
137
286
  */
138
- instance.methods = buildContractMethods(instance)()
139
- return instance
140
- }
141
-
142
- const eventDecode = ({ instance }) => (fn, events) => {
143
- return decodeEvents(events, getFunctionACI(instance.aci, fn, { external: instance.externalAci }))
144
- }
145
-
146
- const call = ({ client, instance }) => async (fn, params = [], options = {}) => {
147
- const opt = { ...instance.options, ...options }
148
- const fnACI = getFunctionACI(instance.aci, fn, { external: instance.externalAci })
149
- const source = opt.source || instance.source
150
-
151
- if (!fn) throw new Error('Function name is required')
152
- if (!instance.deployInfo.address) throw new Error('You need to deploy contract before calling!')
153
- if (
154
- BigNumber(opt.amount).gt(0) &&
155
- (Object.prototype.hasOwnProperty.call(fnACI, 'payable') && !fnACI.payable)
156
- ) throw new Error(`You try to pay "${opt.amount}" to function "${fn}" which is not payable. Only payable function can accept tokens`)
157
- params = !opt.skipArgsConvert ? await prepareArgs(fnACI, params) : params
158
- const result = opt.callStatic
159
- ? await client.contractCallStatic(source, instance.deployInfo.address, fn, params, opt)
160
- : await client.contractCall(source, instance.deployInfo.address, fn, params, opt)
161
- return {
162
- ...result,
163
- ...opt.waitMined ? await decodeCallResult(result, fnACI, opt) : {}
164
- }
165
- }
166
-
167
- const deploy = ({ client, instance }) => async (init = [], options = {}) => {
168
- const opt = { ...instance.options, ...options }
169
- const fnACI = getFunctionACI(instance.aci, 'init', { external: instance.externalAci })
170
- const source = opt.source || instance.source
171
-
172
- if (!instance.compiled) await instance.compile(opt)
173
- init = !opt.skipArgsConvert ? await prepareArgs(fnACI, init) : init
174
-
175
- if (opt.callStatic) {
176
- return client.contractCallStatic(source, null, 'init', init, {
177
- ...opt,
178
- bytecode: instance.compiled
287
+ instance.methods = Object.fromEntries(instance.aci.functions
288
+ .map(({ name, arguments: aciArgs, stateful }) => {
289
+ const genHandler = callStatic => (...args) => {
290
+ const options = args.length === aciArgs.length + 1 ? args.pop() : {}
291
+ if (typeof options !== 'object') throw new Error(`Options should be an object: ${options}`)
292
+ if (name === 'init') return instance.deploy(args, { callStatic, ...options })
293
+ return instance.call(name, args, { callStatic, ...options })
294
+ }
295
+ return [
296
+ name,
297
+ Object.assign(
298
+ genHandler(name === 'init' ? false : !stateful),
299
+ {
300
+ get: genHandler(true),
301
+ send: genHandler(false),
302
+ decodeEvents: events => instance.decodeEvents(events)
303
+ }
304
+ )
305
+ ]
179
306
  })
180
- } else {
181
- const { owner, transaction, address, createdAt, result, rawTx } = await client.contractDeploy(instance.compiled, opt.source || instance.source, init, opt)
182
- instance.deployInfo = { owner, transaction, address, createdAt, result, rawTx }
183
- return instance.deployInfo
184
- }
185
- }
307
+ )
186
308
 
187
- const compile = ({ client, instance }) => async (options = {}) => {
188
- const { bytecode } = await client.contractCompile(instance.source, { ...instance.options, ...options })
189
- instance.compiled = bytecode
190
- return instance.compiled
309
+ return instance
191
310
  }