@aeternity/aepp-sdk 12.0.0 → 12.1.2
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/dist/aepp-sdk.browser-script.js +1 -1
- package/dist/aepp-sdk.browser-script.js.LICENSE.txt +0 -15
- package/dist/aepp-sdk.browser-script.js.map +1 -1
- package/dist/aepp-sdk.browser.js +2 -1
- package/dist/aepp-sdk.browser.js.LICENSE.txt +1 -0
- package/dist/aepp-sdk.browser.js.map +1 -1
- package/dist/aepp-sdk.js +20765 -1
- package/dist/aepp-sdk.js.map +1 -1
- package/es/AeSdk.d.ts +7 -7
- package/es/AeSdk.mjs.map +1 -1
- package/es/AeSdkAepp.d.ts +4 -3
- package/es/AeSdkAepp.mjs +2 -1
- package/es/AeSdkAepp.mjs.map +1 -1
- package/es/AeSdkBase.d.ts +22 -21
- package/es/AeSdkBase.mjs +25 -21
- package/es/AeSdkBase.mjs.map +1 -1
- package/es/AeSdkWallet.d.ts +4 -3
- package/es/AeSdkWallet.mjs +5 -1
- package/es/AeSdkWallet.mjs.map +1 -1
- package/es/Node.d.ts +7 -10
- package/es/Node.mjs +63 -57
- package/es/Node.mjs.map +1 -1
- package/es/account/Base.d.ts +7 -4
- package/es/account/Base.mjs +3 -3
- package/es/account/Base.mjs.map +1 -1
- package/es/account/Memory.d.ts +5 -4
- package/es/account/Memory.mjs +24 -2
- package/es/account/Memory.mjs.map +1 -1
- package/es/account/Rpc.d.ts +6 -6
- package/es/account/Rpc.mjs +3 -2
- package/es/account/Rpc.mjs.map +1 -1
- package/es/aens.d.ts +27 -14
- package/es/aens.mjs +27 -21
- package/es/aens.mjs.map +1 -1
- package/es/aepp-wallet-communication/connection/Browser.d.ts +2 -1
- package/es/aepp-wallet-communication/connection/Browser.mjs +5 -2
- package/es/aepp-wallet-communication/connection/Browser.mjs.map +1 -1
- package/es/aepp-wallet-communication/connection/BrowserRuntime.d.ts +1 -0
- package/es/aepp-wallet-communication/connection/BrowserRuntime.mjs +1 -0
- package/es/aepp-wallet-communication/connection/BrowserRuntime.mjs.map +1 -1
- package/es/aepp-wallet-communication/connection/BrowserWindowMessage.d.ts +1 -0
- package/es/aepp-wallet-communication/connection/BrowserWindowMessage.mjs +5 -1
- package/es/aepp-wallet-communication/connection/BrowserWindowMessage.mjs.map +1 -1
- package/es/aepp-wallet-communication/connection-proxy.d.ts +1 -0
- package/es/aepp-wallet-communication/connection-proxy.mjs +1 -0
- package/es/aepp-wallet-communication/connection-proxy.mjs.map +1 -1
- package/es/aepp-wallet-communication/rpc/RpcClient.d.ts +1 -0
- package/es/aepp-wallet-communication/rpc/RpcClient.mjs +5 -5
- package/es/aepp-wallet-communication/rpc/RpcClient.mjs.map +1 -1
- package/es/aepp-wallet-communication/rpc/types.d.ts +8 -8
- package/es/aepp-wallet-communication/rpc/types.mjs.map +1 -1
- package/es/aepp-wallet-communication/schema.d.ts +17 -2
- package/es/aepp-wallet-communication/schema.mjs +54 -17
- package/es/aepp-wallet-communication/schema.mjs.map +1 -1
- package/es/aepp-wallet-communication/wallet-detector.d.ts +2 -1
- package/es/aepp-wallet-communication/wallet-detector.mjs +2 -3
- package/es/aepp-wallet-communication/wallet-detector.mjs.map +1 -1
- package/es/apis/node/models/index.d.ts +6 -2
- package/es/apis/node/models/index.mjs.map +1 -1
- package/es/apis/node/models/mappers.mjs +4 -2
- package/es/apis/node/models/mappers.mjs.map +1 -1
- package/es/chain.d.ts +92 -64
- package/es/chain.mjs +190 -154
- package/es/chain.mjs.map +1 -1
- package/es/channel/handlers.d.ts +3 -3
- package/es/channel/handlers.mjs +42 -44
- package/es/channel/handlers.mjs.map +1 -1
- package/es/channel/index.d.ts +43 -52
- package/es/channel/index.mjs +46 -49
- package/es/channel/index.mjs.map +1 -1
- package/es/channel/internal.d.ts +16 -15
- package/es/channel/internal.mjs +67 -62
- package/es/channel/internal.mjs.map +1 -1
- package/es/contract/Compiler.d.ts +1 -0
- package/es/contract/Compiler.mjs +5 -4
- package/es/contract/Compiler.mjs.map +1 -1
- package/es/contract/aci.d.ts +17 -15
- package/es/contract/aci.mjs +58 -45
- package/es/contract/aci.mjs.map +1 -1
- package/es/contract/ga.d.ts +16 -15
- package/es/contract/ga.mjs +12 -7
- package/es/contract/ga.mjs.map +1 -1
- package/es/contract/methods.d.ts +9 -6
- package/es/contract/methods.mjs +9 -6
- package/es/contract/methods.mjs.map +1 -1
- package/es/deprecated/index.d.ts +143 -0
- package/es/deprecated/index.mjs +162 -0
- package/es/deprecated/index.mjs.map +1 -0
- package/es/deprecated/methods.d.ts +18 -0
- package/es/deprecated/methods.mjs +26 -0
- package/es/deprecated/methods.mjs.map +1 -0
- package/es/index.d.ts +4 -1
- package/es/index.mjs +4 -1
- package/es/index.mjs.map +1 -1
- package/es/oracle.d.ts +69 -62
- package/es/oracle.mjs +121 -103
- package/es/oracle.mjs.map +1 -1
- package/es/spend.d.ts +16 -15
- package/es/spend.mjs +19 -30
- package/es/spend.mjs.map +1 -1
- package/es/tx/builder/address.d.ts +25 -0
- package/es/tx/builder/address.mjs +45 -0
- package/es/tx/builder/address.mjs.map +1 -0
- package/es/tx/builder/constants.d.ts +55 -26
- package/es/tx/builder/constants.mjs +60 -38
- package/es/tx/builder/constants.mjs.map +1 -1
- package/es/tx/builder/field-types/coin-amount.d.ts +13 -0
- package/es/tx/builder/field-types/coin-amount.mjs +26 -0
- package/es/tx/builder/field-types/coin-amount.mjs.map +1 -0
- package/es/tx/builder/field-types/deposit.d.ts +15 -0
- package/es/tx/builder/field-types/deposit.mjs +19 -0
- package/es/tx/builder/field-types/deposit.mjs.map +1 -0
- package/es/tx/builder/field-types/fee.d.ts +25 -0
- package/es/tx/{min-fee.mjs → builder/field-types/fee.mjs} +62 -60
- package/es/tx/builder/field-types/fee.mjs.map +1 -0
- package/es/tx/builder/field-types/field.d.ts +6 -0
- package/es/tx/builder/field-types/field.mjs +15 -0
- package/es/tx/builder/field-types/field.mjs.map +1 -0
- package/es/tx/builder/field-types/gas-limit.d.ts +12 -0
- package/es/tx/builder/field-types/gas-limit.mjs +33 -0
- package/es/tx/builder/field-types/gas-limit.mjs.map +1 -0
- package/es/tx/builder/field-types/gas-price.d.ts +8 -0
- package/es/tx/builder/field-types/gas-price.mjs +18 -0
- package/es/tx/builder/field-types/gas-price.mjs.map +1 -0
- package/es/tx/builder/field-types/index.d.ts +70 -0
- package/es/tx/builder/field-types/index.mjs +25 -0
- package/es/tx/builder/field-types/index.mjs.map +1 -0
- package/es/tx/builder/field-types/name-fee.d.ts +20 -0
- package/es/tx/builder/field-types/name-fee.mjs +24 -0
- package/es/tx/builder/field-types/name-fee.mjs.map +1 -0
- package/es/tx/builder/field-types/name-id.d.ts +14 -0
- package/es/tx/builder/field-types/name-id.mjs +19 -0
- package/es/tx/builder/field-types/name-id.mjs.map +1 -0
- package/es/tx/builder/field-types/name.d.ts +13 -0
- package/es/tx/builder/field-types/name.mjs +18 -0
- package/es/tx/builder/field-types/name.mjs.map +1 -0
- package/es/tx/builder/field-types/short-u-int.d.ts +6 -0
- package/es/tx/builder/field-types/short-u-int.mjs +12 -0
- package/es/tx/builder/field-types/short-u-int.mjs.map +1 -0
- package/es/tx/builder/field-types/u-int.d.ts +8 -0
- package/es/tx/builder/field-types/u-int.mjs +14 -0
- package/es/tx/builder/field-types/u-int.mjs.map +1 -0
- package/es/tx/builder/helpers.d.ts +27 -33
- package/es/tx/builder/helpers.mjs +41 -47
- package/es/tx/builder/helpers.mjs.map +1 -1
- package/es/tx/builder/index.d.ts +25 -12
- package/es/tx/builder/index.mjs +74 -83
- package/es/tx/builder/index.mjs.map +1 -1
- package/es/tx/builder/schema.d.ts +995 -144
- package/es/tx/builder/schema.mjs +121 -170
- package/es/tx/builder/schema.mjs.map +1 -1
- package/es/tx/index.d.ts +28 -27
- package/es/tx/index.mjs +97 -117
- package/es/tx/index.mjs.map +1 -1
- package/es/tx/validator.d.ts +4 -3
- package/es/tx/validator.mjs +79 -92
- package/es/tx/validator.mjs.map +1 -1
- package/es/typings/@aeternity__argon2-browser/index.d.mjs.map +1 -1
- package/es/typings/@aeternity__uuid/index.d.mjs.map +1 -1
- package/es/typings/bip32-path/index.d.mjs.map +1 -1
- package/es/typings/blakejs/index.d.mjs.map +1 -1
- package/es/typings/sha-js/index.d.mjs +2 -0
- package/es/typings/sha-js/index.d.mjs.map +1 -0
- package/es/typings/tweetnacl-auth/index.d.mjs.map +1 -1
- package/es/utils/amount-formatter.d.ts +9 -9
- package/es/utils/amount-formatter.mjs +17 -17
- package/es/utils/amount-formatter.mjs.map +1 -1
- package/es/utils/autorest.mjs +7 -7
- package/es/utils/autorest.mjs.map +1 -1
- package/es/utils/bignumber.mjs +2 -1
- package/es/utils/bignumber.mjs.map +1 -1
- package/es/utils/bytes.mjs +1 -1
- package/es/utils/bytes.mjs.map +1 -1
- package/es/utils/crypto.d.ts +8 -23
- package/es/utils/crypto.mjs +15 -41
- package/es/utils/crypto.mjs.map +1 -1
- package/es/utils/encoder-types.d.ts +61 -0
- package/es/utils/encoder-types.mjs +36 -0
- package/es/utils/encoder-types.mjs.map +1 -0
- package/es/utils/encoder.d.ts +6 -7
- package/es/utils/encoder.mjs +42 -26
- package/es/utils/encoder.mjs.map +1 -1
- package/es/utils/errors.d.ts +1 -11
- package/es/utils/errors.mjs +4 -20
- package/es/utils/errors.mjs.map +1 -1
- package/es/utils/hd-wallet.d.ts +18 -2
- package/es/utils/hd-wallet.mjs +64 -34
- package/es/utils/hd-wallet.mjs.map +1 -1
- package/es/utils/json-big.mjs +2 -2
- package/es/utils/json-big.mjs.map +1 -1
- package/es/utils/keystore.mjs +4 -2
- package/es/utils/keystore.mjs.map +1 -1
- package/es/utils/mptree.d.ts +2 -2
- package/es/utils/mptree.mjs +11 -6
- package/es/utils/mptree.mjs.map +1 -1
- package/es/utils/other.d.ts +8 -2
- package/es/utils/other.mjs +15 -3
- package/es/utils/other.mjs.map +1 -1
- package/es/utils/semver-satisfies.d.ts +1 -1
- package/es/utils/semver-satisfies.mjs +2 -2
- package/es/utils/semver-satisfies.mjs.map +1 -1
- package/es/utils/string.mjs.map +1 -1
- package/package.json +36 -34
- package/src/AeSdk.ts +30 -27
- package/src/AeSdkAepp.ts +93 -84
- package/src/AeSdkBase.ts +148 -130
- package/src/AeSdkWallet.ts +172 -156
- package/src/Node.ts +108 -102
- package/src/account/Base.ts +42 -32
- package/src/account/Memory.ts +45 -30
- package/src/account/Rpc.ts +32 -30
- package/src/aens.ts +124 -108
- package/src/aepp-wallet-communication/connection/Browser.ts +18 -15
- package/src/aepp-wallet-communication/connection/BrowserRuntime.ts +22 -21
- package/src/aepp-wallet-communication/connection/BrowserWindowMessage.ts +63 -52
- package/src/aepp-wallet-communication/connection-proxy.ts +8 -7
- package/src/aepp-wallet-communication/rpc/RpcClient.ts +67 -61
- package/src/aepp-wallet-communication/rpc/types.ts +32 -32
- package/src/aepp-wallet-communication/schema.ts +117 -74
- package/src/aepp-wallet-communication/wallet-detector.ts +29 -28
- package/src/apis/node/code-model-v4.yaml +54 -20
- package/src/apis/node/models/index.ts +6 -2
- package/src/apis/node/models/mappers.ts +4 -2
- package/src/chain.ts +286 -228
- package/src/channel/handlers.ts +424 -372
- package/src/channel/index.ts +285 -251
- package/src/channel/internal.ts +248 -232
- package/src/contract/Compiler.ts +22 -21
- package/src/contract/aci.ts +267 -258
- package/src/contract/ga.ts +93 -72
- package/src/contract/methods.ts +32 -27
- package/src/deprecated/index.ts +172 -0
- package/src/deprecated/methods.ts +25 -0
- package/src/index.ts +37 -32
- package/src/oracle.ts +211 -189
- package/src/spend.ts +82 -70
- package/src/tx/builder/address.ts +50 -0
- package/src/tx/builder/constants.ts +82 -52
- package/src/tx/builder/field-types/coin-amount.ts +27 -0
- package/src/tx/builder/field-types/deposit.ts +21 -0
- package/src/tx/builder/field-types/fee.ts +143 -0
- package/src/tx/builder/field-types/field.ts +9 -0
- package/src/tx/builder/field-types/gas-limit.ts +41 -0
- package/src/tx/builder/field-types/gas-price.ts +16 -0
- package/src/tx/builder/field-types/index.ts +45 -0
- package/src/tx/builder/field-types/name-fee.ts +32 -0
- package/src/tx/builder/field-types/name-id.ts +20 -0
- package/src/tx/builder/field-types/name.ts +18 -0
- package/src/tx/builder/field-types/short-u-int.ts +11 -0
- package/src/tx/builder/field-types/u-int.ts +16 -0
- package/src/tx/builder/helpers.ts +112 -117
- package/src/tx/builder/index.ts +203 -197
- package/src/tx/builder/schema.ts +421 -465
- package/src/tx/index.ts +128 -135
- package/src/tx/validator.ts +165 -161
- package/src/typings/@aeternity__argon2-browser/index.d.ts +1 -1
- package/src/typings/@aeternity__uuid/index.d.ts +3 -1
- package/src/typings/bip32-path/index.d.ts +6 -6
- package/src/typings/blakejs/index.d.ts +4 -32
- package/src/typings/sha-js/index.d.ts +5 -0
- package/src/typings/tweetnacl-auth/index.d.ts +2 -2
- package/src/utils/amount-formatter.ts +41 -41
- package/src/utils/autorest.ts +57 -54
- package/src/utils/bignumber.ts +7 -6
- package/src/utils/bytes.ts +19 -19
- package/src/utils/crypto.ts +82 -94
- package/src/utils/encoder-types.ts +63 -0
- package/src/utils/encoder.ts +104 -56
- package/src/utils/errors.ts +246 -264
- package/src/utils/hd-wallet.ts +114 -82
- package/src/utils/json-big.ts +16 -15
- package/src/utils/keystore.ts +65 -62
- package/src/utils/mptree.ts +59 -56
- package/src/utils/other.ts +26 -18
- package/src/utils/semver-satisfies.ts +15 -11
- package/src/utils/string.ts +10 -10
- package/es/tx/builder/field-types.d.ts +0 -62
- package/es/tx/builder/field-types.mjs +0 -126
- package/es/tx/builder/field-types.mjs.map +0 -1
- package/es/tx/min-fee.d.ts +0 -20
- package/es/tx/min-fee.mjs.map +0 -1
- package/src/tx/builder/field-types.ts +0 -111
- package/src/tx/min-fee.ts +0 -136
package/src/tx/builder/index.ts
CHANGED
|
@@ -1,104 +1,101 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
|
|
1
|
+
import { decode as rlpDecode, encode as rlpEncode, NestedUint8Array } from 'rlp';
|
|
2
|
+
import {
|
|
3
|
+
decode, encode, Encoded, Encoding,
|
|
4
|
+
} from '../../utils/encoder';
|
|
5
|
+
import { AE_AMOUNT_FORMATS } from '../../utils/amount-formatter';
|
|
6
|
+
import { hash } from '../../utils/crypto';
|
|
7
|
+
import { Field } from './field-types';
|
|
8
8
|
import {
|
|
9
9
|
FIELD_TYPES,
|
|
10
10
|
RawTxObject,
|
|
11
|
+
TX_SCHEMA,
|
|
11
12
|
TxField,
|
|
12
|
-
TxTypeSchemas,
|
|
13
13
|
TxParamsCommon,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} from './
|
|
14
|
+
TxSchema,
|
|
15
|
+
TxTypeSchemas,
|
|
16
|
+
} from './schema';
|
|
17
|
+
import { Tag } from './constants';
|
|
18
|
+
import {
|
|
19
|
+
buildContractId, buildPointers, readInt, readPointers, writeInt,
|
|
20
|
+
} from './helpers';
|
|
21
|
+
import { readId, writeId } from './address';
|
|
22
|
+
import { toBytes } from '../../utils/bytes';
|
|
23
|
+
import MPTree, { MPTreeBinary } from '../../utils/mptree';
|
|
18
24
|
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
decode,
|
|
27
|
-
Pointer,
|
|
28
|
-
buildContractId
|
|
29
|
-
} from './helpers'
|
|
30
|
-
import { toBytes } from '../../utils/bytes'
|
|
31
|
-
import MPTree, { MPTreeBinary } from '../../utils/mptree'
|
|
32
|
-
import { ArgumentError, InvalidTxParamsError, SchemaNotFoundError, DecodeError } from '../../utils/errors'
|
|
33
|
-
import { isKeyOfObject } from '../../utils/other'
|
|
25
|
+
ArgumentError,
|
|
26
|
+
DecodeError,
|
|
27
|
+
InvalidTxParamsError,
|
|
28
|
+
SchemaNotFoundError,
|
|
29
|
+
} from '../../utils/errors';
|
|
30
|
+
import { isKeyOfObject } from '../../utils/other';
|
|
31
|
+
import { NamePointer } from '../../apis/node';
|
|
34
32
|
|
|
35
33
|
/**
|
|
36
34
|
* JavaScript-based Transaction builder
|
|
37
35
|
*/
|
|
38
36
|
|
|
39
37
|
// SERIALIZE AND DESERIALIZE PART
|
|
40
|
-
function deserializeField
|
|
38
|
+
function deserializeField(
|
|
41
39
|
value: any,
|
|
42
|
-
type: FIELD_TYPES |
|
|
43
|
-
prefix?:
|
|
40
|
+
type: FIELD_TYPES | Field,
|
|
41
|
+
prefix?: Encoding | Encoding[],
|
|
44
42
|
): any {
|
|
45
|
-
if (value == null) return ''
|
|
43
|
+
if (value == null) return '';
|
|
46
44
|
switch (type) {
|
|
47
45
|
case FIELD_TYPES.ctVersion: {
|
|
48
|
-
const [vm, , abi] = value
|
|
46
|
+
const [vm, , abi] = value;
|
|
49
47
|
return {
|
|
50
48
|
vmVersion: readInt(Buffer.from([vm])),
|
|
51
|
-
abiVersion: readInt(Buffer.from([abi]))
|
|
52
|
-
}
|
|
49
|
+
abiVersion: readInt(Buffer.from([abi])),
|
|
50
|
+
};
|
|
53
51
|
}
|
|
54
|
-
case FIELD_TYPES.amount:
|
|
55
|
-
case FIELD_TYPES.int:
|
|
56
52
|
case FIELD_TYPES.abiVersion:
|
|
57
53
|
case FIELD_TYPES.ttlType:
|
|
58
|
-
return readInt(value)
|
|
59
|
-
case FIELD_TYPES.shortInt:
|
|
60
|
-
return +readInt(value)
|
|
54
|
+
return readInt(value);
|
|
61
55
|
case FIELD_TYPES.id:
|
|
62
|
-
return readId(value)
|
|
56
|
+
return readId(value);
|
|
63
57
|
case FIELD_TYPES.ids:
|
|
64
|
-
return value.map(readId)
|
|
58
|
+
return value.map(readId);
|
|
65
59
|
case FIELD_TYPES.bool:
|
|
66
|
-
return value[0] === 1
|
|
60
|
+
return value[0] === 1;
|
|
67
61
|
case FIELD_TYPES.binary:
|
|
68
|
-
return encode(value, prefix as
|
|
62
|
+
return encode(value, prefix as Encoding);
|
|
69
63
|
case FIELD_TYPES.stateTree:
|
|
70
|
-
return encode(value,
|
|
64
|
+
return encode(value, Encoding.StateTrees);
|
|
71
65
|
case FIELD_TYPES.string:
|
|
72
|
-
return value.toString()
|
|
66
|
+
return value.toString();
|
|
73
67
|
case FIELD_TYPES.payload:
|
|
74
|
-
return encode(value,
|
|
68
|
+
return encode(value, Encoding.Bytearray);
|
|
75
69
|
case FIELD_TYPES.pointers:
|
|
76
|
-
return readPointers(value)
|
|
70
|
+
return readPointers(value);
|
|
77
71
|
case FIELD_TYPES.rlpBinary:
|
|
78
|
-
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
73
|
+
return unpackTx(encode(value, Encoding.Transaction));
|
|
79
74
|
case FIELD_TYPES.rlpBinaries:
|
|
80
|
-
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
76
|
+
return value.map((v: Buffer) => unpackTx(encode(v, Encoding.Transaction)));
|
|
81
77
|
case FIELD_TYPES.rawBinary:
|
|
82
|
-
return value
|
|
78
|
+
return value;
|
|
83
79
|
case FIELD_TYPES.hex:
|
|
84
|
-
return value.toString('hex')
|
|
80
|
+
return value.toString('hex');
|
|
85
81
|
case FIELD_TYPES.offChainUpdates:
|
|
86
|
-
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
83
|
+
return value.map((v: Buffer) => unpackTx(encode(v, Encoding.Transaction)));
|
|
87
84
|
case FIELD_TYPES.callStack:
|
|
88
85
|
// TODO: fix this
|
|
89
|
-
return [readInt(value)]
|
|
86
|
+
return [readInt(value)];
|
|
90
87
|
case FIELD_TYPES.mptrees:
|
|
91
|
-
return value.map((t: MPTreeBinary) => new MPTree(t))
|
|
88
|
+
return value.map((t: MPTreeBinary) => new MPTree(t));
|
|
92
89
|
case FIELD_TYPES.callReturnType:
|
|
93
90
|
switch (readInt(value)) {
|
|
94
91
|
case '0':
|
|
95
|
-
return 'ok'
|
|
92
|
+
return 'ok';
|
|
96
93
|
case '1':
|
|
97
|
-
return 'error'
|
|
94
|
+
return 'error';
|
|
98
95
|
case '2':
|
|
99
|
-
return 'revert'
|
|
96
|
+
return 'revert';
|
|
100
97
|
default:
|
|
101
|
-
return value
|
|
98
|
+
return value;
|
|
102
99
|
}
|
|
103
100
|
case FIELD_TYPES.sophiaCodeTypeInfo:
|
|
104
101
|
return value.reduce(
|
|
@@ -106,180 +103,161 @@ function deserializeField (
|
|
|
106
103
|
funHash: Buffer,
|
|
107
104
|
fnName: string,
|
|
108
105
|
argType: string,
|
|
109
|
-
outType: string
|
|
106
|
+
outType: string,
|
|
110
107
|
]) => ({
|
|
111
108
|
...acc,
|
|
112
|
-
[fnName.toString()]: { funHash, argType, outType }
|
|
109
|
+
[fnName.toString()]: { funHash, argType, outType },
|
|
113
110
|
}),
|
|
114
|
-
{}
|
|
115
|
-
)
|
|
111
|
+
{},
|
|
112
|
+
);
|
|
116
113
|
default:
|
|
117
|
-
if (type
|
|
118
|
-
return value
|
|
114
|
+
if (typeof type === 'number') return value;
|
|
115
|
+
return type.deserialize(value);
|
|
119
116
|
}
|
|
120
117
|
}
|
|
121
118
|
|
|
122
|
-
function serializeField
|
|
123
|
-
value: any, type: FIELD_TYPES | typeof Field, params: any
|
|
124
|
-
): any {
|
|
119
|
+
function serializeField(value: any, type: FIELD_TYPES | Field, params: any): any {
|
|
125
120
|
switch (type) {
|
|
126
|
-
case FIELD_TYPES.amount:
|
|
127
|
-
case FIELD_TYPES.int:
|
|
128
|
-
case FIELD_TYPES.shortInt:
|
|
129
121
|
case FIELD_TYPES.abiVersion:
|
|
130
122
|
case FIELD_TYPES.ttlType:
|
|
131
|
-
return writeInt(value)
|
|
123
|
+
return writeInt(value);
|
|
132
124
|
case FIELD_TYPES.id:
|
|
133
|
-
return writeId(value)
|
|
125
|
+
return writeId(value);
|
|
134
126
|
case FIELD_TYPES.ids:
|
|
135
|
-
return value.map(writeId)
|
|
127
|
+
return value.map(writeId);
|
|
136
128
|
case FIELD_TYPES.bool:
|
|
137
|
-
return Buffer.from([(value === true) ? 1 : 0])
|
|
129
|
+
return Buffer.from([(value === true) ? 1 : 0]);
|
|
138
130
|
case FIELD_TYPES.binary:
|
|
139
|
-
return decode(value)
|
|
131
|
+
return decode(value);
|
|
140
132
|
case FIELD_TYPES.stateTree:
|
|
141
|
-
return decode(value)
|
|
133
|
+
return decode(value);
|
|
142
134
|
case FIELD_TYPES.hex:
|
|
143
|
-
return Buffer.from(value, 'hex')
|
|
135
|
+
return Buffer.from(value, 'hex');
|
|
144
136
|
case FIELD_TYPES.signatures:
|
|
145
|
-
return value.map(Buffer.from)
|
|
137
|
+
return value.map(Buffer.from);
|
|
146
138
|
case FIELD_TYPES.payload:
|
|
147
139
|
return typeof value === 'string' && value.split('_')[0] === 'ba'
|
|
148
|
-
? decode(value as
|
|
149
|
-
: toBytes(value)
|
|
140
|
+
? decode(value as Encoded.Bytearray)
|
|
141
|
+
: toBytes(value);
|
|
150
142
|
case FIELD_TYPES.string:
|
|
151
|
-
return toBytes(value)
|
|
143
|
+
return toBytes(value);
|
|
152
144
|
case FIELD_TYPES.pointers:
|
|
153
|
-
return buildPointers(value)
|
|
145
|
+
return buildPointers(value);
|
|
154
146
|
case FIELD_TYPES.rlpBinary:
|
|
155
|
-
return value.rlpEncoded ?? value
|
|
147
|
+
return value.rlpEncoded ?? value;
|
|
156
148
|
case FIELD_TYPES.mptrees:
|
|
157
|
-
return value.map((t:
|
|
149
|
+
return value.map((t: MPTree) => t.serialize());
|
|
158
150
|
case FIELD_TYPES.ctVersion:
|
|
159
|
-
return Buffer.from([...toBytes(value.vmVersion), 0, ...toBytes(value.abiVersion)])
|
|
151
|
+
return Buffer.from([...toBytes(value.vmVersion), 0, ...toBytes(value.abiVersion)]);
|
|
160
152
|
case FIELD_TYPES.callReturnType:
|
|
161
153
|
switch (value) {
|
|
162
|
-
case 'ok': return writeInt(0)
|
|
163
|
-
case 'error': return writeInt(1)
|
|
164
|
-
case 'revert': return writeInt(2)
|
|
165
|
-
default: return value
|
|
154
|
+
case 'ok': return writeInt(0);
|
|
155
|
+
case 'error': return writeInt(1);
|
|
156
|
+
case 'revert': return writeInt(2);
|
|
157
|
+
default: return value;
|
|
166
158
|
}
|
|
167
159
|
default:
|
|
168
|
-
if (type
|
|
169
|
-
|
|
160
|
+
if (typeof type === 'number') return value;
|
|
161
|
+
// @ts-expect-error will be solved after removing the whole serializeField function
|
|
162
|
+
return type.serialize(value, params);
|
|
170
163
|
}
|
|
171
164
|
}
|
|
172
165
|
|
|
173
|
-
function validateField
|
|
166
|
+
function validateField(
|
|
174
167
|
value: any,
|
|
175
|
-
type: FIELD_TYPES |
|
|
176
|
-
prefix?:
|
|
168
|
+
type: FIELD_TYPES | Field,
|
|
169
|
+
prefix?: Encoding | Encoding[],
|
|
177
170
|
): string | undefined {
|
|
178
171
|
// All fields are required
|
|
179
|
-
if (value == null) return 'Field is required'
|
|
172
|
+
if (value == null) return 'Field is required';
|
|
180
173
|
|
|
181
174
|
// Validate type of value
|
|
182
175
|
switch (type) {
|
|
183
|
-
case FIELD_TYPES.amount:
|
|
184
|
-
case FIELD_TYPES.int:
|
|
185
|
-
case FIELD_TYPES.shortInt: {
|
|
186
|
-
if (isNaN(value) && !BigNumber.isBigNumber(value)) {
|
|
187
|
-
return `${String(value)} is not of type Number or BigNumber`
|
|
188
|
-
}
|
|
189
|
-
if (new BigNumber(value).lt(0)) return `${String(value)} must be >= 0`
|
|
190
|
-
return
|
|
191
|
-
}
|
|
192
176
|
case FIELD_TYPES.id: {
|
|
193
|
-
const prefixes = Array.isArray(prefix) ? prefix : [prefix]
|
|
177
|
+
const prefixes = Array.isArray(prefix) ? prefix : [prefix];
|
|
194
178
|
if (!prefixes.includes(value.split('_')[0])) {
|
|
195
|
-
if (prefix == null) { return `'${String(value)}' prefix doesn't exist'
|
|
196
|
-
return `'${String(value)}' prefix doesn't match expected prefix '${prefix.toString()}'
|
|
179
|
+
if (prefix == null) { return `'${String(value)}' prefix doesn't exist'`; }
|
|
180
|
+
return `'${String(value)}' prefix doesn't match expected prefix '${prefix.toString()}'`;
|
|
197
181
|
}
|
|
198
|
-
return
|
|
182
|
+
return undefined;
|
|
199
183
|
}
|
|
200
184
|
case FIELD_TYPES.ctVersion:
|
|
201
185
|
if (!(Boolean(value.abiVersion) && Boolean(value.vmVersion))) {
|
|
202
|
-
return 'Value must be an object with "vmVersion" and "abiVersion" fields'
|
|
186
|
+
return 'Value must be an object with "vmVersion" and "abiVersion" fields';
|
|
203
187
|
}
|
|
204
|
-
return
|
|
188
|
+
return undefined;
|
|
205
189
|
case FIELD_TYPES.pointers:
|
|
206
|
-
if (!Array.isArray(value)) return 'Value must be of type Array'
|
|
207
|
-
if (value.some((p:
|
|
208
|
-
return 'Value must contains only object\'s like \'{key: "account_pubkey", id: "ak_lkamsflkalsdalksdlasdlasdlamd"}\''
|
|
190
|
+
if (!Array.isArray(value)) return 'Value must be of type Array';
|
|
191
|
+
if (value.some((p: NamePointer) => !(Boolean(p.key) && Boolean(p.id)))) {
|
|
192
|
+
return 'Value must contains only object\'s like \'{key: "account_pubkey", id: "ak_lkamsflkalsdalksdlasdlasdlamd"}\'';
|
|
209
193
|
}
|
|
210
194
|
if (value.length > 32) {
|
|
211
|
-
return `Expected 32 pointers or less, got ${value.length} instead
|
|
195
|
+
return `Expected 32 pointers or less, got ${value.length} instead`;
|
|
212
196
|
}
|
|
197
|
+
return undefined;
|
|
198
|
+
default:
|
|
199
|
+
return undefined;
|
|
213
200
|
}
|
|
214
201
|
}
|
|
215
202
|
|
|
216
|
-
function transformParams (
|
|
217
|
-
params: TxParamsCommon,
|
|
218
|
-
schema: TxField[],
|
|
219
|
-
{ denomination }: {denomination?: AE_AMOUNT_FORMATS} = {}
|
|
220
|
-
): any {
|
|
221
|
-
params = schema
|
|
222
|
-
.filter(([, t]) => t === FIELD_TYPES.amount)
|
|
223
|
-
.reduce(
|
|
224
|
-
(params: TxParamsCommon, [key]) => ({
|
|
225
|
-
...params,
|
|
226
|
-
[key]: formatAmount(params[key as keyof TxParamsCommon], { denomination })
|
|
227
|
-
}),
|
|
228
|
-
params
|
|
229
|
-
)
|
|
230
|
-
return params
|
|
231
|
-
}
|
|
232
|
-
|
|
233
203
|
/**
|
|
234
204
|
* Validate transaction params
|
|
205
|
+
* @category transaction builder
|
|
235
206
|
* @param params - Object with tx params
|
|
236
207
|
* @param schema - Transaction schema
|
|
237
208
|
* @param excludeKeys - Array of keys to exclude for validation
|
|
238
209
|
* @returns Object with validation errors
|
|
239
210
|
*/
|
|
240
|
-
export function validateParams
|
|
241
|
-
params: any,
|
|
211
|
+
export function validateParams(
|
|
212
|
+
params: any,
|
|
213
|
+
schema: TxField[],
|
|
214
|
+
{ excludeKeys = [] }: { excludeKeys: string[] },
|
|
242
215
|
): object {
|
|
243
216
|
return Object.fromEntries(
|
|
244
217
|
schema
|
|
245
218
|
// TODO: allow optional keys in schema
|
|
246
|
-
.filter(([key]) => !excludeKeys.includes(key)
|
|
247
|
-
!['payload', 'nameFee', 'deposit', 'gasPrice'].includes(key))
|
|
219
|
+
.filter(([key]) => !excludeKeys.includes(key)
|
|
220
|
+
&& !['payload', 'nameFee', 'deposit', 'gasPrice', 'fee', 'gasLimit'].includes(key))
|
|
248
221
|
.map(([key, type, prefix]) => [key, validateField(params[key], type, prefix)])
|
|
249
|
-
.filter(([, message]) => message)
|
|
250
|
-
)
|
|
222
|
+
.filter(([, message]) => message),
|
|
223
|
+
);
|
|
251
224
|
}
|
|
252
225
|
|
|
253
226
|
/**
|
|
254
227
|
* Unpack binary transaction
|
|
228
|
+
* @category transaction builder
|
|
255
229
|
* @param binary - Array with binary transaction field's
|
|
256
230
|
* @param schema - Transaction schema
|
|
257
231
|
* @returns Object with transaction field's
|
|
258
232
|
*/
|
|
259
|
-
export function unpackRawTx<Tx extends TxSchema>
|
|
233
|
+
export function unpackRawTx<Tx extends TxSchema>(
|
|
260
234
|
binary: Uint8Array | NestedUint8Array,
|
|
261
|
-
schema: TxField[]
|
|
235
|
+
schema: TxField[],
|
|
262
236
|
): RawTxObject<Tx> {
|
|
263
237
|
return schema
|
|
264
238
|
.reduce<any>(
|
|
265
239
|
(
|
|
266
240
|
acc,
|
|
267
241
|
[key, fieldType, prefix],
|
|
268
|
-
index
|
|
242
|
+
index,
|
|
269
243
|
) => Object.assign(acc, { [key]: deserializeField(binary[index], fieldType, prefix) }),
|
|
270
|
-
{}
|
|
271
|
-
)
|
|
244
|
+
{},
|
|
245
|
+
);
|
|
272
246
|
}
|
|
273
247
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
248
|
+
/**
|
|
249
|
+
* @category transaction builder
|
|
250
|
+
*/
|
|
251
|
+
export interface BuiltTx<Tx extends TxSchema, Prefix extends Encoding> {
|
|
252
|
+
tx: Encoded.Generic<Prefix>;
|
|
253
|
+
rlpEncoded: Uint8Array;
|
|
254
|
+
binary: Uint8Array;
|
|
255
|
+
txObject: RawTxObject<Tx>;
|
|
279
256
|
}
|
|
280
257
|
|
|
281
258
|
/**
|
|
282
259
|
* Build transaction hash
|
|
260
|
+
* @category transaction builder
|
|
283
261
|
* @param _params - Object with tx params
|
|
284
262
|
* @param type - Transaction type
|
|
285
263
|
* @param options - options
|
|
@@ -292,103 +270,131 @@ export interface BuiltTx<Tx extends TxSchema, Prefix extends EncodingType> {
|
|
|
292
270
|
* @returns object.rlpEncoded rlp encoded transaction
|
|
293
271
|
* @returns object.binary binary transaction
|
|
294
272
|
*/
|
|
295
|
-
export function buildTx<TxType extends
|
|
273
|
+
export function buildTx<TxType extends Tag, Prefix>(
|
|
296
274
|
_params: Omit<TxTypeSchemas[TxType], 'tag' | 'VSN'> & { VSN?: number },
|
|
297
275
|
type: TxType,
|
|
298
|
-
{
|
|
299
|
-
excludeKeys
|
|
300
|
-
prefix
|
|
301
|
-
vsn
|
|
302
|
-
denomination
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
|
|
276
|
+
{
|
|
277
|
+
excludeKeys = [],
|
|
278
|
+
prefix = Encoding.Transaction,
|
|
279
|
+
vsn,
|
|
280
|
+
denomination = AE_AMOUNT_FORMATS.AETTOS,
|
|
281
|
+
}: {
|
|
282
|
+
excludeKeys?: string[];
|
|
283
|
+
prefix?: Encoding;
|
|
284
|
+
vsn?: number;
|
|
285
|
+
denomination?: AE_AMOUNT_FORMATS;
|
|
286
|
+
} = {},
|
|
287
|
+
): BuiltTx<TxSchema, Prefix extends Encoding ? Prefix : Encoding.Transaction> {
|
|
288
|
+
const schemas = TX_SCHEMA[type];
|
|
306
289
|
|
|
307
|
-
vsn ??= Math.max(...Object.keys(schemas).map(a => +a))
|
|
308
|
-
if (!isKeyOfObject(vsn, schemas)) throw new SchemaNotFoundError('serialization',
|
|
290
|
+
vsn ??= Math.max(...Object.keys(schemas).map((a) => +a));
|
|
291
|
+
if (!isKeyOfObject(vsn, schemas)) throw new SchemaNotFoundError('serialization', Tag[type], vsn);
|
|
309
292
|
|
|
310
|
-
const schema = schemas[vsn] as unknown as TxField[]
|
|
293
|
+
const schema = schemas[vsn] as unknown as TxField[];
|
|
311
294
|
|
|
312
|
-
|
|
313
|
-
params.VSN = vsn
|
|
314
|
-
params.tag = type
|
|
315
|
-
|
|
295
|
+
const params = _params as TxParamsCommon & { onNode: Node; denomination?: AE_AMOUNT_FORMATS };
|
|
296
|
+
params.VSN = vsn;
|
|
297
|
+
params.tag = type;
|
|
298
|
+
params.denomination = denomination;
|
|
299
|
+
const filteredSchema = schema.filter(([key]) => !excludeKeys.includes(key));
|
|
316
300
|
|
|
317
|
-
// Transform `amount` type fields to `aettos`
|
|
318
|
-
params = transformParams(params, filteredSchema, { denomination })
|
|
319
301
|
// Validation
|
|
320
|
-
const valid = validateParams(params, schema, { excludeKeys })
|
|
302
|
+
const valid = validateParams(params, schema, { excludeKeys });
|
|
321
303
|
if (Object.keys(valid).length > 0) {
|
|
322
|
-
throw new InvalidTxParamsError(
|
|
304
|
+
throw new InvalidTxParamsError(`Transaction build error. ${JSON.stringify(valid)}`);
|
|
323
305
|
}
|
|
324
306
|
|
|
325
307
|
const binary = filteredSchema
|
|
326
|
-
.map(([key, fieldType]: [keyof TxSchema, FIELD_TYPES,
|
|
327
|
-
|
|
328
|
-
|
|
308
|
+
.map(([key, fieldType]: [keyof TxSchema, FIELD_TYPES, Encoding]) => (
|
|
309
|
+
serializeField(
|
|
310
|
+
params[key],
|
|
311
|
+
fieldType,
|
|
312
|
+
{
|
|
313
|
+
...params,
|
|
314
|
+
txType: type,
|
|
315
|
+
rebuildTx: (overrideParams: any) => buildTx(
|
|
316
|
+
{ ...params, ...overrideParams },
|
|
317
|
+
type,
|
|
318
|
+
{
|
|
319
|
+
excludeKeys, prefix: Encoding.Transaction, vsn, denomination,
|
|
320
|
+
},
|
|
321
|
+
),
|
|
322
|
+
},
|
|
323
|
+
)
|
|
324
|
+
))
|
|
325
|
+
.filter((e) => e !== undefined);
|
|
329
326
|
|
|
330
|
-
const rlpEncoded = rlpEncode(binary)
|
|
331
|
-
const tx = encode(rlpEncoded, prefix)
|
|
327
|
+
const rlpEncoded = rlpEncode(binary);
|
|
328
|
+
const tx = encode(rlpEncoded, prefix);
|
|
332
329
|
return {
|
|
333
330
|
tx,
|
|
334
331
|
rlpEncoded,
|
|
335
332
|
binary,
|
|
336
|
-
txObject: unpackRawTx<TxTypeSchemas[
|
|
337
|
-
} as any
|
|
333
|
+
txObject: unpackRawTx<TxTypeSchemas[Tag]>(binary, schema),
|
|
334
|
+
} as any;
|
|
338
335
|
}
|
|
339
336
|
|
|
337
|
+
/**
|
|
338
|
+
* @category transaction builder
|
|
339
|
+
*/
|
|
340
340
|
export interface TxUnpacked<Tx extends TxSchema> {
|
|
341
|
-
txType:
|
|
342
|
-
tx: RawTxObject<Tx
|
|
343
|
-
rlpEncoded: Uint8Array
|
|
341
|
+
txType: Tag;
|
|
342
|
+
tx: RawTxObject<Tx>;
|
|
343
|
+
rlpEncoded: Uint8Array;
|
|
344
344
|
}
|
|
345
345
|
/**
|
|
346
346
|
* Unpack transaction hash
|
|
347
|
+
* @category transaction builder
|
|
347
348
|
* @param encodedTx - Transaction to unpack
|
|
348
349
|
* @param txType - Expected transaction type
|
|
349
350
|
* @returns object
|
|
350
351
|
* @returns object.tx Object with transaction param's
|
|
351
352
|
* @returns object.txType Transaction type
|
|
352
353
|
*/
|
|
353
|
-
export function unpackTx<TxType extends
|
|
354
|
-
encodedTx:
|
|
354
|
+
export function unpackTx<TxType extends Tag>(
|
|
355
|
+
encodedTx: Encoded.Transaction | Encoded.Poi,
|
|
356
|
+
txType?: TxType,
|
|
355
357
|
): TxUnpacked<TxTypeSchemas[TxType]> {
|
|
356
|
-
const rlpEncoded = decode(encodedTx)
|
|
357
|
-
const binary = rlpDecode(rlpEncoded)
|
|
358
|
-
const objId = +readInt(binary[0] as Buffer)
|
|
359
|
-
if (!isKeyOfObject(objId, TX_SCHEMA)) throw new DecodeError(`Unknown transaction tag: ${objId}`)
|
|
360
|
-
if (txType != null && txType !== objId) throw new DecodeError(`Expected transaction to have ${
|
|
361
|
-
const vsn = +readInt(binary[1] as Buffer)
|
|
362
|
-
if (!isKeyOfObject(vsn, TX_SCHEMA[objId])) throw new SchemaNotFoundError('deserialization', `tag ${objId}`, vsn)
|
|
363
|
-
const schema = TX_SCHEMA[objId][vsn]
|
|
358
|
+
const rlpEncoded = decode(encodedTx);
|
|
359
|
+
const binary = rlpDecode(rlpEncoded);
|
|
360
|
+
const objId = +readInt(binary[0] as Buffer);
|
|
361
|
+
if (!isKeyOfObject(objId, TX_SCHEMA)) throw new DecodeError(`Unknown transaction tag: ${objId}`);
|
|
362
|
+
if (txType != null && txType !== objId) throw new DecodeError(`Expected transaction to have ${Tag[txType]} tag, got ${Tag[objId]} instead`);
|
|
363
|
+
const vsn = +readInt(binary[1] as Buffer);
|
|
364
|
+
if (!isKeyOfObject(vsn, TX_SCHEMA[objId])) throw new SchemaNotFoundError('deserialization', `tag ${objId}`, vsn);
|
|
365
|
+
const schema = TX_SCHEMA[objId][vsn];
|
|
364
366
|
return {
|
|
365
367
|
txType: objId,
|
|
366
368
|
tx: unpackRawTx<TxTypeSchemas[TxType]>(binary, schema),
|
|
367
|
-
rlpEncoded
|
|
368
|
-
}
|
|
369
|
+
rlpEncoded,
|
|
370
|
+
};
|
|
369
371
|
}
|
|
370
372
|
|
|
371
373
|
/**
|
|
372
374
|
* Build a transaction hash
|
|
375
|
+
* @category transaction builder
|
|
373
376
|
* @param rawTx - base64 or rlp encoded transaction
|
|
374
377
|
* @returns Transaction hash
|
|
375
378
|
*/
|
|
376
|
-
export function buildTxHash
|
|
379
|
+
export function buildTxHash(rawTx: Encoded.Transaction | Uint8Array): Encoded.TxHash {
|
|
377
380
|
const data = typeof rawTx === 'string' && rawTx.startsWith('tx_')
|
|
378
381
|
? decode(rawTx)
|
|
379
|
-
: rawTx
|
|
380
|
-
return encode(hash(data),
|
|
382
|
+
: rawTx;
|
|
383
|
+
return encode(hash(data), Encoding.TxHash);
|
|
381
384
|
}
|
|
382
385
|
|
|
383
386
|
/**
|
|
384
387
|
* Build a contract public key by contractCreateTx or gaAttach
|
|
388
|
+
* @category contract
|
|
385
389
|
* @param contractTx - Transaction
|
|
386
390
|
* @returns Contract public key
|
|
387
391
|
*/
|
|
388
|
-
export function buildContractIdByContractTx
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
+
export function buildContractIdByContractTx(
|
|
393
|
+
contractTx: Encoded.Transaction,
|
|
394
|
+
): Encoded.ContractAddress {
|
|
395
|
+
const { txType, tx } = unpackTx<Tag.ContractCreateTx | Tag.GaAttachTx>(contractTx);
|
|
396
|
+
if (![Tag.ContractCreateTx, Tag.GaAttachTx].includes(txType)) {
|
|
397
|
+
throw new ArgumentError('contractCreateTx', 'a contractCreateTx or gaAttach', txType);
|
|
392
398
|
}
|
|
393
|
-
return buildContractId(tx.ownerId, +tx.nonce)
|
|
399
|
+
return buildContractId(tx.ownerId, +tx.nonce);
|
|
394
400
|
}
|