@alephium/web3 0.36.1 → 0.38.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 (95) 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 +6 -1
  4. package/dist/src/api/api-alephium.js +1 -1
  5. package/dist/src/api/types.d.ts +1 -1
  6. package/dist/src/codec/array-codec.d.ts +17 -0
  7. package/dist/src/codec/array-codec.js +59 -0
  8. package/dist/src/codec/asset-output-codec.d.ts +27 -0
  9. package/dist/src/codec/asset-output-codec.js +135 -0
  10. package/dist/src/codec/bigint-codec.d.ts +5 -0
  11. package/dist/src/codec/bigint-codec.js +86 -0
  12. package/dist/src/codec/bytestring-codec.d.ts +16 -0
  13. package/dist/src/codec/bytestring-codec.js +50 -0
  14. package/dist/src/codec/codec.d.ts +8 -0
  15. package/dist/src/codec/codec.js +9 -0
  16. package/dist/src/codec/compact-int-codec.d.ts +51 -0
  17. package/dist/src/codec/compact-int-codec.js +300 -0
  18. package/dist/src/codec/contract-codec.d.ts +23 -0
  19. package/dist/src/codec/contract-codec.js +81 -0
  20. package/dist/src/codec/contract-output-codec.d.ts +21 -0
  21. package/dist/src/codec/contract-output-codec.js +82 -0
  22. package/dist/src/codec/contract-output-ref-codec.d.ts +15 -0
  23. package/dist/src/codec/contract-output-ref-codec.js +38 -0
  24. package/dist/src/codec/either-codec.d.ts +17 -0
  25. package/dist/src/codec/either-codec.js +67 -0
  26. package/dist/src/codec/hash.d.ts +4 -0
  27. package/dist/src/codec/hash.js +23 -0
  28. package/dist/src/codec/index.d.ts +23 -0
  29. package/dist/src/codec/index.js +69 -0
  30. package/dist/src/codec/input-codec.d.ts +22 -0
  31. package/dist/src/codec/input-codec.js +71 -0
  32. package/dist/src/codec/instr-codec.d.ts +230 -0
  33. package/dist/src/codec/instr-codec.js +471 -0
  34. package/dist/src/codec/lockup-script-codec.d.ts +28 -0
  35. package/dist/src/codec/lockup-script-codec.js +80 -0
  36. package/dist/src/codec/long-codec.d.ts +9 -0
  37. package/dist/src/codec/long-codec.js +56 -0
  38. package/dist/src/codec/method-codec.d.ts +31 -0
  39. package/dist/src/codec/method-codec.js +78 -0
  40. package/dist/src/codec/option-codec.d.ts +15 -0
  41. package/dist/src/codec/option-codec.js +55 -0
  42. package/dist/src/codec/output-codec.d.ts +7 -0
  43. package/dist/src/codec/output-codec.js +26 -0
  44. package/dist/src/codec/script-codec.d.ts +16 -0
  45. package/dist/src/codec/script-codec.js +41 -0
  46. package/dist/src/codec/signature-codec.d.ts +14 -0
  47. package/dist/src/codec/signature-codec.js +19 -0
  48. package/dist/src/codec/signed-int-codec.d.ts +9 -0
  49. package/dist/src/codec/signed-int-codec.js +39 -0
  50. package/dist/src/codec/token-codec.d.ts +16 -0
  51. package/dist/src/codec/token-codec.js +46 -0
  52. package/dist/src/codec/transaction-codec.d.ts +27 -0
  53. package/dist/src/codec/transaction-codec.js +128 -0
  54. package/dist/src/codec/unlock-script-codec.d.ts +40 -0
  55. package/dist/src/codec/unlock-script-codec.js +170 -0
  56. package/dist/src/codec/unsigned-tx-codec.d.ts +30 -0
  57. package/dist/src/codec/unsigned-tx-codec.js +103 -0
  58. package/dist/src/contract/contract.d.ts +14 -8
  59. package/dist/src/contract/contract.js +205 -22
  60. package/dist/src/contract/ralph.d.ts +16 -0
  61. package/dist/src/contract/ralph.js +127 -1
  62. package/dist/src/index.d.ts +1 -0
  63. package/dist/src/index.js +2 -1
  64. package/package.json +5 -4
  65. package/src/api/api-alephium.ts +7 -1
  66. package/src/api/types.ts +1 -1
  67. package/src/codec/array-codec.ts +63 -0
  68. package/src/codec/asset-output-codec.ts +149 -0
  69. package/src/codec/bigint-codec.ts +92 -0
  70. package/src/codec/bytestring-codec.ts +56 -0
  71. package/src/codec/codec.ts +31 -0
  72. package/src/codec/compact-int-codec.ts +316 -0
  73. package/src/codec/contract-codec.ts +95 -0
  74. package/src/codec/contract-output-codec.ts +95 -0
  75. package/src/codec/contract-output-ref-codec.ts +42 -0
  76. package/src/codec/either-codec.ts +74 -0
  77. package/src/codec/hash.ts +35 -0
  78. package/src/codec/index.ts +41 -0
  79. package/src/codec/input-codec.ts +81 -0
  80. package/src/codec/instr-codec.ts +479 -0
  81. package/src/codec/lockup-script-codec.ts +99 -0
  82. package/src/codec/long-codec.ts +59 -0
  83. package/src/codec/method-codec.ts +97 -0
  84. package/src/codec/option-codec.ts +60 -0
  85. package/src/codec/output-codec.ts +26 -0
  86. package/src/codec/script-codec.ts +45 -0
  87. package/src/codec/signature-codec.ts +40 -0
  88. package/src/codec/signed-int-codec.ts +37 -0
  89. package/src/codec/token-codec.ts +51 -0
  90. package/src/codec/transaction-codec.ts +147 -0
  91. package/src/codec/unlock-script-codec.ts +194 -0
  92. package/src/codec/unsigned-tx-codec.ts +124 -0
  93. package/src/contract/contract.ts +299 -23
  94. package/src/contract/ralph.ts +140 -2
  95. package/src/index.ts +1 -1
@@ -0,0 +1,149 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import { Buffer } from 'buffer/'
19
+ import { Parser } from 'binary-parser'
20
+ import { ArrayCodec, DecodedArray } from './array-codec'
21
+ import { DecodedCompactInt, compactUnsignedIntCodec } from './compact-int-codec'
22
+ import { signedIntCodec } from './signed-int-codec'
23
+ import { longCodec } from './long-codec'
24
+ import { ByteString, byteStringCodec } from './bytestring-codec'
25
+ import { LockupScript, MultiSig, P2C, P2SH, lockupScriptCodec } from './lockup-script-codec'
26
+ import { FixedAssetOutput } from '../api/api-alephium'
27
+ import { blakeHash, createHint } from './hash'
28
+ import { bs58, binToHex } from '../utils'
29
+ import { Codec } from './codec'
30
+ import { PublicKeyHash } from './lockup-script-codec'
31
+ import { Token, tokensCodec } from './token-codec'
32
+
33
+ export interface AssetOutput {
34
+ amount: DecodedCompactInt
35
+ lockupScript: LockupScript
36
+ lockTime: Buffer
37
+ tokens: DecodedArray<Token>
38
+ additionalData: ByteString
39
+ }
40
+
41
+ export class AssetOutputCodec implements Codec<AssetOutput> {
42
+ parser = Parser.start()
43
+ .nest('amount', {
44
+ type: compactUnsignedIntCodec.parser
45
+ })
46
+ .nest('lockupScript', {
47
+ type: lockupScriptCodec.parser
48
+ })
49
+ .buffer('lockTime', {
50
+ length: 8
51
+ })
52
+ .nest('tokens', {
53
+ type: tokensCodec.parser
54
+ })
55
+ .nest('additionalData', {
56
+ type: byteStringCodec.parser
57
+ })
58
+
59
+ encode(input: AssetOutput): Buffer {
60
+ const amount = Buffer.from(compactUnsignedIntCodec.encode(input.amount))
61
+ const lockupScript = lockupScriptCodec.encode(input.lockupScript)
62
+ const lockTime = Buffer.from(input.lockTime)
63
+ const tokens = Buffer.from(tokensCodec.encode(input.tokens.value))
64
+ const additionalData = Buffer.from(byteStringCodec.encode(input.additionalData))
65
+
66
+ return Buffer.concat([amount, lockupScript, lockTime, tokens, additionalData])
67
+ }
68
+
69
+ decode(input: Buffer): AssetOutput {
70
+ return this.parser.parse(input)
71
+ }
72
+
73
+ static toFixedAssetOutputs(txIdBytes: Uint8Array, outputs: AssetOutput[]): FixedAssetOutput[] {
74
+ return outputs.map((output, index) => AssetOutputCodec.toFixedAssetOutput(txIdBytes, output, index))
75
+ }
76
+
77
+ static toFixedAssetOutput(txIdBytes: Uint8Array, output: AssetOutput, index: number): FixedAssetOutput {
78
+ const attoAlphAmount = compactUnsignedIntCodec.toU256(output.amount).toString()
79
+ const lockTime = Number(longCodec.decode(output.lockTime))
80
+ const tokens = output.tokens.value.map((token) => {
81
+ return {
82
+ id: token.tokenId.toString('hex'),
83
+ amount: compactUnsignedIntCodec.toU256(token.amount).toString()
84
+ }
85
+ })
86
+ const message = output.additionalData.value.toString('hex')
87
+ const scriptType = output.lockupScript.scriptType
88
+ const key = binToHex(blakeHash(Buffer.concat([txIdBytes, signedIntCodec.encode(index)])))
89
+ const outputLockupScript = output.lockupScript.script
90
+ const address = bs58.encode(lockupScriptCodec.encode(output.lockupScript))
91
+
92
+ let hint: number | undefined = undefined
93
+ if (scriptType === 0) {
94
+ // P2PKH
95
+ hint = createHint((outputLockupScript as PublicKeyHash).publicKeyHash)
96
+ } else if (scriptType === 1) {
97
+ // P2MPKH
98
+ hint = createHint((outputLockupScript as MultiSig).publicKeyHashes.value[0].publicKeyHash)
99
+ } else if (scriptType === 2) {
100
+ // P2SH
101
+ hint = createHint((outputLockupScript as P2SH).scriptHash)
102
+ } else if (scriptType === 3) {
103
+ throw new Error(`P2C script type not allowed for asset output`)
104
+ } else {
105
+ throw new Error(`Unexpected output script type: ${scriptType}`)
106
+ }
107
+
108
+ return { hint, key, attoAlphAmount, lockTime, tokens, address, message }
109
+ }
110
+
111
+ static fromFixedAssetOutputs(fixedOutputs: FixedAssetOutput[]): AssetOutput[] {
112
+ return fixedOutputs.map((output) => {
113
+ return AssetOutputCodec.fromFixedAssetOutput(output)
114
+ })
115
+ }
116
+
117
+ static fromFixedAssetOutput(fixedOutput: FixedAssetOutput): AssetOutput {
118
+ const amount: DecodedCompactInt = compactUnsignedIntCodec.fromU256(BigInt(fixedOutput.attoAlphAmount))
119
+
120
+ const lockTime: Buffer = longCodec.encode(BigInt(fixedOutput.lockTime))
121
+ const lockupScript: LockupScript = lockupScriptCodec.decode(Buffer.from(bs58.decode(fixedOutput.address)))
122
+ const tokensValue = fixedOutput.tokens.map((token) => {
123
+ return {
124
+ tokenId: Buffer.from(token.id, 'hex'),
125
+ amount: compactUnsignedIntCodec.fromU256(BigInt(token.amount))
126
+ }
127
+ })
128
+ const tokens: DecodedArray<Token> = {
129
+ length: compactUnsignedIntCodec.fromU32(tokensValue.length),
130
+ value: tokensValue
131
+ }
132
+ const additionalDataValue = Buffer.from(fixedOutput.message, 'hex')
133
+ const additionalData: ByteString = {
134
+ length: compactUnsignedIntCodec.fromU32(additionalDataValue.length),
135
+ value: additionalDataValue
136
+ }
137
+
138
+ return {
139
+ amount,
140
+ lockupScript,
141
+ lockTime,
142
+ tokens,
143
+ additionalData
144
+ }
145
+ }
146
+ }
147
+
148
+ export const assetOutputCodec = new AssetOutputCodec()
149
+ export const assetOutputsCodec = new ArrayCodec(assetOutputCodec)
@@ -0,0 +1,92 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import { Buffer } from 'buffer/'
19
+ export class BigIntCodec {
20
+ static encode(value: bigint): Buffer {
21
+ // Special case for zero.
22
+ if (value === 0n) {
23
+ return Buffer.from([0])
24
+ }
25
+
26
+ const isNegative = value < 0n
27
+ let absValue = isNegative ? -value : value
28
+ const bytes: number[] = []
29
+
30
+ // Extract bytes from absolute value.
31
+ while (absValue > 0n) {
32
+ bytes.push(Number(absValue & 0xffn))
33
+ absValue >>= 8n
34
+ }
35
+
36
+ // If the bigint is positive and the most significant byte has its high bit set,
37
+ // prefix the byte array with a zero byte to signify positive value.
38
+ if (!isNegative && (bytes[bytes.length - 1] & 0x80) !== 0) {
39
+ bytes.push(0)
40
+ }
41
+
42
+ // If the bigint is negative, compute the two's complement of the byte array.
43
+ if (isNegative) {
44
+ let carry = true
45
+ for (let i = 0; i < bytes.length; i++) {
46
+ bytes[i] = ~bytes[i] & 0xff // Invert the bits of the byte.
47
+ if (carry) {
48
+ if (bytes[i] === 0xff) {
49
+ bytes[i] = 0
50
+ } else {
51
+ bytes[i] += 1
52
+ carry = false
53
+ }
54
+ }
55
+ }
56
+
57
+ // If there's still a carry, and the most significant byte is not 0xFF (to store the negative sign bit),
58
+ // or if no bytes were set (which means the value was -1), append a 0xFF byte to hold the carry.
59
+ if (carry || bytes.length === 0 || (bytes[bytes.length - 1] & 0x80) === 0) {
60
+ bytes.push(0xff)
61
+ }
62
+ }
63
+
64
+ // The byte array needs to be reversed since we've constructed it in little-endian order.
65
+ return Buffer.from(new Uint8Array(bytes.reverse()))
66
+ }
67
+
68
+ static decode(encoded: Buffer, signed: boolean): bigint {
69
+ // Special case for zero.
70
+ if (encoded.length === 1 && encoded[0] === 0) {
71
+ return 0n
72
+ }
73
+
74
+ // Determine if the number is negative by checking the most significant byte (MSB)
75
+ const isNegative = signed ? encoded[0] === 0xff : signed
76
+
77
+ // Convert the byte array to a bigint
78
+ let value = 0n
79
+ for (const byte of encoded) {
80
+ value = (value << 8n) | BigInt(byte)
81
+ }
82
+
83
+ // If the number is negative, convert from two's complement
84
+ if (isNegative) {
85
+ // Create a mask for the value's bit length
86
+ const mask = (1n << (8n * BigInt(encoded.length))) - 1n
87
+ value = -(~value & mask) - 1n
88
+ }
89
+
90
+ return value
91
+ }
92
+ }
@@ -0,0 +1,56 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import { Buffer } from 'buffer/'
19
+ import { Parser } from 'binary-parser'
20
+ import { DecodedCompactInt, compactUnsignedIntCodec } from './compact-int-codec'
21
+ import { Codec } from './codec'
22
+
23
+ export interface ByteString {
24
+ length: DecodedCompactInt
25
+ value: Buffer
26
+ }
27
+
28
+ export class ByteStringCodec implements Codec<ByteString> {
29
+ parser = new Parser()
30
+ .nest('length', {
31
+ type: compactUnsignedIntCodec.parser
32
+ })
33
+ .buffer('value', {
34
+ length: function (ctx) {
35
+ return compactUnsignedIntCodec.toU32(this['length']! as any as DecodedCompactInt)
36
+ }
37
+ })
38
+
39
+ encode(input: ByteString): Buffer {
40
+ return Buffer.from([...compactUnsignedIntCodec.encode(input.length), ...input.value])
41
+ }
42
+
43
+ decode(input: Buffer): ByteString {
44
+ return this.parser.parse(input)
45
+ }
46
+
47
+ encodeBuffer(input: Buffer): Buffer {
48
+ return Buffer.from([...compactUnsignedIntCodec.encodeU32(input.length), ...input])
49
+ }
50
+
51
+ decodeBuffer(input: Buffer): Buffer {
52
+ return this.decode(input).value
53
+ }
54
+ }
55
+
56
+ export const byteStringCodec = new ByteStringCodec()
@@ -0,0 +1,31 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import { Buffer } from 'buffer/'
19
+ import { Parser } from 'binary-parser'
20
+
21
+ export interface Codec<T> {
22
+ parser: Parser
23
+ encode(input: T): Buffer
24
+ decode(input: Buffer): T
25
+ }
26
+
27
+ export function assert(value: boolean, message: string) {
28
+ if (!value) {
29
+ throw new Error(message)
30
+ }
31
+ }
@@ -0,0 +1,316 @@
1
+ /*
2
+ Copyright 2018 - 2022 The Alephium Authors
3
+ This file is part of the alephium project.
4
+
5
+ The library is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU Lesser General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ The library is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU Lesser General Public License for more details.
14
+
15
+ You should have received a copy of the GNU Lesser General Public License
16
+ along with the library. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+ import { Buffer } from 'buffer/'
19
+ import { Parser } from 'binary-parser'
20
+ import { Codec, assert } from './codec'
21
+ import { BigIntCodec } from './bigint-codec'
22
+ import { ArrayCodec } from './array-codec'
23
+
24
+ export class CompactInt {
25
+ static readonly oneBytePrefix = 0x00
26
+ static readonly oneByteNegPrefix = 0xc0
27
+ static readonly twoBytePrefix = 0x40
28
+ static readonly twoByteNegPrefix = 0x80
29
+ static readonly fourBytePrefix = 0x80
30
+ static readonly fourByteNegPrefix = 0x40
31
+ static readonly multiBytePrefix = 0xc0
32
+ }
33
+
34
+ const maskRest = 0xc0
35
+ const maskMode = 0x3f
36
+ const maskModeNeg = 0xffffffc0
37
+ const signFlag = 0x20 // 0b00100000
38
+
39
+ export interface DecodedCompactInt {
40
+ mode: number
41
+ rest: Uint8Array
42
+ }
43
+
44
+ const compactIntParser = new Parser().uint8('mode').buffer('rest', {
45
+ length: function (ctx) {
46
+ const rawMode = this['mode']
47
+ const mode = rawMode & maskRest
48
+
49
+ switch (mode) {
50
+ case CompactInt.oneBytePrefix:
51
+ return 0
52
+ case CompactInt.twoBytePrefix:
53
+ return 1
54
+ case CompactInt.fourBytePrefix:
55
+ return 3
56
+ default:
57
+ return (rawMode & maskMode) + 4
58
+ }
59
+ }
60
+ })
61
+
62
+ export class CompactUnsignedIntCodec implements Codec<DecodedCompactInt> {
63
+ private oneByteBound = 0x40
64
+ private twoByteBound = this.oneByteBound << 8
65
+ private fourByteBound = this.oneByteBound << (8 * 3)
66
+
67
+ parser = compactIntParser
68
+
69
+ encode(input: DecodedCompactInt): Buffer {
70
+ return Buffer.from([input.mode, ...input.rest])
71
+ }
72
+
73
+ encodeU32(value: number): Buffer {
74
+ if (value < this.oneByteBound) {
75
+ return Buffer.from([(CompactInt.oneBytePrefix + value) & 0xff])
76
+ } else if (value < this.twoByteBound) {
77
+ return Buffer.from([(CompactInt.twoBytePrefix + (value >> 8)) & 0xff, value & 0xff])
78
+ } else if (value < this.fourByteBound) {
79
+ return Buffer.from([
80
+ (CompactInt.fourBytePrefix + (value >> 24)) & 0xff,
81
+ (value >> 16) & 0xff,
82
+ (value >> 8) & 0xff,
83
+ value & 0xff
84
+ ])
85
+ } else {
86
+ return Buffer.from([
87
+ CompactInt.multiBytePrefix,
88
+ (value >> 24) & 0xff,
89
+ (value >> 16) & 0xff,
90
+ (value >> 8) & 0xff,
91
+ value & 0xff
92
+ ])
93
+ }
94
+ }
95
+
96
+ encodeU256(value: bigint): Buffer {
97
+ assert(value >= 0n, 'Value should be positive')
98
+
99
+ if (value < this.fourByteBound) {
100
+ return this.encodeU32(Number(value))
101
+ } else {
102
+ let bytes = BigIntCodec.encode(value)
103
+ if (bytes[0] === 0) {
104
+ bytes = bytes.slice(1)
105
+ }
106
+
107
+ assert(bytes.length <= 32, 'Expect <= 32 bytes for U256')
108
+
109
+ const header = (bytes.length - 4 + CompactInt.multiBytePrefix) & 0xff
110
+ return Buffer.concat([Buffer.from([header]), bytes])
111
+ }
112
+ }
113
+
114
+ decodeU32(input: Buffer): number {
115
+ const decoded = this.decode(input)
116
+ return this.toU32(decoded)
117
+ }
118
+
119
+ decodeU256(input: Buffer): bigint {
120
+ const decoded = this.decode(input)
121
+ return this.toU256(decoded)
122
+ }
123
+
124
+ decode(input: Buffer): DecodedCompactInt {
125
+ return this.parser.parse(input)
126
+ }
127
+
128
+ toU32(value: DecodedCompactInt): number {
129
+ const body = Buffer.from([value.mode, ...value.rest])
130
+ return decodePositiveInt(value.mode, body)
131
+ }
132
+
133
+ fromU32(value: number): DecodedCompactInt {
134
+ return this.decode(this.encodeU32(value))
135
+ }
136
+
137
+ toU256(value: DecodedCompactInt): bigint {
138
+ const mode = value.mode & maskRest
139
+ if (fixedSize(mode)) {
140
+ return BigInt(this.toU32(value))
141
+ } else {
142
+ assert(value.rest.length <= 32, 'Expect <= 32 bytes for U256')
143
+ return BigIntCodec.decode(Buffer.from(value.rest), false)
144
+ }
145
+ }
146
+
147
+ fromU256(value: bigint): DecodedCompactInt {
148
+ return this.decode(this.encodeU256(value))
149
+ }
150
+ }
151
+
152
+ export const compactUnsignedIntCodec = new CompactUnsignedIntCodec()
153
+
154
+ export class CompactSignedIntCodec implements Codec<DecodedCompactInt> {
155
+ private signFlag = 0x20 // 0b00100000
156
+ private oneByteBound = 0x20 // 0b00100000
157
+ private twoByteBound = this.oneByteBound << 8
158
+ private fourByteBound = this.oneByteBound << (8 * 3)
159
+
160
+ parser = compactIntParser
161
+
162
+ encode(input: DecodedCompactInt): Buffer {
163
+ return Buffer.from([input.mode, ...input.rest])
164
+ }
165
+
166
+ decode(input: Buffer): DecodedCompactInt {
167
+ return this.parser.parse(input)
168
+ }
169
+
170
+ decodeI32(input: Buffer): number {
171
+ const decoded = this.decode(input)
172
+ return this.toI32(decoded)
173
+ }
174
+
175
+ encodeI32(value: number): Buffer {
176
+ if (value >= 0) {
177
+ if (value < this.oneByteBound) {
178
+ return Buffer.from([(CompactInt.oneBytePrefix + value) & 0xff])
179
+ } else if (value < this.twoByteBound) {
180
+ return Buffer.from([(CompactInt.twoBytePrefix + (value >> 8)) & 0xff, value & 0xff])
181
+ } else if (value < this.fourByteBound) {
182
+ return Buffer.from([
183
+ (CompactInt.fourBytePrefix + (value >> 24)) & 0xff,
184
+ (value >> 16) & 0xff,
185
+ (value >> 8) & 0xff,
186
+ value & 0xff
187
+ ])
188
+ } else {
189
+ return Buffer.from([
190
+ CompactInt.multiBytePrefix,
191
+ (value >> 24) & 0xff,
192
+ (value >> 16) & 0xff,
193
+ (value >> 8) & 0xff,
194
+ value & 0xff
195
+ ])
196
+ }
197
+ } else {
198
+ if (value >= -this.oneByteBound) {
199
+ return Buffer.from([(value ^ CompactInt.oneByteNegPrefix) & 0xff])
200
+ } else if (value >= -this.twoByteBound) {
201
+ return Buffer.from([((value >> 8) ^ CompactInt.twoByteNegPrefix) & 0xff, value & 0xff])
202
+ } else if (value >= -this.fourByteBound) {
203
+ return Buffer.from([
204
+ ((value >> 24) ^ CompactInt.fourByteNegPrefix) & 0xff,
205
+ (value >> 16) & 0xff,
206
+ (value >> 8) & 0xff,
207
+ value & 0xff
208
+ ])
209
+ } else {
210
+ return Buffer.from([
211
+ CompactInt.multiBytePrefix,
212
+ (value >> 24) & 0xff,
213
+ (value >> 16) & 0xff,
214
+ (value >> 8) & 0xff,
215
+ value & 0xff
216
+ ])
217
+ }
218
+ }
219
+ }
220
+
221
+ encodeI256(value: bigint): Buffer {
222
+ if (value >= -0x20000000 && value < 0x20000000) {
223
+ return this.encodeI32(Number(value))
224
+ } else {
225
+ const bytes = BigIntCodec.encode(value)
226
+ const header = (bytes.length - 4 + CompactInt.multiBytePrefix) & 0xff
227
+ return Buffer.concat([Buffer.from([header]), bytes])
228
+ }
229
+ }
230
+
231
+ decodeI256(input: Buffer): bigint {
232
+ const decoded = this.decode(input)
233
+ return this.toI256(decoded)
234
+ }
235
+
236
+ toI32(value: DecodedCompactInt): number {
237
+ const body = Buffer.from([value.mode, ...value.rest])
238
+ const mode = value.mode & maskRest
239
+ if (fixedSize(mode)) {
240
+ const isPositive = (value.mode & signFlag) == 0
241
+ if (isPositive) {
242
+ return decodePositiveInt(value.mode, body)
243
+ } else {
244
+ return decodeNegativeInt(value.mode, body)
245
+ }
246
+ } else {
247
+ if (body.length === 5) {
248
+ return ((body[1] & 0xff) << 24) | ((body[2] & 0xff) << 16) | ((body[3] & 0xff) << 8) | (body[4] & 0xff)
249
+ } else {
250
+ throw new Error(`Expect 4 bytes int, but get ${body.length - 1} bytes int`)
251
+ }
252
+ }
253
+ }
254
+
255
+ fromI32(value: number): DecodedCompactInt {
256
+ return this.decode(this.encodeI32(value))
257
+ }
258
+
259
+ toI256(value: DecodedCompactInt): bigint {
260
+ const mode = value.mode & maskRest
261
+
262
+ if (fixedSize(mode)) {
263
+ return BigInt(this.toI32(value))
264
+ } else {
265
+ assert(value.rest.length <= 32, 'Expect <= 32 bytes for I256')
266
+ return BigIntCodec.decode(Buffer.from(value.rest), true)
267
+ }
268
+ }
269
+
270
+ fromI256(value: bigint): DecodedCompactInt {
271
+ return this.decode(this.encodeI256(value))
272
+ }
273
+ }
274
+
275
+ export const compactSignedIntCodec = new CompactSignedIntCodec()
276
+
277
+ function decodePositiveInt(rawMode: number, body: Buffer): number {
278
+ const mode = rawMode & maskRest
279
+
280
+ switch (mode) {
281
+ case CompactInt.oneBytePrefix:
282
+ return rawMode
283
+ case CompactInt.twoBytePrefix:
284
+ assert(body.length === 2, 'Length should be 2')
285
+ return ((body[0] & maskMode) << 8) | (body[1] & 0xff)
286
+ case CompactInt.fourBytePrefix:
287
+ assert(body.length === 4, 'Length should be 4')
288
+ return ((body[0] & maskMode) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)
289
+ default:
290
+ if (body.length === 5) {
291
+ return Number(BigInt('0x' + body.slice(1).toString('hex')))
292
+ } else {
293
+ throw new Error(`decodePositiveInt: Expect 4 bytes int, but get ${body.length - 1} bytes int`)
294
+ }
295
+ }
296
+ }
297
+
298
+ function decodeNegativeInt(rawMode: number, body: Buffer) {
299
+ const mode = rawMode & maskRest
300
+ switch (mode) {
301
+ case CompactInt.oneBytePrefix:
302
+ return rawMode | maskModeNeg
303
+ case CompactInt.twoBytePrefix:
304
+ assert(body.length === 2, 'Length should be 2')
305
+ return ((body[0] | maskModeNeg) << 8) | (body[1] & 0xff)
306
+ case CompactInt.fourBytePrefix:
307
+ assert(body.length === 4, 'Length should be 4')
308
+ return ((body[0] | maskModeNeg) << 24) | ((body[1] & 0xff) << 16) | ((body[2] & 0xff) << 8) | (body[3] & 0xff)
309
+ default:
310
+ throw new Error(`decodeNegativeInt: Expect 4 bytes int, but get ${body.length - 1} bytes int`)
311
+ }
312
+ }
313
+
314
+ function fixedSize(mode: number): boolean {
315
+ return mode === CompactInt.oneBytePrefix || mode === CompactInt.twoBytePrefix || mode === CompactInt.fourBytePrefix
316
+ }