@aeternity/aepp-sdk 10.0.0 → 11.0.0
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.
- package/README.md +15 -14
- package/dist/aepp-sdk.browser-script.js +1 -1
- package/dist/aepp-sdk.browser-script.js.LICENSE.txt +7 -27
- package/dist/aepp-sdk.browser-script.js.map +1 -1
- package/dist/aepp-sdk.browser.js +1 -1
- package/dist/aepp-sdk.browser.js.map +1 -1
- package/dist/aepp-sdk.js +1 -1
- package/dist/aepp-sdk.js.map +1 -1
- package/es/account/{base.js → base.mjs} +20 -10
- package/es/account/base.mjs.map +1 -0
- package/es/account/{memory.js → memory.mjs} +29 -14
- package/es/account/memory.mjs.map +1 -0
- package/es/account/{multiple.js → multiple.mjs} +10 -9
- package/es/account/multiple.mjs.map +1 -0
- package/es/ae/{aens.js → aens.mjs} +18 -22
- package/es/ae/aens.mjs.map +1 -0
- package/es/ae/{aepp.js → aepp.mjs} +9 -9
- package/es/ae/aepp.mjs.map +1 -0
- package/es/ae/contract.mjs +159 -0
- package/es/ae/contract.mjs.map +1 -0
- package/es/ae/{index.js → index.mjs} +8 -7
- package/es/ae/index.mjs.map +1 -0
- package/es/ae/{oracle.js → oracle.mjs} +33 -16
- package/es/ae/oracle.mjs.map +1 -0
- package/es/ae/{universal.js → universal.mjs} +10 -10
- package/es/ae/universal.mjs.map +1 -0
- package/es/ae/{wallet.js → wallet.mjs} +10 -10
- package/es/ae/wallet.mjs.map +1 -0
- package/es/aepp-wallet-communication/schema.d.ts +74 -0
- package/es/bignumber.d.ts +1 -7
- package/es/chain/{index.js → index.mjs} +20 -4
- package/es/chain/index.mjs.map +1 -0
- package/es/chain/{node.js → node.mjs} +121 -73
- package/es/chain/node.mjs.map +1 -0
- package/es/channel/{handlers.js → handlers.mjs} +18 -20
- package/es/channel/handlers.mjs.map +1 -0
- package/es/channel/{index.js → index.mjs} +7 -7
- package/es/channel/index.mjs.map +1 -0
- package/es/channel/{internal.js → internal.mjs} +49 -32
- package/es/channel/internal.mjs.map +1 -0
- package/es/contract/aci.mjs +477 -0
- package/es/contract/aci.mjs.map +1 -0
- package/es/contract/compiler.mjs +115 -0
- package/es/contract/compiler.mjs.map +1 -0
- package/es/contract/ga/helpers.mjs +30 -0
- package/es/contract/ga/helpers.mjs.map +1 -0
- package/es/contract/ga/{index.js → index.mjs} +36 -28
- package/es/contract/ga/index.mjs.map +1 -0
- package/es/errors.d.ts +284 -0
- package/es/index.mjs +57 -0
- package/es/index.mjs.map +1 -0
- package/es/node-pool/{index.js → index.mjs} +11 -10
- package/es/node-pool/index.mjs.map +1 -0
- package/es/{node.js → node.mjs} +9 -8
- package/es/node.mjs.map +1 -0
- package/es/tx/builder/field-types.mjs +74 -0
- package/es/tx/builder/field-types.mjs.map +1 -0
- package/es/tx/builder/{helpers.js → helpers.mjs} +114 -56
- package/es/tx/builder/helpers.mjs.map +1 -0
- package/es/tx/builder/{index.js → index.mjs} +79 -68
- package/es/tx/builder/index.mjs.map +1 -0
- package/es/tx/builder/{schema.js → schema.mjs} +11 -65
- package/es/tx/builder/schema.mjs.map +1 -0
- package/es/tx/{index.js → index.mjs} +5 -2
- package/es/tx/index.mjs.map +1 -0
- package/es/tx/{tx-object.js → tx-object.mjs} +22 -15
- package/es/tx/tx-object.mjs.map +1 -0
- package/es/tx/{tx.js → tx.mjs} +15 -14
- package/es/tx/tx.mjs.map +1 -0
- package/es/tx/{validator.js → validator.mjs} +72 -33
- package/es/tx/validator.mjs.map +1 -0
- package/es/typings/blakejs/index.d.mjs +2 -0
- package/es/typings/blakejs/{index.d.js.map → index.d.mjs.map} +1 -1
- package/es/utils/aepp-wallet-communication/connection/{browser-runtime.js → browser-runtime.mjs} +7 -6
- package/es/utils/aepp-wallet-communication/connection/browser-runtime.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/connection/{browser-window-message.js → browser-window-message.mjs} +10 -11
- package/es/utils/aepp-wallet-communication/connection/browser-window-message.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/connection/{index.js → index.mjs} +5 -2
- package/es/utils/aepp-wallet-communication/connection/index.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/{content-script-bridge.js → content-script-bridge.mjs} +6 -5
- package/es/utils/aepp-wallet-communication/content-script-bridge.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/{helpers.js → helpers.mjs} +3 -14
- package/es/utils/aepp-wallet-communication/helpers.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/rpc/{aepp-rpc.js → aepp-rpc.mjs} +113 -67
- package/es/utils/aepp-wallet-communication/rpc/aepp-rpc.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/rpc/{rpc-client.js → rpc-client.mjs} +14 -9
- package/es/utils/aepp-wallet-communication/rpc/rpc-client.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/rpc/{wallet-rpc.js → wallet-rpc.mjs} +71 -63
- package/es/utils/aepp-wallet-communication/rpc/wallet-rpc.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/schema.mjs +102 -0
- package/es/utils/aepp-wallet-communication/schema.mjs.map +1 -0
- package/es/utils/aepp-wallet-communication/{wallet-detector.js → wallet-detector.mjs} +6 -5
- package/es/utils/aepp-wallet-communication/wallet-detector.mjs.map +1 -0
- package/es/utils/{amount-formatter.js → amount-formatter.mjs} +14 -7
- package/es/utils/amount-formatter.mjs.map +1 -0
- package/es/utils/{async-init.js → async-init.mjs} +8 -11
- package/es/utils/async-init.mjs.map +1 -0
- package/es/utils/{bignumber.js → bignumber.mjs} +2 -9
- package/es/utils/bignumber.mjs.map +1 -0
- package/es/utils/{bytes.js → bytes.mjs} +16 -8
- package/es/utils/bytes.mjs.map +1 -0
- package/es/utils/{crypto-ts.js → crypto-ts.mjs} +11 -3
- package/es/utils/crypto-ts.mjs.map +1 -0
- package/es/utils/{crypto.js → crypto.mjs} +40 -105
- package/es/utils/crypto.mjs.map +1 -0
- package/es/utils/errors.mjs +689 -0
- package/es/utils/errors.mjs.map +1 -0
- package/es/utils/{hd-wallet.js → hd-wallet.mjs} +33 -34
- package/es/utils/hd-wallet.mjs.map +1 -0
- package/es/utils/{json-big.js → json-big.mjs} +1 -1
- package/es/utils/{json-big.js.map → json-big.mjs.map} +1 -1
- package/es/utils/{keystore.js → keystore.mjs} +63 -51
- package/es/utils/keystore.mjs.map +1 -0
- package/es/utils/{mptree.js → mptree.mjs} +21 -12
- package/es/utils/mptree.mjs.map +1 -0
- package/es/utils/{other.js → other.mjs} +2 -2
- package/es/utils/other.mjs.map +1 -0
- package/es/utils/{semver-satisfies.js → semver-satisfies.mjs} +1 -1
- package/es/utils/{semver-satisfies.js.map → semver-satisfies.mjs.map} +1 -1
- package/es/utils/{string.js → string.mjs} +1 -1
- package/es/utils/{string.js.map → string.mjs.map} +1 -1
- package/es/utils/{swagger.js → swagger.mjs} +46 -14
- package/es/utils/swagger.mjs.map +1 -0
- package/package.json +46 -55
- package/src/account/memory.js +13 -8
- package/src/account/multiple.js +12 -4
- package/src/ae/aens.js +12 -17
- package/src/ae/aepp.js +2 -2
- package/src/ae/contract.js +15 -152
- package/src/ae/index.js +2 -1
- package/src/ae/oracle.js +25 -10
- package/src/ae/universal.js +2 -2
- package/src/ae/wallet.js +2 -2
- package/src/chain/index.js +21 -2
- package/src/chain/node.js +80 -53
- package/src/channel/handlers.js +20 -17
- package/src/channel/internal.js +30 -24
- package/src/contract/{aci/index.js → aci.js} +152 -93
- package/src/contract/compiler.js +22 -117
- package/src/contract/ga/helpers.js +7 -5
- package/src/contract/ga/index.js +27 -24
- package/src/index.js +7 -8
- package/src/node-pool/index.js +9 -8
- package/src/node.js +5 -7
- package/src/tx/builder/field-types.js +61 -0
- package/src/tx/builder/helpers.js +113 -58
- package/src/tx/builder/index.js +39 -34
- package/src/tx/builder/schema.js +11 -25
- package/src/tx/tx-object.js +10 -9
- package/src/tx/tx.js +17 -8
- package/src/tx/validator.js +25 -5
- package/src/utils/aepp-wallet-communication/connection/browser-runtime.js +8 -3
- package/src/utils/aepp-wallet-communication/connection/browser-window-message.js +10 -6
- package/src/utils/aepp-wallet-communication/content-script-bridge.js +5 -4
- package/src/utils/aepp-wallet-communication/helpers.js +2 -12
- package/src/utils/aepp-wallet-communication/rpc/aepp-rpc.js +81 -55
- package/src/utils/aepp-wallet-communication/rpc/rpc-client.js +15 -6
- package/src/utils/aepp-wallet-communication/rpc/wallet-rpc.js +60 -49
- package/src/utils/aepp-wallet-communication/schema.ts +80 -0
- package/src/utils/aepp-wallet-communication/wallet-detector.js +3 -2
- package/src/utils/amount-formatter.ts +4 -3
- package/src/utils/async-init.js +10 -6
- package/src/utils/bignumber.ts +1 -9
- package/src/utils/bytes.ts +3 -2
- package/src/utils/crypto-ts.ts +2 -2
- package/src/utils/crypto.js +9 -92
- package/src/utils/errors.ts +683 -0
- package/src/utils/hd-wallet.js +11 -26
- package/src/utils/keystore.js +47 -51
- package/src/utils/mptree.ts +12 -6
- package/src/utils/swagger.js +67 -44
- package/CHANGELOG.md +0 -1603
- package/es/account/base.js.map +0 -1
- package/es/account/memory.js.map +0 -1
- package/es/account/multiple.js.map +0 -1
- package/es/ae/aens.js.map +0 -1
- package/es/ae/aepp.js.map +0 -1
- package/es/ae/contract.js +0 -312
- package/es/ae/contract.js.map +0 -1
- package/es/ae/index.js.map +0 -1
- package/es/ae/oracle.js.map +0 -1
- package/es/ae/universal.js.map +0 -1
- package/es/ae/wallet.js.map +0 -1
- package/es/chain/index.js.map +0 -1
- package/es/chain/node.js.map +0 -1
- package/es/channel/handlers.js.map +0 -1
- package/es/channel/index.js.map +0 -1
- package/es/channel/internal.js.map +0 -1
- package/es/contract/aci/helpers.js +0 -298
- package/es/contract/aci/helpers.js.map +0 -1
- package/es/contract/aci/index.js +0 -361
- package/es/contract/aci/index.js.map +0 -1
- package/es/contract/aci/transformation.js +0 -66
- package/es/contract/aci/transformation.js.map +0 -1
- package/es/contract/compiler.js +0 -244
- package/es/contract/compiler.js.map +0 -1
- package/es/contract/ga/helpers.js +0 -22
- package/es/contract/ga/helpers.js.map +0 -1
- package/es/contract/ga/index.js.map +0 -1
- package/es/contract/index.js +0 -162
- package/es/contract/index.js.map +0 -1
- package/es/index.js +0 -57
- package/es/index.js.map +0 -1
- package/es/node-pool/index.js.map +0 -1
- package/es/node.js.map +0 -1
- package/es/tx/builder/helpers.js.map +0 -1
- package/es/tx/builder/index.js.map +0 -1
- package/es/tx/builder/schema.js.map +0 -1
- package/es/tx/index.js.map +0 -1
- package/es/tx/tx-object.js.map +0 -1
- package/es/tx/tx.js.map +0 -1
- package/es/tx/validator.js.map +0 -1
- package/es/typings/blakejs/index.d.js +0 -2
- package/es/utils/aepp-wallet-communication/connection/browser-runtime.js.map +0 -1
- package/es/utils/aepp-wallet-communication/connection/browser-window-message.js.map +0 -1
- package/es/utils/aepp-wallet-communication/connection/index.js.map +0 -1
- package/es/utils/aepp-wallet-communication/content-script-bridge.js.map +0 -1
- package/es/utils/aepp-wallet-communication/helpers.js.map +0 -1
- package/es/utils/aepp-wallet-communication/rpc/aepp-rpc.js.map +0 -1
- package/es/utils/aepp-wallet-communication/rpc/rpc-client.js.map +0 -1
- package/es/utils/aepp-wallet-communication/rpc/wallet-rpc.js.map +0 -1
- package/es/utils/aepp-wallet-communication/schema.js +0 -107
- package/es/utils/aepp-wallet-communication/schema.js.map +0 -1
- package/es/utils/aepp-wallet-communication/wallet-detector.js.map +0 -1
- package/es/utils/amount-formatter.js.map +0 -1
- package/es/utils/async-init.js.map +0 -1
- package/es/utils/bignumber.js.map +0 -1
- package/es/utils/bytes.js.map +0 -1
- package/es/utils/crypto-ts.js.map +0 -1
- package/es/utils/crypto.js.map +0 -1
- package/es/utils/hd-wallet.js.map +0 -1
- package/es/utils/keystore.js.map +0 -1
- package/es/utils/mptree.js.map +0 -1
- package/es/utils/other.js.map +0 -1
- package/es/utils/swagger.js.map +0 -1
- package/src/contract/aci/transformation.js +0 -72
- package/src/contract/index.js +0 -163
- package/src/utils/aepp-wallet-communication/schema.js +0 -108
package/src/channel/handlers.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import { generateKeyPair, encodeContractAddress
|
|
18
|
+
import { generateKeyPair, encodeContractAddress } from '../utils/crypto'
|
|
19
19
|
import {
|
|
20
20
|
options,
|
|
21
21
|
changeStatus,
|
|
@@ -28,20 +28,23 @@ import {
|
|
|
28
28
|
fsmId
|
|
29
29
|
} from './internal'
|
|
30
30
|
import { unpackTx, buildTx } from '../tx/builder'
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
import { encode } from '../tx/builder/helpers'
|
|
32
|
+
import {
|
|
33
|
+
IllegalArgumentError,
|
|
34
|
+
InsufficientBalanceError,
|
|
35
|
+
ChannelConnectionError,
|
|
36
|
+
UnexpectedChannelMessageError
|
|
37
|
+
} from '../utils/errors'
|
|
35
38
|
|
|
36
39
|
async function appendSignature (tx, signFn) {
|
|
37
40
|
const { signatures, encodedTx } = unpackTx(tx).tx
|
|
38
|
-
const result = await signFn(
|
|
41
|
+
const result = await signFn(encode(encodedTx.rlpEncoded, 'tx'))
|
|
39
42
|
if (typeof result === 'string') {
|
|
40
43
|
const { tx: signedTx, txType } = unpackTx(result)
|
|
41
|
-
return
|
|
44
|
+
return buildTx({
|
|
42
45
|
signatures: signatures.concat(signedTx.signatures),
|
|
43
46
|
encodedTx: signedTx.encodedTx.rlpEncoded
|
|
44
|
-
}, txType).
|
|
47
|
+
}, txType).tx
|
|
45
48
|
}
|
|
46
49
|
return result
|
|
47
50
|
}
|
|
@@ -49,7 +52,7 @@ async function appendSignature (tx, signFn) {
|
|
|
49
52
|
function handleUnexpectedMessage (channel, message, state) {
|
|
50
53
|
if (state && state.reject) {
|
|
51
54
|
state.reject(Object.assign(
|
|
52
|
-
new
|
|
55
|
+
new UnexpectedChannelMessageError(`Unexpected message received:\n\n${JSON.stringify(message)}`),
|
|
53
56
|
{ wsMessage: message }
|
|
54
57
|
))
|
|
55
58
|
}
|
|
@@ -75,7 +78,7 @@ export function awaitingConnection (channel, message, state) {
|
|
|
75
78
|
return { handler: awaitingConnection }
|
|
76
79
|
}
|
|
77
80
|
if (message.method === 'channels.error') {
|
|
78
|
-
emit(channel, 'error', new
|
|
81
|
+
emit(channel, 'error', new ChannelConnectionError(message.payload.message))
|
|
79
82
|
return { handler: channelClosed }
|
|
80
83
|
}
|
|
81
84
|
}
|
|
@@ -251,17 +254,17 @@ export async function awaitingOffChainTx (channel, message, state) {
|
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
if (message.method === 'channels.error') {
|
|
254
|
-
state.reject(new
|
|
257
|
+
state.reject(new ChannelConnectionError(message.data.message))
|
|
255
258
|
return { handler: channelOpen }
|
|
256
259
|
}
|
|
257
260
|
if (message.error) {
|
|
258
261
|
const { data = [] } = message.error
|
|
259
262
|
if (data.find(i => i.code === 1001)) {
|
|
260
|
-
state.reject(new
|
|
263
|
+
state.reject(new InsufficientBalanceError('Insufficient balance'))
|
|
261
264
|
} else if (data.find(i => i.code === 1002)) {
|
|
262
|
-
state.reject(new
|
|
265
|
+
state.reject(new IllegalArgumentError('Amount cannot be negative'))
|
|
263
266
|
} else {
|
|
264
|
-
state.reject(new
|
|
267
|
+
state.reject(new ChannelConnectionError(message.error.message))
|
|
265
268
|
}
|
|
266
269
|
return { handler: channelOpen }
|
|
267
270
|
}
|
|
@@ -303,7 +306,7 @@ export function awaitingOffChainUpdate (channel, message, state) {
|
|
|
303
306
|
}
|
|
304
307
|
}
|
|
305
308
|
if (message.error) {
|
|
306
|
-
state.reject(new
|
|
309
|
+
state.reject(new ChannelConnectionError(message.error.message))
|
|
307
310
|
return { handler: channelOpen }
|
|
308
311
|
}
|
|
309
312
|
return handleUnexpectedMessage(channel, message, state)
|
|
@@ -387,7 +390,7 @@ export function awaitingLeave (channel, message, state) {
|
|
|
387
390
|
return { handler: channelClosed }
|
|
388
391
|
}
|
|
389
392
|
if (message.method === 'channels.error') {
|
|
390
|
-
state.reject(new
|
|
393
|
+
state.reject(new ChannelConnectionError(message.data.message))
|
|
391
394
|
return { handler: channelOpen }
|
|
392
395
|
}
|
|
393
396
|
return handleUnexpectedMessage(channel, message, state)
|
|
@@ -651,7 +654,7 @@ export function awaitingCallsPruned (channels, message, state) {
|
|
|
651
654
|
state.resolve()
|
|
652
655
|
return { handler: channelOpen }
|
|
653
656
|
}
|
|
654
|
-
state.reject(new
|
|
657
|
+
state.reject(new UnexpectedChannelMessageError('Unexpected message received'))
|
|
655
658
|
return { handler: channelClosed }
|
|
656
659
|
}
|
|
657
660
|
|
package/src/channel/internal.js
CHANGED
|
@@ -20,6 +20,7 @@ import { EventEmitter } from 'events'
|
|
|
20
20
|
import JsonBig from '../utils/json-big'
|
|
21
21
|
import { pascalToSnake } from '../utils/string'
|
|
22
22
|
import { awaitingConnection, awaitingReconnection, channelOpen } from './handlers'
|
|
23
|
+
import { ChannelCallError, ChannelPingTimedOutError, UnknownChannelStateError } from '../utils/errors'
|
|
23
24
|
|
|
24
25
|
// Send ping message every 10 seconds
|
|
25
26
|
const PING_TIMEOUT_MS = 10000
|
|
@@ -49,7 +50,7 @@ export function emit (channel, ...args) {
|
|
|
49
50
|
|
|
50
51
|
function enterState (channel, nextState) {
|
|
51
52
|
if (!nextState) {
|
|
52
|
-
throw new
|
|
53
|
+
throw new UnknownChannelStateError()
|
|
53
54
|
}
|
|
54
55
|
fsm.set(channel, nextState)
|
|
55
56
|
if (nextState.handler.enter) {
|
|
@@ -109,16 +110,21 @@ async function handleMessage (channel, message) {
|
|
|
109
110
|
}
|
|
110
111
|
|
|
111
112
|
async function dequeueMessage (channel) {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
const [message, ...remaining] = queue
|
|
117
|
-
messageQueue.set(channel, remaining || [])
|
|
113
|
+
if (messageQueueLocked.get(channel)) return
|
|
114
|
+
const messages = messageQueue.get(channel)
|
|
115
|
+
if (!messages.length) return
|
|
118
116
|
messageQueueLocked.set(channel, true)
|
|
119
|
-
|
|
117
|
+
while (messages.length) {
|
|
118
|
+
const message = messages.shift()
|
|
119
|
+
try {
|
|
120
|
+
await handleMessage(channel, message)
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error('Error handling incoming message:')
|
|
123
|
+
console.error(message)
|
|
124
|
+
console.error(error)
|
|
125
|
+
}
|
|
126
|
+
}
|
|
120
127
|
messageQueueLocked.set(channel, false)
|
|
121
|
-
dequeueMessage(channel)
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
function ping (channel) {
|
|
@@ -134,7 +140,7 @@ function ping (channel) {
|
|
|
134
140
|
})
|
|
135
141
|
pongTimeoutId.set(channel, setTimeout(() => {
|
|
136
142
|
disconnect(channel)
|
|
137
|
-
emit(channel, 'error', new
|
|
143
|
+
emit(channel, 'error', new ChannelPingTimedOutError())
|
|
138
144
|
}, PONG_TIMEOUT_MS))
|
|
139
145
|
}, PING_TIMEOUT_MS))
|
|
140
146
|
}
|
|
@@ -150,9 +156,13 @@ function onMessage (channel, data) {
|
|
|
150
156
|
} finally {
|
|
151
157
|
rpcCallbacks.get(channel).delete(message.id)
|
|
152
158
|
}
|
|
153
|
-
|
|
159
|
+
return
|
|
160
|
+
}
|
|
161
|
+
if (message.method === 'channels.message') {
|
|
154
162
|
emit(channel, 'message', message.params.data.message)
|
|
155
|
-
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
if (message.method === 'channels.system.pong') {
|
|
156
166
|
if (
|
|
157
167
|
(message.params.channel_id === channelId.get(channel)) ||
|
|
158
168
|
// Skip channelId check if channelId is not known yet
|
|
@@ -160,18 +170,10 @@ function onMessage (channel, data) {
|
|
|
160
170
|
) {
|
|
161
171
|
ping(channel)
|
|
162
172
|
}
|
|
163
|
-
|
|
164
|
-
messageQueue.set(channel, [...(messageQueue.get(channel) || []), message])
|
|
165
|
-
dequeueMessage(channel)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function wrapCallErrorMessage (message) {
|
|
170
|
-
const [{ message: details } = {}] = message.error.data || []
|
|
171
|
-
if (details) {
|
|
172
|
-
return new Error(`${message.error.message}: ${details}`)
|
|
173
|
+
return
|
|
173
174
|
}
|
|
174
|
-
|
|
175
|
+
messageQueue.get(channel).push(message)
|
|
176
|
+
dequeueMessage(channel)
|
|
175
177
|
}
|
|
176
178
|
|
|
177
179
|
export function call (channel, method, params) {
|
|
@@ -179,7 +181,10 @@ export function call (channel, method, params) {
|
|
|
179
181
|
const id = sequence.set(channel, sequence.get(channel) + 1).get(channel)
|
|
180
182
|
rpcCallbacks.get(channel).set(id, (message) => {
|
|
181
183
|
if (message.result) return resolve(message.result)
|
|
182
|
-
if (message.error)
|
|
184
|
+
if (message.error) {
|
|
185
|
+
const [{ message: details } = {}] = message.error.data || []
|
|
186
|
+
return reject(new ChannelCallError(message.error.message + (details ? `: ${details}` : '')))
|
|
187
|
+
}
|
|
183
188
|
})
|
|
184
189
|
send(channel, { jsonrpc: '2.0', method, id, params })
|
|
185
190
|
})
|
|
@@ -199,6 +204,7 @@ export async function initialize (channel, { url, ...channelOptions }) {
|
|
|
199
204
|
eventEmitters.set(channel, new EventEmitter())
|
|
200
205
|
sequence.set(channel, 0)
|
|
201
206
|
rpcCallbacks.set(channel, new Map())
|
|
207
|
+
messageQueue.set(channel, [])
|
|
202
208
|
|
|
203
209
|
const wsUrl = new URL(url)
|
|
204
210
|
Object.entries(channelOptions)
|
|
@@ -22,38 +22,28 @@
|
|
|
22
22
|
* @export getContractInstance
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
import * as R from 'ramda'
|
|
26
|
-
import BigNumber from 'bignumber.js'
|
|
27
25
|
import { Encoder as Calldata } from '@aeternity/aepp-calldata'
|
|
28
|
-
import {
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
}
|
|
26
|
+
import { DRY_RUN_ACCOUNT, GAS_MAX } from '../tx/builder/schema'
|
|
27
|
+
import TxObject from '../tx/tx-object'
|
|
28
|
+
import { decode } from '../tx/builder/helpers'
|
|
29
|
+
import {
|
|
30
|
+
MissingContractDefError,
|
|
31
|
+
MissingContractAddressError,
|
|
32
|
+
InactiveContractError,
|
|
33
|
+
BytecodeMismatchError,
|
|
34
|
+
InternalError,
|
|
35
|
+
DuplicateContractError,
|
|
36
|
+
MissingFunctionNameError,
|
|
37
|
+
InvalidMethodInvocationError,
|
|
38
|
+
NotPayableFunctionError,
|
|
39
|
+
TypeError,
|
|
40
|
+
NodeInvocationError,
|
|
41
|
+
IllegalArgumentError,
|
|
42
|
+
NoSuchContractFunctionError,
|
|
43
|
+
MissingEventDefinitionError,
|
|
44
|
+
AmbiguousEventDefinitionError
|
|
45
|
+
} from '../utils/errors'
|
|
46
|
+
import { hash } from '../utils/crypto-ts'
|
|
57
47
|
|
|
58
48
|
/**
|
|
59
49
|
* Generate contract ACI object with predefined js methods for contract usage - can be used for
|
|
@@ -68,7 +58,7 @@ function getFunctionACI (aci, name, external) {
|
|
|
68
58
|
* @param {Boolean} [options.validateBytecode] Compare source code with on-chain version
|
|
69
59
|
* @return {ContractInstance} JS Contract API
|
|
70
60
|
* @example
|
|
71
|
-
* const contractIns = await
|
|
61
|
+
* const contractIns = await aeSdk.getContractInstance({ source })
|
|
72
62
|
* await contractIns.deploy([321]) or await contractIns.methods.init(321)
|
|
73
63
|
* const callResult = await contractIns.call('setState', [123]) or
|
|
74
64
|
* await contractIns.methods.setState.send(123, options)
|
|
@@ -81,30 +71,32 @@ function getFunctionACI (aci, name, external) {
|
|
|
81
71
|
export default async function getContractInstance ({
|
|
82
72
|
source,
|
|
83
73
|
bytecode,
|
|
84
|
-
aci,
|
|
74
|
+
aci: _aci,
|
|
85
75
|
contractAddress,
|
|
86
76
|
filesystem = {},
|
|
87
77
|
validateBytecode,
|
|
88
78
|
...otherOptions
|
|
89
79
|
} = {}) {
|
|
90
|
-
|
|
91
|
-
|
|
80
|
+
if (!_aci && source) {
|
|
81
|
+
_aci = await this.compilerApi.generateACI({ code: source, options: { filesystem } })
|
|
82
|
+
}
|
|
83
|
+
if (!_aci) throw new MissingContractDefError()
|
|
92
84
|
contractAddress = contractAddress && await this.resolveName(
|
|
93
85
|
contractAddress, 'contract_pubkey', { resolveByNode: true }
|
|
94
86
|
)
|
|
95
|
-
if (!contractAddress && !source && !bytecode)
|
|
87
|
+
if (!contractAddress && !source && !bytecode) {
|
|
88
|
+
throw new MissingContractAddressError('Can\'t create instance by ACI without address')
|
|
89
|
+
}
|
|
96
90
|
|
|
97
91
|
if (contractAddress) {
|
|
98
|
-
const contract = await this.getContract(contractAddress)
|
|
99
|
-
if (!contract) throw new
|
|
100
|
-
if (!contract.active) throw new Error(`Contract with address ${contractAddress} not active`)
|
|
92
|
+
const contract = await this.getContract(contractAddress)
|
|
93
|
+
if (!contract.active) throw new InactiveContractError(contractAddress)
|
|
101
94
|
}
|
|
102
95
|
|
|
103
96
|
const instance = {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
calldata: new Calldata([
|
|
107
|
-
externalAci: (aci.external_encoded_aci ?? []).map(a => a.contract || a.namespace),
|
|
97
|
+
_aci,
|
|
98
|
+
_name: _aci.encoded_aci.contract.name,
|
|
99
|
+
calldata: new Calldata([_aci.encoded_aci, ..._aci.external_encoded_aci]),
|
|
108
100
|
source,
|
|
109
101
|
bytecode,
|
|
110
102
|
deployInfo: { address: contractAddress },
|
|
@@ -118,12 +110,14 @@ export default async function getContractInstance ({
|
|
|
118
110
|
}
|
|
119
111
|
|
|
120
112
|
if (validateBytecode) {
|
|
121
|
-
if (!contractAddress) throw new
|
|
113
|
+
if (!contractAddress) throw new MissingContractAddressError('Can\'t validate bytecode without contract address')
|
|
122
114
|
const onChanBytecode = (await this.getContractByteCode(contractAddress)).bytecode
|
|
123
|
-
const isValid =
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
115
|
+
const isValid = source
|
|
116
|
+
? await this.compilerApi.validateByteCode(
|
|
117
|
+
{ bytecode: onChanBytecode, source, options: instance.options }
|
|
118
|
+
).then((res) => Object.entries(res).length === 0, () => false)
|
|
119
|
+
: bytecode === onChanBytecode
|
|
120
|
+
if (!isValid) throw new BytecodeMismatchError(source ? 'source' : 'bytecode')
|
|
127
121
|
}
|
|
128
122
|
|
|
129
123
|
/**
|
|
@@ -133,11 +127,11 @@ export default async function getContractInstance ({
|
|
|
133
127
|
* @return {String} bytecode bytecode
|
|
134
128
|
*/
|
|
135
129
|
instance.compile = async (options = {}) => {
|
|
136
|
-
if (instance.bytecode) throw new
|
|
137
|
-
if (!instance.source) throw new
|
|
138
|
-
const { bytecode } = await this.
|
|
139
|
-
instance.source, { ...instance.options, ...options }
|
|
140
|
-
)
|
|
130
|
+
if (instance.bytecode) throw new IllegalArgumentError('Contract already compiled')
|
|
131
|
+
if (!instance.source) throw new IllegalArgumentError('Can\'t compile without source code')
|
|
132
|
+
const { bytecode } = await this.compilerApi.compileContract({
|
|
133
|
+
code: instance.source, options: { ...instance.options, ...options }
|
|
134
|
+
})
|
|
141
135
|
instance.bytecode = bytecode
|
|
142
136
|
return instance.bytecode
|
|
143
137
|
}
|
|
@@ -148,9 +142,10 @@ export default async function getContractInstance ({
|
|
|
148
142
|
hash: txData.hash, tx: TxObject({ tx: txData.rawTx }), txData, rawTx: txData.rawTx
|
|
149
143
|
}
|
|
150
144
|
if (options.waitMined === false) return result
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
145
|
+
const { callInfo } = await this.api.getTransactionInfoByHash(txData.hash)
|
|
146
|
+
Object.assign(result.txData, callInfo) // TODO: don't duplicate data in result
|
|
147
|
+
await handleCallError(callInfo)
|
|
148
|
+
return { ...result, result: callInfo }
|
|
154
149
|
}
|
|
155
150
|
|
|
156
151
|
const handleCallError = ({ returnType, returnValue }) => {
|
|
@@ -164,9 +159,16 @@ export default async function getContractInstance ({
|
|
|
164
159
|
case 'error':
|
|
165
160
|
message = decode(returnValue).toString()
|
|
166
161
|
break
|
|
167
|
-
default: throw new
|
|
162
|
+
default: throw new InternalError(`Unknown returnType: ${returnType}`)
|
|
168
163
|
}
|
|
169
|
-
throw new
|
|
164
|
+
throw new NodeInvocationError(message)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
instance._estimateGas = async (name, params, options) => {
|
|
168
|
+
const { result: { gasUsed } } =
|
|
169
|
+
await instance.call(name, params, { ...options, callStatic: true })
|
|
170
|
+
// taken from https://github.com/aeternity/aepp-sdk-js/issues/1286#issuecomment-977814771
|
|
171
|
+
return Math.floor(gasUsed * 1.25)
|
|
170
172
|
}
|
|
171
173
|
|
|
172
174
|
/**
|
|
@@ -178,15 +180,16 @@ export default async function getContractInstance ({
|
|
|
178
180
|
* @return {Object} deploy info
|
|
179
181
|
*/
|
|
180
182
|
instance.deploy = async (params = [], options) => {
|
|
181
|
-
const opt = { ...instance.options, ...options
|
|
183
|
+
const opt = { ...instance.options, ...options }
|
|
182
184
|
if (!instance.bytecode) await instance.compile(opt)
|
|
183
185
|
if (opt.callStatic) return instance.call('init', params, opt)
|
|
184
|
-
if (instance.deployInfo.address) throw new
|
|
186
|
+
if (instance.deployInfo.address) throw new DuplicateContractError()
|
|
185
187
|
|
|
186
188
|
const ownerId = await this.address(opt)
|
|
187
189
|
const { tx, contractId } = await this.contractCreateTx({
|
|
188
190
|
...opt,
|
|
189
|
-
|
|
191
|
+
gas: opt.gas ?? await instance._estimateGas('init', params, opt),
|
|
192
|
+
callData: instance.calldata.encode(instance._name, 'init', params),
|
|
190
193
|
code: instance.bytecode,
|
|
191
194
|
ownerId
|
|
192
195
|
})
|
|
@@ -197,16 +200,23 @@ export default async function getContractInstance ({
|
|
|
197
200
|
transaction: hash,
|
|
198
201
|
rawTx,
|
|
199
202
|
txData,
|
|
200
|
-
address: contractId
|
|
201
|
-
call: (name, args, options) =>
|
|
202
|
-
this.contractCall(instance.source, contractId, name, args, { ...opt, ...options }),
|
|
203
|
-
callStatic: (name, args, options) =>
|
|
204
|
-
this.contractCallStatic(instance.source, contractId, name, args, { ...opt, ...options }),
|
|
205
|
-
createdAt: new Date()
|
|
203
|
+
address: contractId
|
|
206
204
|
})
|
|
207
205
|
return instance.deployInfo
|
|
208
206
|
}
|
|
209
207
|
|
|
208
|
+
/**
|
|
209
|
+
* Get function schema from contract ACI object
|
|
210
|
+
* @param {String} name Function name
|
|
211
|
+
* @return {Object} function ACI
|
|
212
|
+
*/
|
|
213
|
+
function getFunctionACI (name) {
|
|
214
|
+
const fn = instance._aci.encoded_aci.contract.functions.find(f => f.name === name)
|
|
215
|
+
if (fn) return fn
|
|
216
|
+
if (name === 'init') return { payable: false }
|
|
217
|
+
throw new NoSuchContractFunctionError(`Function ${name} doesn't exist in contract`)
|
|
218
|
+
}
|
|
219
|
+
|
|
210
220
|
/**
|
|
211
221
|
* Call contract function
|
|
212
222
|
* @alias module:@aeternity/aepp-sdk/es/contract/aci
|
|
@@ -219,22 +229,19 @@ export default async function getContractInstance ({
|
|
|
219
229
|
*/
|
|
220
230
|
instance.call = async (fn, params = [], options = {}) => {
|
|
221
231
|
const opt = { ...instance.options, ...options }
|
|
222
|
-
const fnACI = getFunctionACI(
|
|
232
|
+
const fnACI = getFunctionACI(fn)
|
|
223
233
|
const contractId = instance.deployInfo.address
|
|
224
234
|
|
|
225
|
-
if (!fn) throw new
|
|
226
|
-
if (fn === 'init' && !opt.callStatic) throw new
|
|
227
|
-
if (!contractId && fn !== 'init') throw new
|
|
228
|
-
if (
|
|
229
|
-
BigNumber(opt.amount).gt(0) &&
|
|
230
|
-
(Object.prototype.hasOwnProperty.call(fnACI, 'payable') && !fnACI.payable)
|
|
231
|
-
) throw new Error(`You try to pay "${opt.amount}" to function "${fn}" which is not payable. Only payable function can accept tokens`)
|
|
235
|
+
if (!fn) throw new MissingFunctionNameError()
|
|
236
|
+
if (fn === 'init' && !opt.callStatic) throw new InvalidMethodInvocationError('"init" can be called only via dryRun')
|
|
237
|
+
if (!contractId && fn !== 'init') throw new InvalidMethodInvocationError('You need to deploy contract before calling!')
|
|
238
|
+
if (opt.amount > 0 && fnACI.payable === false) throw new NotPayableFunctionError(`You try to pay "${opt.amount}" to function "${fn}" which is not payable. Only payable function can accept coins`)
|
|
232
239
|
|
|
233
240
|
const callerId = await this.address(opt).catch(error => {
|
|
234
241
|
if (opt.callStatic) return DRY_RUN_ACCOUNT.pub
|
|
235
242
|
else throw error
|
|
236
243
|
})
|
|
237
|
-
const callData = instance.calldata.encode(instance.
|
|
244
|
+
const callData = instance.calldata.encode(instance._name, fn, params)
|
|
238
245
|
|
|
239
246
|
let res
|
|
240
247
|
if (opt.callStatic) {
|
|
@@ -243,8 +250,10 @@ export default async function getContractInstance ({
|
|
|
243
250
|
}
|
|
244
251
|
const txOpt = {
|
|
245
252
|
...opt,
|
|
253
|
+
gas: opt.gas ?? GAS_MAX,
|
|
246
254
|
callData,
|
|
247
|
-
nonce: opt.
|
|
255
|
+
nonce: opt.nonce ??
|
|
256
|
+
(opt.top && (await this.getAccount(callerId, { hash: opt.top })).nonce + 1)
|
|
248
257
|
}
|
|
249
258
|
const tx = fn === 'init'
|
|
250
259
|
? (await this.contractCreateTx({ ...txOpt, code: instance.bytecode, ownerId: callerId })).tx
|
|
@@ -254,33 +263,84 @@ export default async function getContractInstance ({
|
|
|
254
263
|
await handleCallError(callObj)
|
|
255
264
|
res = { ...dryRunOther, tx: TxObject({ tx }), result: callObj }
|
|
256
265
|
} else {
|
|
257
|
-
const tx = await this.contractCallTx({
|
|
266
|
+
const tx = await this.contractCallTx({
|
|
267
|
+
...opt,
|
|
268
|
+
gas: opt.gas ?? await instance._estimateGas(fn, params, opt),
|
|
269
|
+
callerId,
|
|
270
|
+
contractId,
|
|
271
|
+
callData
|
|
272
|
+
})
|
|
258
273
|
res = await sendAndProcess(tx, opt)
|
|
259
274
|
}
|
|
260
275
|
if (opt.waitMined || opt.callStatic) {
|
|
261
276
|
res.decodedResult = fnACI.returns && fnACI.returns !== 'unit' && fn !== 'init' &&
|
|
262
|
-
instance.calldata.decode(instance.
|
|
263
|
-
res.decodedEvents = instance.decodeEvents(res.result.log)
|
|
277
|
+
instance.calldata.decode(instance._name, fn, res.result.returnValue)
|
|
278
|
+
res.decodedEvents = instance.decodeEvents(res.result.log, opt)
|
|
264
279
|
}
|
|
265
280
|
return res
|
|
266
281
|
}
|
|
267
282
|
|
|
283
|
+
/**
|
|
284
|
+
* @param {String} address Contract address that emitted event
|
|
285
|
+
* @param {BigInt} nameHash Hash of emitted event name
|
|
286
|
+
* @param {Object} [options]
|
|
287
|
+
* @param {Object} [options.contractAddressToName] Map of contract addresses to their names
|
|
288
|
+
* @return {String} Contract name
|
|
289
|
+
* @throws {MissingEventDefinitionError}
|
|
290
|
+
* @throws {AmbiguousEventDefinitionError}
|
|
291
|
+
*/
|
|
292
|
+
function getContractNameByEvent (address, nameHash, { contractAddressToName }) {
|
|
293
|
+
const addressToName = { ...instance.options.contractAddressToName, ...contractAddressToName }
|
|
294
|
+
if (addressToName[address]) return addressToName[address]
|
|
295
|
+
|
|
296
|
+
const matchedEvents = [
|
|
297
|
+
instance._aci.encoded_aci,
|
|
298
|
+
...instance._aci.external_encoded_aci
|
|
299
|
+
]
|
|
300
|
+
.filter(({ contract }) => contract?.event)
|
|
301
|
+
.map(({ contract }) => [contract.name, contract.event.variant])
|
|
302
|
+
.map(([name, events]) => events.map(event => [name, Object.keys(event)[0]]))
|
|
303
|
+
.flat()
|
|
304
|
+
.filter(([, eventName]) => BigInt('0x' + hash(eventName).toString('hex')) === nameHash)
|
|
305
|
+
switch (matchedEvents.length) {
|
|
306
|
+
case 0: throw new MissingEventDefinitionError(nameHash, address)
|
|
307
|
+
case 1: return matchedEvents[0][0]
|
|
308
|
+
default: throw new AmbiguousEventDefinitionError(address, matchedEvents)
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
268
312
|
/**
|
|
269
313
|
* Decode Events
|
|
270
314
|
* @alias module:@aeternity/aepp-sdk/es/contract/aci
|
|
271
315
|
* @rtype (events: Array) => DecodedEvents: Array
|
|
272
|
-
* @param {Array} events Array of encoded events(callRes.result.log)
|
|
316
|
+
* @param {Array} events Array of encoded events (callRes.result.log)
|
|
317
|
+
* @param {Object} [options]
|
|
318
|
+
* @param {Boolean} [options.omitUnknown] Omit events that can't be decoded in case ACI is not
|
|
319
|
+
* complete
|
|
273
320
|
* @return {Object} DecodedEvents
|
|
274
321
|
*/
|
|
275
|
-
instance.decodeEvents = (events) =>
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
322
|
+
instance.decodeEvents = (events, { omitUnknown, ...opt } = {}) => events
|
|
323
|
+
.map(event => {
|
|
324
|
+
const topics = event.topics.map(t => BigInt(t))
|
|
325
|
+
let contractName
|
|
326
|
+
try {
|
|
327
|
+
contractName = getContractNameByEvent(event.address, topics[0], opt)
|
|
328
|
+
} catch (error) {
|
|
329
|
+
if (omitUnknown && error instanceof MissingEventDefinitionError) return null
|
|
330
|
+
throw error
|
|
331
|
+
}
|
|
332
|
+
const decoded = instance.calldata.decodeEvent(contractName, event.data, topics)
|
|
333
|
+
const [name, args] = Object.entries(decoded)[0]
|
|
334
|
+
return {
|
|
335
|
+
name,
|
|
336
|
+
args,
|
|
337
|
+
contract: {
|
|
338
|
+
name: contractName,
|
|
339
|
+
address: event.address
|
|
340
|
+
}
|
|
341
|
+
}
|
|
280
342
|
})
|
|
281
|
-
|
|
282
|
-
return decodeEvents(events, eventsSchema)
|
|
283
|
-
}
|
|
343
|
+
.filter(e => e)
|
|
284
344
|
|
|
285
345
|
/**
|
|
286
346
|
* Generate proto function based on contract function using Contract ACI schema
|
|
@@ -291,11 +351,11 @@ export default async function getContractInstance ({
|
|
|
291
351
|
* `await contract.methods.testFunction.get()` -> use call-static(dry-run)
|
|
292
352
|
* `await contract.methods.testFunction.send()` -> send tx on-chain
|
|
293
353
|
*/
|
|
294
|
-
instance.methods = Object.fromEntries(instance.
|
|
354
|
+
instance.methods = Object.fromEntries(instance._aci.encoded_aci.contract.functions
|
|
295
355
|
.map(({ name, arguments: aciArgs, stateful }) => {
|
|
296
356
|
const genHandler = callStatic => (...args) => {
|
|
297
357
|
const options = args.length === aciArgs.length + 1 ? args.pop() : {}
|
|
298
|
-
if (typeof options !== 'object') throw new
|
|
358
|
+
if (typeof options !== 'object') throw new TypeError(`Options should be an object: ${options}`)
|
|
299
359
|
if (name === 'init') return instance.deploy(args, { callStatic, ...options })
|
|
300
360
|
return instance.call(name, args, { callStatic, ...options })
|
|
301
361
|
}
|
|
@@ -305,8 +365,7 @@ export default async function getContractInstance ({
|
|
|
305
365
|
genHandler(name === 'init' ? false : !stateful),
|
|
306
366
|
{
|
|
307
367
|
get: genHandler(true),
|
|
308
|
-
send: genHandler(false)
|
|
309
|
-
decodeEvents: events => instance.decodeEvents(events)
|
|
368
|
+
send: genHandler(false)
|
|
310
369
|
}
|
|
311
370
|
)
|
|
312
371
|
]
|