@alephium/web3 1.3.0 → 1.5.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.
Files changed (107) 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/address/address.js +11 -5
  4. package/dist/src/api/api-alephium.d.ts +2 -4
  5. package/dist/src/api/api-alephium.js +1 -1
  6. package/dist/src/codec/array-codec.d.ts +4 -12
  7. package/dist/src/codec/array-codec.js +15 -28
  8. package/dist/src/codec/asset-output-codec.d.ts +6 -11
  9. package/dist/src/codec/asset-output-codec.js +32 -71
  10. package/dist/src/codec/bigint-codec.d.ts +2 -1
  11. package/dist/src/codec/bigint-codec.js +14 -2
  12. package/dist/src/codec/bytestring-codec.d.ts +6 -11
  13. package/dist/src/codec/bytestring-codec.js +9 -23
  14. package/dist/src/codec/codec.d.ts +54 -5
  15. package/dist/src/codec/codec.js +112 -14
  16. package/dist/src/codec/compact-int-codec.d.ts +65 -44
  17. package/dist/src/codec/compact-int-codec.js +222 -204
  18. package/dist/src/codec/contract-codec.d.ts +5 -8
  19. package/dist/src/codec/contract-codec.js +15 -29
  20. package/dist/src/codec/contract-output-codec.d.ts +4 -10
  21. package/dist/src/codec/contract-output-codec.js +20 -40
  22. package/dist/src/codec/contract-output-ref-codec.d.ts +2 -8
  23. package/dist/src/codec/contract-output-ref-codec.js +7 -17
  24. package/dist/src/codec/either-codec.d.ts +8 -15
  25. package/dist/src/codec/either-codec.js +5 -46
  26. package/dist/src/codec/index.d.ts +4 -3
  27. package/dist/src/codec/index.js +7 -4
  28. package/dist/src/codec/input-codec.d.ts +4 -10
  29. package/dist/src/codec/input-codec.js +11 -46
  30. package/dist/src/codec/instr-codec.d.ts +633 -40
  31. package/dist/src/codec/instr-codec.js +1040 -434
  32. package/dist/src/codec/int-as-4bytes-codec.d.ts +7 -0
  33. package/dist/src/codec/{signed-int-codec.js → int-as-4bytes-codec.js} +6 -12
  34. package/dist/src/codec/lockup-script-codec.d.ts +23 -26
  35. package/dist/src/codec/lockup-script-codec.js +12 -58
  36. package/dist/src/codec/method-codec.d.ts +6 -18
  37. package/dist/src/codec/method-codec.js +20 -48
  38. package/dist/src/codec/option-codec.d.ts +8 -13
  39. package/dist/src/codec/option-codec.js +14 -32
  40. package/dist/src/codec/output-codec.d.ts +2 -2
  41. package/dist/src/codec/output-codec.js +1 -1
  42. package/dist/src/codec/reader.d.ts +8 -0
  43. package/dist/src/codec/reader.js +48 -0
  44. package/dist/src/codec/script-codec.d.ts +6 -14
  45. package/dist/src/codec/script-codec.js +6 -22
  46. package/dist/src/codec/signature-codec.d.ts +4 -12
  47. package/dist/src/codec/signature-codec.js +3 -15
  48. package/dist/src/codec/timestamp-codec.d.ts +8 -0
  49. package/dist/src/codec/timestamp-codec.js +39 -0
  50. package/dist/src/codec/token-codec.d.ts +3 -10
  51. package/dist/src/codec/token-codec.js +6 -24
  52. package/dist/src/codec/transaction-codec.d.ts +6 -11
  53. package/dist/src/codec/transaction-codec.js +24 -49
  54. package/dist/src/codec/unlock-script-codec.d.ts +25 -36
  55. package/dist/src/codec/unlock-script-codec.js +26 -147
  56. package/dist/src/codec/unsigned-tx-codec.d.ts +8 -14
  57. package/dist/src/codec/unsigned-tx-codec.js +24 -66
  58. package/dist/src/codec/val.d.ts +27 -0
  59. package/dist/src/codec/val.js +33 -0
  60. package/dist/src/contract/contract.d.ts +1 -0
  61. package/dist/src/contract/contract.js +20 -13
  62. package/dist/src/contract/index.d.ts +1 -0
  63. package/dist/src/contract/index.js +1 -0
  64. package/dist/src/contract/ralph.d.ts +0 -4
  65. package/dist/src/contract/ralph.js +50 -179
  66. package/dist/src/contract/script-simulator.d.ts +27 -0
  67. package/dist/src/contract/script-simulator.js +757 -0
  68. package/dist/src/exchange/exchange.js +1 -1
  69. package/package.json +3 -4
  70. package/src/address/address.ts +15 -9
  71. package/src/api/api-alephium.ts +2 -4
  72. package/src/codec/array-codec.ts +16 -34
  73. package/src/codec/asset-output-codec.ts +38 -83
  74. package/src/codec/bigint-codec.ts +16 -2
  75. package/src/codec/bytestring-codec.ts +10 -28
  76. package/src/codec/codec.ts +121 -15
  77. package/src/codec/compact-int-codec.ts +230 -207
  78. package/src/codec/contract-codec.ts +20 -33
  79. package/src/codec/contract-output-codec.ts +22 -48
  80. package/src/codec/contract-output-ref-codec.ts +6 -17
  81. package/src/codec/either-codec.ts +4 -53
  82. package/src/codec/index.ts +4 -3
  83. package/src/codec/input-codec.ts +14 -36
  84. package/src/codec/instr-codec.ts +1229 -455
  85. package/src/codec/{signed-int-codec.ts → int-as-4bytes-codec.ts} +6 -10
  86. package/src/codec/lockup-script-codec.ts +28 -76
  87. package/src/codec/method-codec.ts +23 -61
  88. package/src/codec/option-codec.ts +13 -36
  89. package/src/codec/output-codec.ts +2 -2
  90. package/src/codec/reader.ts +56 -0
  91. package/src/codec/script-codec.ts +9 -31
  92. package/src/codec/signature-codec.ts +3 -18
  93. package/src/codec/timestamp-codec.ts +42 -0
  94. package/src/codec/token-codec.ts +7 -26
  95. package/src/codec/transaction-codec.ts +29 -58
  96. package/src/codec/unlock-script-codec.ts +44 -171
  97. package/src/codec/unsigned-tx-codec.ts +34 -63
  98. package/src/codec/val.ts +40 -0
  99. package/src/contract/contract.ts +24 -20
  100. package/src/contract/index.ts +1 -0
  101. package/src/contract/ralph.ts +76 -172
  102. package/src/contract/script-simulator.ts +838 -0
  103. package/src/exchange/exchange.ts +1 -1
  104. package/dist/src/codec/long-codec.d.ts +0 -8
  105. package/dist/src/codec/long-codec.js +0 -55
  106. package/dist/src/codec/signed-int-codec.d.ts +0 -8
  107. package/src/codec/long-codec.ts +0 -58
@@ -15,75 +15,67 @@ GNU Lesser General Public License for more details.
15
15
  You should have received a copy of the GNU Lesser General Public License
16
16
  along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
- import { Parser } from 'binary-parser'
19
18
  import { Codec, assert } from './codec'
20
19
  import { BigIntCodec } from './bigint-codec'
21
- import { binToHex } from '../utils'
22
-
23
- export class CompactInt {
24
- static readonly oneBytePrefix = 0x00
25
- static readonly oneByteNegPrefix = 0xc0
26
- static readonly twoBytePrefix = 0x40
27
- static readonly twoByteNegPrefix = 0x80
28
- static readonly fourBytePrefix = 0x80
29
- static readonly fourByteNegPrefix = 0x40
30
- static readonly multiBytePrefix = 0xc0
31
- }
20
+ import { Reader } from './reader'
32
21
 
33
22
  const maskRest = 0xc0
34
23
  const maskMode = 0x3f
35
24
  const maskModeNeg = 0xffffffc0
36
- const signFlag = 0x20 // 0b00100000
37
25
 
38
- export interface DecodedCompactInt {
39
- mode: number
40
- rest: Uint8Array
26
+ type FixedWidthMode = {
27
+ type: 'SingleByte' | 'TwoByte' | 'FourByte'
28
+ prefix: number
29
+ negPrefix: number
41
30
  }
42
-
43
- const compactIntParser = new Parser().uint8('mode').buffer('rest', {
44
- length: function (ctx) {
45
- const rawMode = this['mode']
46
- const mode = rawMode & maskRest
47
-
48
- switch (mode) {
49
- case CompactInt.oneBytePrefix:
50
- return 0
51
- case CompactInt.twoBytePrefix:
52
- return 1
53
- case CompactInt.fourBytePrefix:
54
- return 3
55
- default:
56
- return (rawMode & maskMode) + 4
31
+ type MultiByteMode = { type: 'MultiByte'; prefix: number }
32
+ type Mode = FixedWidthMode | MultiByteMode
33
+
34
+ const SingleByteMode: FixedWidthMode = { type: 'SingleByte', prefix: 0x00, negPrefix: 0xc0 }
35
+ const TwoByteMode: FixedWidthMode = { type: 'TwoByte', prefix: 0x40, negPrefix: 0x80 }
36
+ const FourByteMode: FixedWidthMode = { type: 'FourByte', prefix: 0x80, negPrefix: 0x40 }
37
+ const MultiByte: MultiByteMode = { type: 'MultiByte', prefix: 0xc0 }
38
+
39
+ function decodeMode(input: Reader): { mode: Mode; body: Uint8Array } {
40
+ const byte = input.consumeByte()
41
+ switch (byte & maskRest) {
42
+ case SingleByteMode.prefix:
43
+ return { mode: SingleByteMode, body: new Uint8Array([byte]) }
44
+ case TwoByteMode.prefix:
45
+ return { mode: TwoByteMode, body: new Uint8Array([byte, ...input.consumeBytes(1)]) }
46
+ case FourByteMode.prefix:
47
+ return { mode: FourByteMode, body: new Uint8Array([byte, ...input.consumeBytes(3)]) }
48
+ default: {
49
+ const length = (byte & maskMode) + 4
50
+ return { mode: MultiByte, body: new Uint8Array([byte, ...input.consumeBytes(length)]) }
57
51
  }
58
52
  }
59
- })
60
-
61
- export class CompactUnsignedIntCodec implements Codec<DecodedCompactInt> {
62
- private oneByteBound = 0x40
63
- private twoByteBound = this.oneByteBound << 8
64
- private fourByteBound = this.oneByteBound << (8 * 3)
65
-
66
- parser = compactIntParser
67
-
68
- encode(input: DecodedCompactInt): Uint8Array {
69
- return new Uint8Array([input.mode, ...input.rest])
70
- }
53
+ }
71
54
 
72
- encodeU32(value: number): Uint8Array {
73
- if (value < this.oneByteBound) {
74
- return new Uint8Array([(CompactInt.oneBytePrefix + value) & 0xff])
75
- } else if (value < this.twoByteBound) {
76
- return new Uint8Array([(CompactInt.twoBytePrefix + (value >> 8)) & 0xff, value & 0xff])
77
- } else if (value < this.fourByteBound) {
55
+ export class UnSigned {
56
+ static readonly oneByteBound = BigInt(0x40)
57
+ static readonly twoByteBound = UnSigned.oneByteBound << BigInt(8)
58
+ static readonly fourByteBound = UnSigned.oneByteBound << BigInt(8 * 3)
59
+ static readonly u256UpperBound = BigInt(1) << BigInt(256)
60
+ static readonly u32UpperBound = 2 ** 32
61
+
62
+ static encodeU32(value: number): Uint8Array {
63
+ assert(value >= 0 && value < UnSigned.u32UpperBound, `Invalid u32 value: ${value}`)
64
+
65
+ if (value < UnSigned.oneByteBound) {
66
+ return new Uint8Array([(SingleByteMode.prefix + value) & 0xff])
67
+ } else if (value < UnSigned.twoByteBound) {
68
+ return new Uint8Array([(TwoByteMode.prefix + (value >> 8)) & 0xff, value & 0xff])
69
+ } else if (value < UnSigned.fourByteBound) {
78
70
  return new Uint8Array([
79
- (CompactInt.fourBytePrefix + (value >> 24)) & 0xff,
71
+ (FourByteMode.prefix + (value >> 24)) & 0xff,
80
72
  (value >> 16) & 0xff,
81
73
  (value >> 8) & 0xff,
82
74
  value & 0xff
83
75
  ])
84
76
  } else {
85
77
  return new Uint8Array([
86
- CompactInt.multiBytePrefix,
78
+ MultiByte.prefix,
87
79
  (value >> 24) & 0xff,
88
80
  (value >> 16) & 0xff,
89
81
  (value >> 8) & 0xff,
@@ -92,211 +84,242 @@ export class CompactUnsignedIntCodec implements Codec<DecodedCompactInt> {
92
84
  }
93
85
  }
94
86
 
95
- encodeU256(value: bigint): Uint8Array {
96
- assert(value >= 0n, 'Value should be positive')
87
+ static encodeU256(value: bigint): Uint8Array {
88
+ assert(value >= 0n && value < UnSigned.u256UpperBound, `Invalid u256 value: ${value}`)
97
89
 
98
- if (value < this.fourByteBound) {
99
- return this.encodeU32(Number(value))
90
+ if (value < UnSigned.fourByteBound) {
91
+ return UnSigned.encodeU32(Number(value))
100
92
  } else {
101
93
  let bytes = BigIntCodec.encode(value)
102
94
  if (bytes[0] === 0) {
103
95
  bytes = bytes.slice(1)
104
96
  }
105
97
 
106
- assert(bytes.length <= 32, 'Expect <= 32 bytes for U256')
107
-
108
- const header = (bytes.length - 4 + CompactInt.multiBytePrefix) & 0xff
98
+ const header = (bytes.length - 4 + MultiByte.prefix) & 0xff
109
99
  return new Uint8Array([header, ...bytes])
110
100
  }
111
101
  }
112
102
 
113
- decodeU256(input: Uint8Array): bigint {
114
- const decoded = this.decode(input)
115
- return this.toU256(decoded)
116
- }
117
-
118
- decode(input: Uint8Array): DecodedCompactInt {
119
- return this.parser.parse(input)
103
+ static decodeInt(mode: FixedWidthMode, body: Uint8Array): number {
104
+ switch (mode.type) {
105
+ case 'SingleByte':
106
+ assert(body.length === 1, 'Length should be 2')
107
+ return body[0]
108
+ case 'TwoByte':
109
+ assert(body.length === 2, 'Length should be 2')
110
+ return ((body[0] & maskMode) << 8) | (body[1] & 0xff)
111
+ case 'FourByte':
112
+ assert(body.length === 4, 'Length should be 4')
113
+ return (
114
+ (((body[0] & maskMode) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)) >>> 0
115
+ )
116
+ }
120
117
  }
121
118
 
122
- toU256(value: DecodedCompactInt): bigint {
123
- const mode = value.mode & maskRest
124
- if (fixedSize(mode)) {
125
- const body = new Uint8Array([value.mode, ...value.rest])
126
- return BigInt(decodePositiveInt(value.mode, body))
127
- } else {
128
- assert(value.rest.length <= 32, 'Expect <= 32 bytes for U256')
129
- return BigIntCodec.decode(value.rest, false)
119
+ static decodeU32(mode: Mode, body: Uint8Array): number {
120
+ switch (mode.type) {
121
+ case 'SingleByte':
122
+ case 'TwoByte':
123
+ case 'FourByte':
124
+ return UnSigned.decodeInt(mode, body)
125
+ case 'MultiByte':
126
+ assert(body.length >= 5, 'Length should be greater than 5')
127
+ if (body.length === 5) {
128
+ return ((body[1] << 24) | ((body[2] & 0xff) << 16) | ((body[3] & 0xff) << 8) | (body[4] & 0xff)) >>> 0
129
+ } else {
130
+ throw new Error(`Expect 4 bytes int, but get ${body.length - 1} bytes int`)
131
+ }
130
132
  }
131
133
  }
132
134
 
133
- fromU256(value: bigint): DecodedCompactInt {
134
- return this.decode(this.encodeU256(value))
135
+ static decodeU256(mode: Mode, body: Uint8Array): bigint {
136
+ switch (mode.type) {
137
+ case 'SingleByte':
138
+ case 'TwoByte':
139
+ case 'FourByte':
140
+ return BigInt(UnSigned.decodeInt(mode, body))
141
+ case 'MultiByte':
142
+ return BigIntCodec.decodeUnsigned(body.slice(1, body.length))
143
+ }
135
144
  }
136
145
  }
137
146
 
138
- export const compactUnsignedIntCodec = new CompactUnsignedIntCodec()
139
-
140
- export class CompactSignedIntCodec implements Codec<DecodedCompactInt> {
141
- private signFlag = 0x20 // 0b00100000
142
- private oneByteBound = 0x20 // 0b00100000
143
- private twoByteBound = this.oneByteBound << 8
144
- private fourByteBound = this.oneByteBound << (8 * 3)
145
-
146
- parser = compactIntParser
147
-
148
- encode(input: DecodedCompactInt): Uint8Array {
149
- return new Uint8Array([input.mode, ...input.rest])
147
+ export const u256Codec = new (class extends Codec<bigint> {
148
+ encode(input: bigint): Uint8Array {
149
+ return UnSigned.encodeU256(input)
150
+ }
151
+ _decode(input: Reader): bigint {
152
+ const { mode, body } = decodeMode(input)
153
+ return UnSigned.decodeU256(mode, body)
150
154
  }
155
+ })()
151
156
 
152
- decode(input: Uint8Array): DecodedCompactInt {
153
- return this.parser.parse(input)
157
+ export const u32Codec = new (class extends Codec<number> {
158
+ encode(input: number): Uint8Array {
159
+ return UnSigned.encodeU32(input)
160
+ }
161
+ _decode(input: Reader): number {
162
+ const { mode, body } = decodeMode(input)
163
+ return UnSigned.decodeU32(mode, body)
164
+ }
165
+ })()
166
+
167
+ export class Signed {
168
+ static readonly signFlag = 0x20 // 0b00100000
169
+ static readonly oneByteBound = BigInt(0x20)
170
+ static readonly twoByteBound = Signed.oneByteBound << BigInt(8)
171
+ static readonly fourByteBound = Signed.oneByteBound << BigInt(8 * 3)
172
+ static readonly i256UpperBound = BigInt(1) << BigInt(255)
173
+ static readonly i256LowerBound = -Signed.i256UpperBound
174
+ static readonly i32UpperBound = 2 ** 31
175
+ static readonly i32LowerBound = -Signed.i32UpperBound
176
+
177
+ static encodeI32(value: number): Uint8Array {
178
+ assert(value >= Signed.i32LowerBound && value < Signed.i32UpperBound, `Invalid i32 value: ${value}`)
179
+ if (value >= 0) {
180
+ return Signed.encodePositiveI32(value)
181
+ } else {
182
+ return Signed.encodeNegativeI32(value)
183
+ }
154
184
  }
155
185
 
156
- decodeI32(input: Uint8Array): number {
157
- const decoded = this.decode(input)
158
- return this.toI32(decoded)
186
+ static encodePositiveI32(value: number): Uint8Array {
187
+ if (value < this.oneByteBound) {
188
+ return new Uint8Array([(SingleByteMode.prefix + value) & 0xff])
189
+ } else if (value < this.twoByteBound) {
190
+ return new Uint8Array([(TwoByteMode.prefix + (value >> 8)) & 0xff, value & 0xff])
191
+ } else if (value < this.fourByteBound) {
192
+ return new Uint8Array([
193
+ (FourByteMode.prefix + (value >> 24)) & 0xff,
194
+ (value >> 16) & 0xff,
195
+ (value >> 8) & 0xff,
196
+ value & 0xff
197
+ ])
198
+ } else {
199
+ return new Uint8Array([
200
+ MultiByte.prefix,
201
+ (value >> 24) & 0xff,
202
+ (value >> 16) & 0xff,
203
+ (value >> 8) & 0xff,
204
+ value & 0xff
205
+ ])
206
+ }
159
207
  }
160
208
 
161
- encodeI32(value: number): Uint8Array {
162
- if (value >= 0) {
163
- if (value < this.oneByteBound) {
164
- return new Uint8Array([(CompactInt.oneBytePrefix + value) & 0xff])
165
- } else if (value < this.twoByteBound) {
166
- return new Uint8Array([(CompactInt.twoBytePrefix + (value >> 8)) & 0xff, value & 0xff])
167
- } else if (value < this.fourByteBound) {
168
- return new Uint8Array([
169
- (CompactInt.fourBytePrefix + (value >> 24)) & 0xff,
170
- (value >> 16) & 0xff,
171
- (value >> 8) & 0xff,
172
- value & 0xff
173
- ])
174
- } else {
175
- return new Uint8Array([
176
- CompactInt.multiBytePrefix,
177
- (value >> 24) & 0xff,
178
- (value >> 16) & 0xff,
179
- (value >> 8) & 0xff,
180
- value & 0xff
181
- ])
182
- }
209
+ static encodeNegativeI32(value: number): Uint8Array {
210
+ if (value >= -this.oneByteBound) {
211
+ return new Uint8Array([(value ^ SingleByteMode.negPrefix) & 0xff])
212
+ } else if (value >= -this.twoByteBound) {
213
+ return new Uint8Array([((value >> 8) ^ TwoByteMode.negPrefix) & 0xff, value & 0xff])
214
+ } else if (value >= -this.fourByteBound) {
215
+ return new Uint8Array([
216
+ ((value >> 24) ^ FourByteMode.negPrefix) & 0xff,
217
+ (value >> 16) & 0xff,
218
+ (value >> 8) & 0xff,
219
+ value & 0xff
220
+ ])
183
221
  } else {
184
- if (value >= -this.oneByteBound) {
185
- return new Uint8Array([(value ^ CompactInt.oneByteNegPrefix) & 0xff])
186
- } else if (value >= -this.twoByteBound) {
187
- return new Uint8Array([((value >> 8) ^ CompactInt.twoByteNegPrefix) & 0xff, value & 0xff])
188
- } else if (value >= -this.fourByteBound) {
189
- return new Uint8Array([
190
- ((value >> 24) ^ CompactInt.fourByteNegPrefix) & 0xff,
191
- (value >> 16) & 0xff,
192
- (value >> 8) & 0xff,
193
- value & 0xff
194
- ])
195
- } else {
196
- return new Uint8Array([
197
- CompactInt.multiBytePrefix,
198
- (value >> 24) & 0xff,
199
- (value >> 16) & 0xff,
200
- (value >> 8) & 0xff,
201
- value & 0xff
202
- ])
203
- }
222
+ return new Uint8Array([
223
+ MultiByte.prefix,
224
+ (value >> 24) & 0xff,
225
+ (value >> 16) & 0xff,
226
+ (value >> 8) & 0xff,
227
+ value & 0xff
228
+ ])
204
229
  }
205
230
  }
206
231
 
207
- encodeI256(value: bigint): Uint8Array {
232
+ static encodeI256(value: bigint): Uint8Array {
233
+ assert(value >= Signed.i256LowerBound && value < Signed.i256UpperBound, `Invalid i256 value: ${value}`)
234
+
208
235
  if (value >= -0x20000000 && value < 0x20000000) {
209
236
  return this.encodeI32(Number(value))
210
237
  } else {
211
238
  const bytes = BigIntCodec.encode(value)
212
- const header = (bytes.length - 4 + CompactInt.multiBytePrefix) & 0xff
239
+ const header = (bytes.length - 4 + MultiByte.prefix) & 0xff
213
240
  return new Uint8Array([header, ...bytes])
214
241
  }
215
242
  }
216
243
 
217
- decodeI256(input: Uint8Array): bigint {
218
- const decoded = this.decode(input)
219
- return this.toI256(decoded)
220
- }
221
-
222
- toI32(value: DecodedCompactInt): number {
223
- const body = new Uint8Array([value.mode, ...value.rest])
224
- const mode = value.mode & maskRest
225
- if (fixedSize(mode)) {
226
- const isPositive = (value.mode & signFlag) == 0
227
- if (isPositive) {
228
- return decodePositiveInt(value.mode, body)
229
- } else {
230
- return decodeNegativeInt(value.mode, body)
231
- }
244
+ static decodeInt(mode: FixedWidthMode, body: Uint8Array): number {
245
+ const isPositive = (body[0] & Signed.signFlag) === 0
246
+ if (isPositive) {
247
+ return Signed.decodePositiveInt(mode, body)
232
248
  } else {
233
- if (body.length === 5) {
234
- return ((body[1] & 0xff) << 24) | ((body[2] & 0xff) << 16) | ((body[3] & 0xff) << 8) | (body[4] & 0xff)
235
- } else {
236
- throw new Error(`Expect 4 bytes int, but get ${body.length - 1} bytes int`)
237
- }
249
+ return Signed.decodeNegativeInt(mode, body)
238
250
  }
239
251
  }
240
252
 
241
- fromI32(value: number): DecodedCompactInt {
242
- return this.decode(this.encodeI32(value))
253
+ static decodePositiveInt(mode: FixedWidthMode, body: Uint8Array): number {
254
+ switch (mode.type) {
255
+ case 'SingleByte':
256
+ return body[0]
257
+ case 'TwoByte':
258
+ assert(body.length === 2, 'Length should be 2')
259
+ return ((body[0] & maskMode) << 8) | (body[1] & 0xff)
260
+ case 'FourByte':
261
+ assert(body.length === 4, 'Length should be 4')
262
+ return ((body[0] & maskMode) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)
263
+ }
243
264
  }
244
265
 
245
- toI256(value: DecodedCompactInt): bigint {
246
- const mode = value.mode & maskRest
247
-
248
- if (fixedSize(mode)) {
249
- return BigInt(this.toI32(value))
250
- } else {
251
- assert(value.rest.length <= 32, 'Expect <= 32 bytes for I256')
252
- return BigIntCodec.decode(value.rest, true)
266
+ static decodeNegativeInt(mode: FixedWidthMode, body: Uint8Array) {
267
+ switch (mode.type) {
268
+ case 'SingleByte':
269
+ return body[0] | maskModeNeg
270
+ case 'TwoByte':
271
+ assert(body.length === 2, 'Length should be 2')
272
+ return ((body[0] | maskModeNeg) << 8) | (body[1] & 0xff)
273
+ case 'FourByte':
274
+ assert(body.length === 4, 'Length should be 4')
275
+ return ((body[0] | maskModeNeg) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)
253
276
  }
254
277
  }
255
278
 
256
- fromI256(value: bigint): DecodedCompactInt {
257
- return this.decode(this.encodeI256(value))
279
+ static decodeI32(mode: Mode, body: Uint8Array): number {
280
+ switch (mode.type) {
281
+ case 'SingleByte':
282
+ case 'TwoByte':
283
+ case 'FourByte':
284
+ return Signed.decodeInt(mode, body)
285
+ case 'MultiByte':
286
+ if (body.length === 5) {
287
+ return (body[1] << 24) | ((body[2] & 0xff) << 16) | ((body[3] & 0xff) << 8) | (body[4] & 0xff)
288
+ } else {
289
+ throw new Error(`Expect 4 bytes int, but get ${body.length - 1} bytes int`)
290
+ }
291
+ }
258
292
  }
259
- }
260
-
261
- export const compactSignedIntCodec = new CompactSignedIntCodec()
262
293
 
263
- function decodePositiveInt(rawMode: number, body: Uint8Array): number {
264
- const mode = rawMode & maskRest
265
-
266
- switch (mode) {
267
- case CompactInt.oneBytePrefix:
268
- return rawMode
269
- case CompactInt.twoBytePrefix:
270
- assert(body.length === 2, 'Length should be 2')
271
- return ((body[0] & maskMode) << 8) | (body[1] & 0xff)
272
- case CompactInt.fourBytePrefix:
273
- assert(body.length === 4, 'Length should be 4')
274
- return ((body[0] & maskMode) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)
275
- default:
276
- if (body.length === 5) {
277
- return Number(BigInt('0x' + binToHex(body.slice(1))))
278
- } else {
279
- throw new Error(`decodePositiveInt: Expect 4 bytes int, but get ${body.length - 1} bytes int`)
280
- }
294
+ static decodeI256(mode: Mode, body: Uint8Array): bigint {
295
+ switch (mode.type) {
296
+ case 'SingleByte':
297
+ case 'TwoByte':
298
+ case 'FourByte':
299
+ return BigInt(Signed.decodeInt(mode, body))
300
+ case 'MultiByte':
301
+ const bytes = body.slice(1, body.length)
302
+ assert(bytes.length <= 32, 'Expect <= 32 bytes for I256')
303
+ return BigIntCodec.decodeSigned(bytes)
304
+ }
281
305
  }
282
306
  }
283
307
 
284
- function decodeNegativeInt(rawMode: number, body: Uint8Array) {
285
- const mode = rawMode & maskRest
286
- switch (mode) {
287
- case CompactInt.oneBytePrefix:
288
- return rawMode | maskModeNeg
289
- case CompactInt.twoBytePrefix:
290
- assert(body.length === 2, 'Length should be 2')
291
- return ((body[0] | maskModeNeg) << 8) | (body[1] & 0xff)
292
- case CompactInt.fourBytePrefix:
293
- assert(body.length === 4, 'Length should be 4')
294
- return ((body[0] | maskModeNeg) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)
295
- default:
296
- throw new Error(`decodeNegativeInt: Expect 4 bytes int, but get ${body.length - 1} bytes int`)
308
+ export const i256Codec = new (class extends Codec<bigint> {
309
+ encode(input: bigint): Uint8Array {
310
+ return Signed.encodeI256(input)
297
311
  }
298
- }
299
-
300
- function fixedSize(mode: number): boolean {
301
- return mode === CompactInt.oneBytePrefix || mode === CompactInt.twoBytePrefix || mode === CompactInt.fourBytePrefix
302
- }
312
+ _decode(input: Reader): bigint {
313
+ const { mode, body } = decodeMode(input)
314
+ return Signed.decodeI256(mode, body)
315
+ }
316
+ })()
317
+ export const i32Codec = new (class extends Codec<number> {
318
+ encode(input: number): Uint8Array {
319
+ return Signed.encodeI32(input)
320
+ }
321
+ _decode(input: Reader): number {
322
+ const { mode, body } = decodeMode(input)
323
+ return Signed.decodeI32(mode, body)
324
+ }
325
+ })()
@@ -16,18 +16,18 @@ You should have received a copy of the GNU Lesser General Public License
16
16
  along with the library. If not, see <http://www.gnu.org/licenses/>.
17
17
  */
18
18
 
19
- import { Parser } from 'binary-parser'
20
- import { ArrayCodec, DecodedArray } from './array-codec'
19
+ import { ArrayCodec } from './array-codec'
21
20
  import { Codec } from './codec'
22
- import { compactSignedIntCodec, DecodedCompactInt } from './compact-int-codec'
23
- import { Method, MethodCodec, methodCodec } from './method-codec'
21
+ import { i32Codec } from './compact-int-codec'
22
+ import { Method, methodCodec } from './method-codec'
24
23
  import { concatBytes } from '../utils'
24
+ import { Reader } from './reader'
25
25
 
26
- const compactSignedIntsCodec = new ArrayCodec(compactSignedIntCodec)
26
+ const i32sCodec = new ArrayCodec(i32Codec)
27
27
 
28
28
  export interface HalfDecodedContract {
29
- fieldLength: DecodedCompactInt
30
- methodIndexes: DecodedArray<DecodedCompactInt>
29
+ fieldLength: number
30
+ methodIndexes: number[]
31
31
  methods: Uint8Array
32
32
  }
33
33
 
@@ -36,36 +36,26 @@ export interface Contract {
36
36
  methods: Method[]
37
37
  }
38
38
 
39
- export class ContractCodec implements Codec<HalfDecodedContract> {
40
- parser = Parser.start()
41
- .nest('fieldLength', {
42
- type: compactSignedIntCodec.parser
43
- })
44
- .nest('methodIndexes', {
45
- type: compactSignedIntsCodec.parser
46
- })
47
- .buffer('methods', { readUntil: 'eof' })
48
-
39
+ export class ContractCodec extends Codec<HalfDecodedContract> {
49
40
  encode(input: HalfDecodedContract): Uint8Array {
50
- return concatBytes([
51
- compactSignedIntCodec.encode(input.fieldLength),
52
- compactSignedIntsCodec.encode(input.methodIndexes.value),
53
- input.methods
54
- ])
41
+ return concatBytes([i32Codec.encode(input.fieldLength), i32sCodec.encode(input.methodIndexes), input.methods])
55
42
  }
56
43
 
57
- decode(input: Uint8Array): HalfDecodedContract {
58
- return this.parser.parse(input)
44
+ _decode(input: Reader): HalfDecodedContract {
45
+ const fieldLength = i32Codec._decode(input)
46
+ const methodIndexes = i32sCodec._decode(input)
47
+ const methods = input.consumeAll()
48
+ return { fieldLength, methodIndexes, methods }
59
49
  }
60
50
 
61
51
  decodeContract(input: Uint8Array): Contract {
62
52
  const halfDecoded = this.decode(input)
63
- const fieldLength = compactSignedIntCodec.toI32(halfDecoded.fieldLength)
64
- const methodIndexes = halfDecoded.methodIndexes.value.map((v) => compactSignedIntCodec.toI32(v))
53
+ const fieldLength = halfDecoded.fieldLength
54
+ const methodIndexes = halfDecoded.methodIndexes
65
55
  const methods: Method[] = []
66
56
  for (let i = 0, start = 0; i < methodIndexes.length; i++) {
67
57
  const end = methodIndexes[i]
68
- const method = MethodCodec.toMethod(methodCodec.decode(halfDecoded.methods.slice(start, end)))
58
+ const method = methodCodec.decode(halfDecoded.methods.slice(start, end))
69
59
  methods.push(method)
70
60
  start = end
71
61
  }
@@ -74,8 +64,8 @@ export class ContractCodec implements Codec<HalfDecodedContract> {
74
64
  }
75
65
 
76
66
  encodeContract(contract: Contract): Uint8Array {
77
- const fieldLength = compactSignedIntCodec.fromI32(contract.fieldLength)
78
- const methods = contract.methods.map((m) => methodCodec.encode(MethodCodec.fromMethod(m)))
67
+ const fieldLength = contract.fieldLength
68
+ const methods = contract.methods.map((m) => methodCodec.encode(m))
79
69
  let count = 0
80
70
  const methodIndexes = Array.from(Array(methods.length).keys()).map((index) => {
81
71
  count += methods[`${index}`].length
@@ -83,10 +73,7 @@ export class ContractCodec implements Codec<HalfDecodedContract> {
83
73
  })
84
74
  const halfDecoded = {
85
75
  fieldLength,
86
- methodIndexes: {
87
- length: compactSignedIntCodec.fromI32(methodIndexes.length),
88
- value: methodIndexes.map((value) => compactSignedIntCodec.fromI32(value))
89
- },
76
+ methodIndexes: methodIndexes,
90
77
  methods: concatBytes(methods)
91
78
  }
92
79
  return this.encode(halfDecoded)