@alephium/web3 0.37.0 → 0.38.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 (97) hide show
  1. package/dist/alephium-web3.min.js +1 -1
  2. package/dist/alephium-web3.min.js.map +1 -1
  3. package/dist/src/api/api-alephium.d.ts +5 -0
  4. package/dist/src/api/types.d.ts +1 -1
  5. package/dist/src/codec/array-codec.d.ts +17 -0
  6. package/dist/src/codec/array-codec.js +59 -0
  7. package/dist/src/codec/asset-output-codec.d.ts +27 -0
  8. package/dist/src/codec/asset-output-codec.js +135 -0
  9. package/dist/src/codec/bigint-codec.d.ts +5 -0
  10. package/dist/src/codec/bigint-codec.js +86 -0
  11. package/dist/src/codec/bytestring-codec.d.ts +16 -0
  12. package/dist/src/codec/bytestring-codec.js +50 -0
  13. package/dist/src/codec/codec.d.ts +8 -0
  14. package/dist/src/codec/codec.js +9 -0
  15. package/dist/src/codec/compact-int-codec.d.ts +51 -0
  16. package/dist/src/codec/compact-int-codec.js +300 -0
  17. package/dist/src/codec/contract-codec.d.ts +23 -0
  18. package/dist/src/codec/contract-codec.js +81 -0
  19. package/dist/src/codec/contract-output-codec.d.ts +21 -0
  20. package/dist/src/codec/contract-output-codec.js +82 -0
  21. package/dist/src/codec/contract-output-ref-codec.d.ts +15 -0
  22. package/dist/src/codec/contract-output-ref-codec.js +38 -0
  23. package/dist/src/codec/either-codec.d.ts +17 -0
  24. package/dist/src/codec/either-codec.js +67 -0
  25. package/dist/src/codec/hash.d.ts +4 -0
  26. package/dist/src/codec/hash.js +23 -0
  27. package/dist/src/codec/index.d.ts +23 -0
  28. package/dist/src/codec/index.js +69 -0
  29. package/dist/src/codec/input-codec.d.ts +22 -0
  30. package/dist/src/codec/input-codec.js +71 -0
  31. package/dist/src/codec/instr-codec.d.ts +230 -0
  32. package/dist/src/codec/instr-codec.js +471 -0
  33. package/dist/src/codec/lockup-script-codec.d.ts +28 -0
  34. package/dist/src/codec/lockup-script-codec.js +80 -0
  35. package/dist/src/codec/long-codec.d.ts +9 -0
  36. package/dist/src/codec/long-codec.js +56 -0
  37. package/dist/src/codec/method-codec.d.ts +31 -0
  38. package/dist/src/codec/method-codec.js +78 -0
  39. package/dist/src/codec/option-codec.d.ts +15 -0
  40. package/dist/src/codec/option-codec.js +55 -0
  41. package/dist/src/codec/output-codec.d.ts +7 -0
  42. package/dist/src/codec/output-codec.js +26 -0
  43. package/dist/src/codec/script-codec.d.ts +16 -0
  44. package/dist/src/codec/script-codec.js +41 -0
  45. package/dist/src/codec/signature-codec.d.ts +14 -0
  46. package/dist/src/codec/signature-codec.js +19 -0
  47. package/dist/src/codec/signed-int-codec.d.ts +9 -0
  48. package/dist/src/codec/signed-int-codec.js +39 -0
  49. package/dist/src/codec/token-codec.d.ts +16 -0
  50. package/dist/src/codec/token-codec.js +46 -0
  51. package/dist/src/codec/transaction-codec.d.ts +27 -0
  52. package/dist/src/codec/transaction-codec.js +128 -0
  53. package/dist/src/codec/unlock-script-codec.d.ts +40 -0
  54. package/dist/src/codec/unlock-script-codec.js +170 -0
  55. package/dist/src/codec/unsigned-tx-codec.d.ts +30 -0
  56. package/dist/src/codec/unsigned-tx-codec.js +103 -0
  57. package/dist/src/contract/contract.d.ts +10 -4
  58. package/dist/src/contract/contract.js +184 -11
  59. package/dist/src/contract/ralph.d.ts +16 -0
  60. package/dist/src/contract/ralph.js +127 -1
  61. package/dist/src/index.d.ts +1 -0
  62. package/dist/src/index.js +2 -1
  63. package/dist/src/utils/address.d.ts +2 -0
  64. package/dist/src/utils/address.js +18 -6
  65. package/package.json +4 -3
  66. package/src/api/api-alephium.ts +6 -0
  67. package/src/api/types.ts +1 -1
  68. package/src/codec/array-codec.ts +63 -0
  69. package/src/codec/asset-output-codec.ts +149 -0
  70. package/src/codec/bigint-codec.ts +92 -0
  71. package/src/codec/bytestring-codec.ts +56 -0
  72. package/src/codec/codec.ts +31 -0
  73. package/src/codec/compact-int-codec.ts +316 -0
  74. package/src/codec/contract-codec.ts +95 -0
  75. package/src/codec/contract-output-codec.ts +95 -0
  76. package/src/codec/contract-output-ref-codec.ts +42 -0
  77. package/src/codec/either-codec.ts +74 -0
  78. package/src/codec/hash.ts +35 -0
  79. package/src/codec/index.ts +41 -0
  80. package/src/codec/input-codec.ts +81 -0
  81. package/src/codec/instr-codec.ts +479 -0
  82. package/src/codec/lockup-script-codec.ts +99 -0
  83. package/src/codec/long-codec.ts +59 -0
  84. package/src/codec/method-codec.ts +97 -0
  85. package/src/codec/option-codec.ts +60 -0
  86. package/src/codec/output-codec.ts +26 -0
  87. package/src/codec/script-codec.ts +45 -0
  88. package/src/codec/signature-codec.ts +40 -0
  89. package/src/codec/signed-int-codec.ts +37 -0
  90. package/src/codec/token-codec.ts +51 -0
  91. package/src/codec/transaction-codec.ts +147 -0
  92. package/src/codec/unlock-script-codec.ts +194 -0
  93. package/src/codec/unsigned-tx-codec.ts +124 -0
  94. package/src/contract/contract.ts +271 -14
  95. package/src/contract/ralph.ts +140 -2
  96. package/src/index.ts +1 -1
  97. package/src/utils/address.ts +17 -5
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unlockScriptCodec = exports.UnlockScriptCodec = exports.P2SHCodec = void 0;
4
+ /*
5
+ Copyright 2018 - 2022 The Alephium Authors
6
+ This file is part of the alephium project.
7
+
8
+ The library is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU Lesser General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ The library is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+ const buffer_1 = require("buffer/");
22
+ const binary_parser_1 = require("binary-parser");
23
+ const array_codec_1 = require("./array-codec");
24
+ const compact_int_codec_1 = require("./compact-int-codec");
25
+ const script_codec_1 = require("./script-codec");
26
+ const bytestring_codec_1 = require("./bytestring-codec");
27
+ const lockup_script_codec_1 = require("./lockup-script-codec");
28
+ class P2PKHCodec {
29
+ constructor() {
30
+ this.parser = binary_parser_1.Parser.start().buffer('publicKey', { length: 33 });
31
+ }
32
+ encode(input) {
33
+ return input.publicKey;
34
+ }
35
+ decode(input) {
36
+ return this.parser.parse(input);
37
+ }
38
+ }
39
+ const p2pkhCodec = new P2PKHCodec();
40
+ class P2MPKHCodec {
41
+ constructor() {
42
+ this.parser = binary_parser_1.Parser.start().nest('publicKeys', {
43
+ type: array_codec_1.ArrayCodec.arrayParser(binary_parser_1.Parser.start()
44
+ .nest('publicKey', { type: p2pkhCodec.parser })
45
+ .nest('index', { type: compact_int_codec_1.compactUnsignedIntCodec.parser }))
46
+ });
47
+ }
48
+ encode(input) {
49
+ return buffer_1.Buffer.concat([
50
+ buffer_1.Buffer.from(compact_int_codec_1.compactUnsignedIntCodec.encode(input.publicKeys.length)),
51
+ ...input.publicKeys.value.map((v) => {
52
+ return buffer_1.Buffer.concat([v.publicKey.publicKey, buffer_1.Buffer.from(compact_int_codec_1.compactUnsignedIntCodec.encode(v.index))]);
53
+ })
54
+ ]);
55
+ }
56
+ decode(input) {
57
+ return this.parser.parse(input);
58
+ }
59
+ }
60
+ const p2mpkhCodec = new P2MPKHCodec();
61
+ class ValCodec {
62
+ constructor() {
63
+ this.parser = binary_parser_1.Parser.start()
64
+ .int8('type')
65
+ .choice('val', {
66
+ tag: 'type',
67
+ choices: {
68
+ 0x00: new binary_parser_1.Parser().uint8('value'),
69
+ 0x01: compact_int_codec_1.compactSignedIntCodec.parser,
70
+ 0x02: compact_int_codec_1.compactUnsignedIntCodec.parser,
71
+ 0x03: bytestring_codec_1.byteStringCodec.parser,
72
+ 0x04: lockup_script_codec_1.lockupScriptCodec.parser // Address
73
+ }
74
+ });
75
+ }
76
+ encode(input) {
77
+ const valType = input.type;
78
+ if (valType === 0x00) {
79
+ // Boolean
80
+ return buffer_1.Buffer.from([valType, input.val]);
81
+ }
82
+ else if (valType === 0x01) {
83
+ // I256
84
+ return buffer_1.Buffer.from([valType, ...compact_int_codec_1.compactUnsignedIntCodec.encode(input.val)]);
85
+ }
86
+ else if (valType === 0x02) {
87
+ // U256
88
+ return buffer_1.Buffer.from([valType, ...compact_int_codec_1.compactUnsignedIntCodec.encode(input.val)]);
89
+ }
90
+ else if (valType === 0x03) {
91
+ // ByteVec
92
+ return buffer_1.Buffer.from([valType, ...bytestring_codec_1.byteStringCodec.encode(input.val)]);
93
+ }
94
+ else if (valType === 0x04) {
95
+ // Address
96
+ return buffer_1.Buffer.from([valType, ...lockup_script_codec_1.lockupScriptCodec.encode(input.val)]);
97
+ }
98
+ else {
99
+ throw new Error(`ValCodec: unsupported val type: ${valType}`);
100
+ }
101
+ }
102
+ decode(input) {
103
+ return this.parser.parse(input);
104
+ }
105
+ }
106
+ const valCodec = new ValCodec();
107
+ const valsCodec = new array_codec_1.ArrayCodec(valCodec);
108
+ class P2SHCodec {
109
+ constructor() {
110
+ this.parser = binary_parser_1.Parser.start()
111
+ .nest('script', {
112
+ type: script_codec_1.scriptCodec.parser
113
+ })
114
+ .nest('params', {
115
+ type: valsCodec.parser
116
+ });
117
+ }
118
+ encode(input) {
119
+ return buffer_1.Buffer.concat([script_codec_1.scriptCodec.encode(input.script), valsCodec.encode(input.params.value)]);
120
+ }
121
+ decode(input) {
122
+ return this.parser.parse(input);
123
+ }
124
+ }
125
+ exports.P2SHCodec = P2SHCodec;
126
+ const p2shCodec = new P2SHCodec();
127
+ class UnlockScriptCodec {
128
+ constructor() {
129
+ this.parser = binary_parser_1.Parser.start()
130
+ .uint8('scriptType')
131
+ .choice('script', {
132
+ tag: 'scriptType',
133
+ choices: {
134
+ 0: p2pkhCodec.parser,
135
+ 1: p2mpkhCodec.parser,
136
+ 2: p2shCodec.parser,
137
+ 3: binary_parser_1.Parser.start() // TODO: SameAsPrevious, FIXME
138
+ }
139
+ });
140
+ }
141
+ encode(input) {
142
+ const scriptType = input.scriptType;
143
+ const inputUnLockScript = input.script;
144
+ const inputUnLockScriptType = buffer_1.Buffer.from([scriptType]);
145
+ if (scriptType === 0) {
146
+ // P2PKH
147
+ return buffer_1.Buffer.concat([inputUnLockScriptType, p2pkhCodec.encode(inputUnLockScript)]);
148
+ }
149
+ else if (scriptType === 1) {
150
+ // P2MPKH
151
+ return buffer_1.Buffer.concat([inputUnLockScriptType, p2mpkhCodec.encode(inputUnLockScript)]);
152
+ }
153
+ else if (scriptType === 2) {
154
+ // P2SH
155
+ return buffer_1.Buffer.concat([inputUnLockScriptType, p2shCodec.encode(input.script)]);
156
+ }
157
+ else if (scriptType === 3) {
158
+ // SameAsPrevious
159
+ return inputUnLockScriptType;
160
+ }
161
+ else {
162
+ throw new Error(`TODO: encode unlock script: ${scriptType}`);
163
+ }
164
+ }
165
+ decode(input) {
166
+ return this.parser.parse(input);
167
+ }
168
+ }
169
+ exports.UnlockScriptCodec = UnlockScriptCodec;
170
+ exports.unlockScriptCodec = new UnlockScriptCodec();
@@ -0,0 +1,30 @@
1
+ import { Buffer } from 'buffer/';
2
+ import { Parser } from 'binary-parser';
3
+ import { UnsignedTx as ApiUnsignedTx } from '../api/api-alephium';
4
+ import { Script } from './script-codec';
5
+ import { Option } from './option-codec';
6
+ import { DecodedCompactInt } from './compact-int-codec';
7
+ import { Input } from './input-codec';
8
+ import { AssetOutput } from './asset-output-codec';
9
+ import { DecodedArray } from './array-codec';
10
+ import { Codec } from './codec';
11
+ export interface UnsignedTx {
12
+ version: number;
13
+ networkId: number;
14
+ statefulScript: Option<Script>;
15
+ gasAmount: DecodedCompactInt;
16
+ gasPrice: DecodedCompactInt;
17
+ inputs: DecodedArray<Input>;
18
+ fixedOutputs: DecodedArray<AssetOutput>;
19
+ }
20
+ export declare class UnsignedTxCodec implements Codec<UnsignedTx> {
21
+ parser: Parser;
22
+ encode(decodedUnsignedTx: UnsignedTx): Buffer;
23
+ decode(input: Buffer): UnsignedTx;
24
+ encodeApiUnsignedTx(input: ApiUnsignedTx): Buffer;
25
+ decodeApiUnsignedTx(input: Buffer): ApiUnsignedTx;
26
+ static txId(unsignedTx: UnsignedTx): string;
27
+ static toApiUnsignedTx(unsigned: UnsignedTx): ApiUnsignedTx;
28
+ static fromApiUnsignedTx(unsignedTx: ApiUnsignedTx): UnsignedTx;
29
+ }
30
+ export declare const unsignedTxCodec: UnsignedTxCodec;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.unsignedTxCodec = exports.UnsignedTxCodec = void 0;
4
+ /*
5
+ Copyright 2018 - 2022 The Alephium Authors
6
+ This file is part of the alephium project.
7
+
8
+ The library is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU Lesser General Public License as published by
10
+ the Free Software Foundation, either version 3 of the License, or
11
+ (at your option) any later version.
12
+
13
+ The library is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
20
+ */
21
+ const buffer_1 = require("buffer/");
22
+ const binary_parser_1 = require("binary-parser");
23
+ const utils_1 = require("../utils");
24
+ const script_codec_1 = require("./script-codec");
25
+ const compact_int_codec_1 = require("./compact-int-codec");
26
+ const input_codec_1 = require("./input-codec");
27
+ const asset_output_codec_1 = require("./asset-output-codec");
28
+ const hash_1 = require("./hash");
29
+ class UnsignedTxCodec {
30
+ constructor() {
31
+ this.parser = new binary_parser_1.Parser()
32
+ .uint8('version')
33
+ .uint8('networkId')
34
+ .nest('statefulScript', {
35
+ type: script_codec_1.statefulScriptCodecOpt.parser
36
+ })
37
+ .nest('gasAmount', {
38
+ type: compact_int_codec_1.compactSignedIntCodec.parser
39
+ })
40
+ .nest('gasPrice', {
41
+ type: compact_int_codec_1.compactUnsignedIntCodec.parser
42
+ })
43
+ .nest('inputs', {
44
+ type: input_codec_1.inputsCodec.parser
45
+ })
46
+ .nest('fixedOutputs', {
47
+ type: asset_output_codec_1.assetOutputsCodec.parser
48
+ });
49
+ }
50
+ encode(decodedUnsignedTx) {
51
+ return buffer_1.Buffer.concat([
52
+ buffer_1.Buffer.from([decodedUnsignedTx.version, decodedUnsignedTx.networkId]),
53
+ script_codec_1.statefulScriptCodecOpt.encode(decodedUnsignedTx.statefulScript),
54
+ compact_int_codec_1.compactSignedIntCodec.encode(decodedUnsignedTx.gasAmount),
55
+ compact_int_codec_1.compactUnsignedIntCodec.encode(decodedUnsignedTx.gasPrice),
56
+ input_codec_1.inputsCodec.encode(decodedUnsignedTx.inputs.value),
57
+ asset_output_codec_1.assetOutputsCodec.encode(decodedUnsignedTx.fixedOutputs.value)
58
+ ]);
59
+ }
60
+ decode(input) {
61
+ return this.parser.parse(input);
62
+ }
63
+ encodeApiUnsignedTx(input) {
64
+ const decoded = UnsignedTxCodec.fromApiUnsignedTx(input);
65
+ return this.encode(decoded);
66
+ }
67
+ decodeApiUnsignedTx(input) {
68
+ const decoded = this.parser.parse(input);
69
+ return UnsignedTxCodec.toApiUnsignedTx(decoded);
70
+ }
71
+ static txId(unsignedTx) {
72
+ return (0, utils_1.binToHex)((0, hash_1.blakeHash)(exports.unsignedTxCodec.encode(unsignedTx)));
73
+ }
74
+ static toApiUnsignedTx(unsigned) {
75
+ const txId = UnsignedTxCodec.txId(unsigned);
76
+ const txIdBytes = (0, utils_1.hexToBinUnsafe)(txId);
77
+ const version = unsigned.version;
78
+ const networkId = unsigned.networkId;
79
+ const gasAmount = compact_int_codec_1.compactSignedIntCodec.toI32(unsigned.gasAmount);
80
+ const gasPrice = compact_int_codec_1.compactUnsignedIntCodec.toU256(unsigned.gasPrice).toString();
81
+ const inputs = input_codec_1.InputCodec.toAssetInputs(unsigned.inputs.value);
82
+ const fixedOutputs = asset_output_codec_1.AssetOutputCodec.toFixedAssetOutputs(txIdBytes, unsigned.fixedOutputs.value);
83
+ let scriptOpt = undefined;
84
+ if (unsigned.statefulScript.option === 1) {
85
+ scriptOpt = script_codec_1.scriptCodec.encode(unsigned.statefulScript.value).toString('hex');
86
+ }
87
+ return { txId, version, networkId, gasAmount, scriptOpt, gasPrice, inputs, fixedOutputs };
88
+ }
89
+ static fromApiUnsignedTx(unsignedTx) {
90
+ const version = unsignedTx.version;
91
+ const networkId = unsignedTx.networkId;
92
+ const gasAmount = compact_int_codec_1.compactSignedIntCodec.fromI32(unsignedTx.gasAmount);
93
+ const gasPrice = compact_int_codec_1.compactUnsignedIntCodec.fromU256(BigInt(unsignedTx.gasPrice));
94
+ const inputsValue = input_codec_1.InputCodec.fromAssetInputs(unsignedTx.inputs);
95
+ const inputs = input_codec_1.inputsCodec.fromArray(inputsValue);
96
+ const fixedOutputsValue = asset_output_codec_1.AssetOutputCodec.fromFixedAssetOutputs(unsignedTx.fixedOutputs);
97
+ const fixedOutputs = asset_output_codec_1.assetOutputsCodec.fromArray(fixedOutputsValue);
98
+ const statefulScript = script_codec_1.statefulScriptCodecOpt.fromBuffer(unsignedTx.scriptOpt ? buffer_1.Buffer.from(unsignedTx.scriptOpt, 'hex') : undefined);
99
+ return { version, networkId, gasAmount, gasPrice, inputs, fixedOutputs, statefulScript };
100
+ }
101
+ }
102
+ exports.UnsignedTxCodec = UnsignedTxCodec;
103
+ exports.unsignedTxCodec = new UnsignedTxCodec();
@@ -3,6 +3,7 @@ import { SignDeployContractTxParams, SignDeployContractTxResult, SignExecuteScri
3
3
  import { Optional } from '../utils';
4
4
  import { EventSubscribeOptions, EventSubscription } from './events';
5
5
  export type FieldsSig = node.FieldsSig;
6
+ export type MapsSig = node.MapsSig;
6
7
  export type EventSig = node.EventSig;
7
8
  export type FunctionSig = node.FunctionSig;
8
9
  export type Fields = NamedVals;
@@ -130,10 +131,11 @@ export declare class Contract extends Artifact {
130
131
  readonly constants: Constant[];
131
132
  readonly enums: Enum[];
132
133
  readonly structs: Struct[];
134
+ readonly mapsSig?: MapsSig;
133
135
  readonly stdInterfaceId?: HexString;
134
136
  readonly bytecodeDebug: string;
135
137
  readonly codeHashDebug: string;
136
- constructor(version: string, name: string, bytecode: string, bytecodeDebugPatch: string, codeHash: string, codeHashDebug: string, fieldsSig: FieldsSig, eventsSig: EventSig[], functions: FunctionSig[], constants: Constant[], enums: Enum[], structs: Struct[], stdInterfaceId?: HexString);
138
+ constructor(version: string, name: string, bytecode: string, bytecodeDebugPatch: string, codeHash: string, codeHashDebug: string, fieldsSig: FieldsSig, eventsSig: EventSig[], functions: FunctionSig[], constants: Constant[], enums: Enum[], structs: Struct[], mapsSig?: MapsSig, stdInterfaceId?: HexString);
137
139
  static fromJson(artifact: any, bytecodeDebugPatch?: string, codeHashDebug?: string, structs?: Struct[]): Contract;
138
140
  static fromCompileResult(result: node.CompileContractResult, structs?: Struct[]): Contract;
139
141
  static fromArtifactFile(path: string, bytecodeDebugPatch: string, codeHashDebug: string, structs?: Struct[]): Promise<Contract>;
@@ -196,7 +198,8 @@ export interface ContractState<T extends Fields = Fields> {
196
198
  fieldsSig: FieldsSig;
197
199
  asset: Asset;
198
200
  }
199
- export interface TestContractParams<F extends Fields = Fields, A extends Arguments = Arguments> {
201
+ export type TestContractParamsWithoutMaps<F extends Fields = Fields, A extends Arguments = Arguments> = Omit<TestContractParams<F, A>, 'initialMaps'>;
202
+ export interface TestContractParams<F extends Fields = Fields, A extends Arguments = Arguments, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>> {
200
203
  group?: number;
201
204
  address?: string;
202
205
  callerAddress?: string;
@@ -204,6 +207,7 @@ export interface TestContractParams<F extends Fields = Fields, A extends Argumen
204
207
  blockTimeStamp?: number;
205
208
  txId?: string;
206
209
  initialFields: F;
210
+ initialMaps?: M;
207
211
  initialAsset?: Asset;
208
212
  testArgs: A;
209
213
  existingContracts?: ContractState[];
@@ -218,11 +222,13 @@ export interface ContractEvent<T extends Fields = Fields> {
218
222
  fields: T;
219
223
  }
220
224
  export type DebugMessage = node.DebugMessage;
221
- export interface TestContractResult<R> {
225
+ export type TestContractResultWithoutMaps<R> = Omit<TestContractResult<R>, 'maps'>;
226
+ export interface TestContractResult<R, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>> {
222
227
  contractId: string;
223
228
  contractAddress: string;
224
229
  returns: R;
225
230
  gasUsed: number;
231
+ maps?: M;
226
232
  contracts: ContractState[];
227
233
  txOutputs: Output[];
228
234
  events: ContractEvent[];
@@ -315,7 +321,7 @@ export declare function subscribeEventsFromContract<T extends Fields, M extends
315
321
  export declare function addStdIdToFields<F extends Fields>(contract: Contract, fields: F): F | (F & {
316
322
  __stdInterfaceId: HexString;
317
323
  });
318
- export declare function testMethod<I extends ContractInstance, F extends Fields, A extends Arguments, R>(contract: ContractFactory<I, F>, methodName: string, params: Optional<TestContractParams<F, A>, 'testArgs' | 'initialFields'>): Promise<TestContractResult<R>>;
324
+ export declare function testMethod<I extends ContractInstance, F extends Fields, A extends Arguments, R, M extends Record<string, Map<Val, Val>> = Record<string, Map<Val, Val>>>(factory: ContractFactory<I, F>, methodName: string, params: Optional<TestContractParams<F, A, M>, 'testArgs' | 'initialFields'>): Promise<TestContractResult<R, M>>;
319
325
  export declare abstract class ContractInstance {
320
326
  readonly address: Address;
321
327
  readonly contractId: string;
@@ -57,6 +57,7 @@ const constants_1 = require("../constants");
57
57
  const blake = __importStar(require("blakejs"));
58
58
  const error_1 = require("../utils/error");
59
59
  const debug_1 = require("../debug");
60
+ const codec_1 = require("../codec");
60
61
  const crypto = new utils_1.WebCrypto();
61
62
  exports.StdIdFieldName = '__stdInterfaceId';
62
63
  var SourceKind;
@@ -610,7 +611,7 @@ class Artifact {
610
611
  }
611
612
  exports.Artifact = Artifact;
612
613
  class Contract extends Artifact {
613
- constructor(version, name, bytecode, bytecodeDebugPatch, codeHash, codeHashDebug, fieldsSig, eventsSig, functions, constants, enums, structs, stdInterfaceId) {
614
+ constructor(version, name, bytecode, bytecodeDebugPatch, codeHash, codeHashDebug, fieldsSig, eventsSig, functions, constants, enums, structs, mapsSig, stdInterfaceId) {
614
615
  super(version, name, functions);
615
616
  this.bytecode = bytecode;
616
617
  this.bytecodeDebugPatch = bytecodeDebugPatch;
@@ -620,6 +621,7 @@ class Contract extends Artifact {
620
621
  this.constants = constants;
621
622
  this.enums = enums;
622
623
  this.structs = structs;
624
+ this.mapsSig = mapsSig;
623
625
  this.stdInterfaceId = stdInterfaceId;
624
626
  this.bytecodeDebug = ralph.buildDebugBytecode(this.bytecode, this.bytecodeDebugPatch);
625
627
  this.codeHashDebug = codeHashDebug;
@@ -637,11 +639,11 @@ class Contract extends Artifact {
637
639
  artifact.functions == null) {
638
640
  throw Error('The artifact JSON for contract is incomplete');
639
641
  }
640
- const contract = new Contract(artifact.version, artifact.name, artifact.bytecode, bytecodeDebugPatch, artifact.codeHash, codeHashDebug ? codeHashDebug : artifact.codeHash, artifact.fieldsSig, artifact.eventsSig, artifact.functions, artifact.constants, artifact.enums, structs, artifact.stdInterfaceId === null ? undefined : artifact.stdInterfaceId);
642
+ const contract = new Contract(artifact.version, artifact.name, artifact.bytecode, bytecodeDebugPatch, artifact.codeHash, codeHashDebug ? codeHashDebug : artifact.codeHash, artifact.fieldsSig, artifact.eventsSig, artifact.functions, artifact.constants, artifact.enums, structs, artifact.mapsSig === null ? undefined : artifact.mapsSig, artifact.stdInterfaceId === null ? undefined : artifact.stdInterfaceId);
641
643
  return contract;
642
644
  }
643
645
  static fromCompileResult(result, structs = []) {
644
- return new Contract(result.version, result.name, result.bytecode, result.bytecodeDebugPatch, result.codeHash, result.codeHashDebug, result.fields, result.events, result.functions, result.constants, result.enums, structs, result.stdInterfaceId);
646
+ return new Contract(result.version, result.name, result.bytecode, result.bytecodeDebugPatch, result.codeHash, result.codeHashDebug, result.fields, result.events, result.functions, result.constants, result.enums, structs, result.maps, result.stdInterfaceId);
645
647
  }
646
648
  // support both 'code.ral' and 'code.ral.json'
647
649
  static async fromArtifactFile(path, bytecodeDebugPatch, codeHashDebug, structs = []) {
@@ -661,6 +663,9 @@ class Contract extends Artifact {
661
663
  constants: this.constants,
662
664
  enums: this.enums
663
665
  };
666
+ if (this.mapsSig !== undefined) {
667
+ object.mapsSig = this.mapsSig;
668
+ }
664
669
  if (this.stdInterfaceId !== undefined) {
665
670
  object.stdInterfaceId = this.stdInterfaceId;
666
671
  }
@@ -1200,21 +1205,189 @@ function addStdIdToFields(contract, fields) {
1200
1205
  : { ...fields, __stdInterfaceId: stdInterfaceIdPrefix + contract.stdInterfaceId };
1201
1206
  }
1202
1207
  exports.addStdIdToFields = addStdIdToFields;
1203
- async function testMethod(contract, methodName, params) {
1208
+ function calcWrapperContractId(parentContractId, mapIndex, key, keyType, group) {
1209
+ const prefix = ralph.encodeMapPrefix(mapIndex);
1210
+ const encodedKey = ralph.primitiveToByteVec(key, keyType);
1211
+ const path = (0, utils_1.binToHex)(prefix) + (0, utils_1.binToHex)(encodedKey);
1212
+ return (0, utils_1.subContractId)(parentContractId, path, group);
1213
+ }
1214
+ function genCodeForType(type, structs) {
1215
+ const { immFields, mutFields } = ralph.calcFieldSize(type, true, structs);
1216
+ const loadImmFieldByIndex = {
1217
+ isPublic: true,
1218
+ assetModifier: 0,
1219
+ argsLength: 1,
1220
+ localsLength: 1,
1221
+ returnLength: 1,
1222
+ instrs: [(0, codec_1.LoadLocal)(0), codec_1.LoadImmFieldByIndex]
1223
+ };
1224
+ const loadMutFieldByIndex = {
1225
+ ...loadImmFieldByIndex,
1226
+ instrs: [(0, codec_1.LoadLocal)(0), codec_1.LoadMutFieldByIndex]
1227
+ };
1228
+ const parentContractIdIndex = immFields;
1229
+ const storeMutFieldByIndex = {
1230
+ ...loadImmFieldByIndex,
1231
+ argsLength: 2,
1232
+ localsLength: 2,
1233
+ returnLength: 0,
1234
+ instrs: [
1235
+ codec_1.CallerContractId,
1236
+ (0, codec_1.LoadImmField)(parentContractIdIndex),
1237
+ codec_1.ByteVecEq,
1238
+ codec_1.Assert,
1239
+ (0, codec_1.LoadLocal)(0),
1240
+ (0, codec_1.LoadLocal)(1),
1241
+ codec_1.StoreMutFieldByIndex
1242
+ ]
1243
+ };
1244
+ const destroy = {
1245
+ isPublic: true,
1246
+ assetModifier: 2,
1247
+ argsLength: 1,
1248
+ localsLength: 1,
1249
+ returnLength: 0,
1250
+ instrs: [codec_1.CallerContractId, (0, codec_1.LoadImmField)(parentContractIdIndex), codec_1.ByteVecEq, codec_1.Assert, (0, codec_1.LoadLocal)(0), codec_1.DestroySelf]
1251
+ };
1252
+ const c = {
1253
+ fieldLength: immFields + mutFields + 1,
1254
+ methods: [loadImmFieldByIndex, loadMutFieldByIndex, storeMutFieldByIndex, destroy]
1255
+ };
1256
+ const bytecode = codec_1.contract.contractCodec.encode(codec_1.contract.toHalfDecoded(c));
1257
+ const codeHash = blake.blake2b(bytecode, undefined, 32);
1258
+ return { bytecode: (0, utils_1.binToHex)(bytecode), codeHash: (0, utils_1.binToHex)(codeHash) };
1259
+ }
1260
+ function getContractFieldsSig(mapValueType) {
1261
+ return {
1262
+ names: ['value', 'parentContractId'],
1263
+ types: [mapValueType, 'ByteVec'],
1264
+ isMutable: [true, false]
1265
+ };
1266
+ }
1267
+ function mapToExistingContracts(contract, parentContractId, group, map, mapIndex, type) {
1268
+ const [keyType, valueType] = ralph.parseMapType(type);
1269
+ const generatedContract = genCodeForType(valueType, contract.structs);
1270
+ return Array.from(map.entries()).map(([key, value]) => {
1271
+ const fields = { value, parentContractId };
1272
+ const contractId = calcWrapperContractId(parentContractId, mapIndex, key, keyType, group);
1273
+ return {
1274
+ ...generatedContract,
1275
+ address: (0, utils_1.addressFromContractId)(contractId),
1276
+ contractId: contractId,
1277
+ fieldsSig: getContractFieldsSig(valueType),
1278
+ fields,
1279
+ asset: { alphAmount: constants_1.ONE_ALPH }
1280
+ };
1281
+ });
1282
+ }
1283
+ function mapsToExistingContracts(contract, parentContractId, group, initialMaps) {
1284
+ const mapsSig = contract.mapsSig;
1285
+ if (mapsSig === undefined)
1286
+ return [];
1287
+ const contractStates = [];
1288
+ Object.keys(initialMaps).forEach((name) => {
1289
+ const index = mapsSig.names.findIndex((n) => n === name);
1290
+ if (index === -1)
1291
+ throw new Error(`Map var ${name} does not exist in contract ${contract.name}`);
1292
+ const mapType = mapsSig.types[`${index}`];
1293
+ const states = mapToExistingContracts(contract, parentContractId, group, initialMaps[`${name}`], index, mapType);
1294
+ contractStates.push(...states);
1295
+ });
1296
+ return contractStates;
1297
+ }
1298
+ async function testMethod(factory, methodName, params) {
1204
1299
  const txId = params?.txId ?? randomTxId();
1205
- const initialFields = params.initialFields === undefined ? {} : params.initialFields;
1206
- const apiParams = contract.contract.toApiTestContractParams(methodName, {
1300
+ const contract = factory.contract;
1301
+ const address = params.address ?? (0, utils_1.addressFromContractId)((0, utils_1.binToHex)(crypto.getRandomValues(new Uint8Array(32))));
1302
+ const contractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
1303
+ const group = params.group ?? 0;
1304
+ const initialMaps = params.initialMaps ?? {};
1305
+ const contractStates = mapsToExistingContracts(contract, contractId, group, initialMaps);
1306
+ const apiParams = contract.toApiTestContractParams(methodName, {
1207
1307
  ...params,
1308
+ address,
1208
1309
  txId: txId,
1209
- initialFields: addStdIdToFields(contract.contract, initialFields),
1210
- testArgs: params.testArgs === undefined ? {} : params.testArgs
1310
+ initialFields: addStdIdToFields(contract, params.initialFields ?? {}),
1311
+ testArgs: params.testArgs === undefined ? {} : params.testArgs,
1312
+ existingContracts: (params.existingContracts ?? []).concat(contractStates)
1211
1313
  });
1212
1314
  const apiResult = await (0, global_1.getCurrentNodeProvider)().contracts.postContractsTestContract(apiParams);
1213
- const testResult = contract.contract.fromApiTestContractResult(methodName, apiResult, txId);
1214
- contract.contract.printDebugMessages(methodName, testResult.debugMessages);
1215
- return testResult;
1315
+ const maps = existingContractsToMaps(contract, address, group, apiResult, initialMaps);
1316
+ const testResult = contract.fromApiTestContractResult(methodName, apiResult, txId);
1317
+ contract.printDebugMessages(methodName, testResult.debugMessages);
1318
+ return {
1319
+ ...testResult,
1320
+ maps
1321
+ };
1216
1322
  }
1217
1323
  exports.testMethod = testMethod;
1324
+ function buildMapInfo(contract, fields) {
1325
+ const mapsSig = contract.mapsSig;
1326
+ if (mapsSig === undefined)
1327
+ return [];
1328
+ return mapsSig.names.map((name, index) => {
1329
+ const mapType = mapsSig.types[`${index}`];
1330
+ const value = (fields[`${name}`] ?? new Map());
1331
+ const [keyType, valueType] = ralph.parseMapType(mapType);
1332
+ return { name, value, keyType, valueType, index };
1333
+ });
1334
+ }
1335
+ function extractFromEventLog(contract, result, allMaps, address, group) {
1336
+ const parentContractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
1337
+ const newInserted = [];
1338
+ result.debugMessages.forEach((message) => {
1339
+ if (message.contractAddress !== address)
1340
+ return;
1341
+ const decoded = ralph.tryDecodeMapDebugLog(message.message);
1342
+ if (decoded === undefined)
1343
+ return;
1344
+ const map = allMaps[`${decoded.mapIndex}`];
1345
+ const decodedKey = ralph.decodePrimitive(decoded.encodedKey, map.keyType);
1346
+ const contractId = (0, utils_1.subContractId)(parentContractId, decoded.path, group);
1347
+ if (!decoded.isInsert) {
1348
+ map.value.delete(decodedKey);
1349
+ return;
1350
+ }
1351
+ const state = result.contracts.find((s) => s.address === (0, utils_1.addressFromContractId)(contractId));
1352
+ if (state === undefined) {
1353
+ throw new Error(`Cannot find contract state for map value, map field: ${map.name}, value type: ${map.valueType}`);
1354
+ }
1355
+ newInserted.push(state.address);
1356
+ const fieldsSig = getContractFieldsSig(map.valueType);
1357
+ const fields = fromApiFields(state.immFields, state.mutFields, fieldsSig, contract.structs);
1358
+ map.value.set(decodedKey, fields['value']);
1359
+ });
1360
+ return newInserted;
1361
+ }
1362
+ function updateMaps(contract, result, allMaps, address, group) {
1363
+ const parentContractId = (0, utils_1.binToHex)((0, utils_1.contractIdFromAddress)(address));
1364
+ const updated = [];
1365
+ allMaps.forEach((map) => {
1366
+ Array.from(map.value.keys()).forEach((key) => {
1367
+ const contractId = calcWrapperContractId(parentContractId, map.index, key, map.keyType, group);
1368
+ const updatedState = result.contracts.find((s) => s.address === (0, utils_1.addressFromContractId)(contractId));
1369
+ if (updatedState === undefined)
1370
+ return;
1371
+ updated.push(updatedState.address);
1372
+ const fieldsSig = getContractFieldsSig(map.valueType);
1373
+ const fields = fromApiFields(updatedState.immFields, updatedState.mutFields, fieldsSig, contract.structs);
1374
+ map.value.set(key, fields['value']);
1375
+ });
1376
+ });
1377
+ return updated;
1378
+ }
1379
+ function existingContractsToMaps(contract, address, group, result, maps) {
1380
+ const allMaps = buildMapInfo(contract, maps);
1381
+ const updated = updateMaps(contract, result, allMaps, address, group);
1382
+ const newInserted = extractFromEventLog(contract, result, allMaps, address, group);
1383
+ const mapEntries = updated.concat(newInserted);
1384
+ const remainContracts = result.contracts.filter((c) => mapEntries.find((addr) => c.address === addr) === undefined);
1385
+ result.contracts = remainContracts;
1386
+ return allMaps.reduce((acc, map) => {
1387
+ acc[`${map.name}`] = map.value;
1388
+ return acc;
1389
+ }, {});
1390
+ }
1218
1391
  class ContractInstance {
1219
1392
  constructor(address) {
1220
1393
  this.address = address;
@@ -1,6 +1,7 @@
1
1
  import { Val } from '../api';
2
2
  import { Fields, FieldsSig, Struct } from './contract';
3
3
  export declare function encodeBool(bool: boolean): Uint8Array;
4
+ export declare function decodeBool(bytes: Uint8Array): boolean;
4
5
  export declare function encodeI256(i256: bigint): Uint8Array;
5
6
  export declare function encodeU256(u256: bigint): Uint8Array;
6
7
  export declare function encodeByteVec(bytes: string): Uint8Array;
@@ -19,6 +20,21 @@ export declare function encodeVmByteVec(bytes: string): Uint8Array;
19
20
  export declare function encodeVmAddress(address: string): Uint8Array;
20
21
  export declare function encodeScriptFieldAsString(tpe: string, value: Val): string;
21
22
  export declare function encodeScriptField(tpe: string, value: Val): Uint8Array;
23
+ export declare function splitFields(fieldsSig: FieldsSig): [FieldsSig, FieldsSig];
24
+ export declare function parseMapType(type: string): [string, string];
25
+ export declare function encodeMapPrefix(mapIndex: number): Uint8Array;
26
+ export declare function calcFieldSize(type: string, isMutable: boolean, structs: Struct[]): {
27
+ immFields: number;
28
+ mutFields: number;
29
+ };
30
+ export declare function tryDecodeMapDebugLog(message: string): {
31
+ path: string;
32
+ mapIndex: number;
33
+ encodedKey: Uint8Array;
34
+ isInsert: boolean;
35
+ } | undefined;
36
+ export declare function decodePrimitive(value: Uint8Array, type: string): Val;
37
+ export declare function primitiveToByteVec(value: Val, type: string): Uint8Array;
22
38
  export declare function flattenFields(fields: Fields, names: string[], types: string[], isMutable: boolean[], structs: Struct[]): {
23
39
  name: string;
24
40
  type: string;