@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.
- package/dist/alephium-web3.min.js +1 -1
- package/dist/alephium-web3.min.js.map +1 -1
- package/dist/src/address/address.js +11 -5
- package/dist/src/api/api-alephium.d.ts +2 -4
- package/dist/src/api/api-alephium.js +1 -1
- package/dist/src/codec/array-codec.d.ts +4 -12
- package/dist/src/codec/array-codec.js +15 -28
- package/dist/src/codec/asset-output-codec.d.ts +6 -11
- package/dist/src/codec/asset-output-codec.js +32 -71
- package/dist/src/codec/bigint-codec.d.ts +2 -1
- package/dist/src/codec/bigint-codec.js +14 -2
- package/dist/src/codec/bytestring-codec.d.ts +6 -11
- package/dist/src/codec/bytestring-codec.js +9 -23
- package/dist/src/codec/codec.d.ts +54 -5
- package/dist/src/codec/codec.js +112 -14
- package/dist/src/codec/compact-int-codec.d.ts +65 -44
- package/dist/src/codec/compact-int-codec.js +222 -204
- package/dist/src/codec/contract-codec.d.ts +5 -8
- package/dist/src/codec/contract-codec.js +15 -29
- package/dist/src/codec/contract-output-codec.d.ts +4 -10
- package/dist/src/codec/contract-output-codec.js +20 -40
- package/dist/src/codec/contract-output-ref-codec.d.ts +2 -8
- package/dist/src/codec/contract-output-ref-codec.js +7 -17
- package/dist/src/codec/either-codec.d.ts +8 -15
- package/dist/src/codec/either-codec.js +5 -46
- package/dist/src/codec/index.d.ts +4 -3
- package/dist/src/codec/index.js +7 -4
- package/dist/src/codec/input-codec.d.ts +4 -10
- package/dist/src/codec/input-codec.js +11 -46
- package/dist/src/codec/instr-codec.d.ts +633 -40
- package/dist/src/codec/instr-codec.js +1040 -434
- package/dist/src/codec/int-as-4bytes-codec.d.ts +7 -0
- package/dist/src/codec/{signed-int-codec.js → int-as-4bytes-codec.js} +6 -12
- package/dist/src/codec/lockup-script-codec.d.ts +23 -26
- package/dist/src/codec/lockup-script-codec.js +12 -58
- package/dist/src/codec/method-codec.d.ts +6 -18
- package/dist/src/codec/method-codec.js +20 -48
- package/dist/src/codec/option-codec.d.ts +8 -13
- package/dist/src/codec/option-codec.js +14 -32
- package/dist/src/codec/output-codec.d.ts +2 -2
- package/dist/src/codec/output-codec.js +1 -1
- package/dist/src/codec/reader.d.ts +8 -0
- package/dist/src/codec/reader.js +48 -0
- package/dist/src/codec/script-codec.d.ts +6 -14
- package/dist/src/codec/script-codec.js +6 -22
- package/dist/src/codec/signature-codec.d.ts +4 -12
- package/dist/src/codec/signature-codec.js +3 -15
- package/dist/src/codec/timestamp-codec.d.ts +8 -0
- package/dist/src/codec/timestamp-codec.js +39 -0
- package/dist/src/codec/token-codec.d.ts +3 -10
- package/dist/src/codec/token-codec.js +6 -24
- package/dist/src/codec/transaction-codec.d.ts +6 -11
- package/dist/src/codec/transaction-codec.js +24 -49
- package/dist/src/codec/unlock-script-codec.d.ts +25 -36
- package/dist/src/codec/unlock-script-codec.js +26 -147
- package/dist/src/codec/unsigned-tx-codec.d.ts +8 -14
- package/dist/src/codec/unsigned-tx-codec.js +24 -66
- package/dist/src/codec/val.d.ts +27 -0
- package/dist/src/codec/val.js +33 -0
- package/dist/src/contract/contract.d.ts +1 -0
- package/dist/src/contract/contract.js +20 -13
- package/dist/src/contract/index.d.ts +1 -0
- package/dist/src/contract/index.js +1 -0
- package/dist/src/contract/ralph.d.ts +0 -4
- package/dist/src/contract/ralph.js +50 -179
- package/dist/src/contract/script-simulator.d.ts +27 -0
- package/dist/src/contract/script-simulator.js +757 -0
- package/dist/src/exchange/exchange.js +1 -1
- package/package.json +3 -4
- package/src/address/address.ts +15 -9
- package/src/api/api-alephium.ts +2 -4
- package/src/codec/array-codec.ts +16 -34
- package/src/codec/asset-output-codec.ts +38 -83
- package/src/codec/bigint-codec.ts +16 -2
- package/src/codec/bytestring-codec.ts +10 -28
- package/src/codec/codec.ts +121 -15
- package/src/codec/compact-int-codec.ts +230 -207
- package/src/codec/contract-codec.ts +20 -33
- package/src/codec/contract-output-codec.ts +22 -48
- package/src/codec/contract-output-ref-codec.ts +6 -17
- package/src/codec/either-codec.ts +4 -53
- package/src/codec/index.ts +4 -3
- package/src/codec/input-codec.ts +14 -36
- package/src/codec/instr-codec.ts +1229 -455
- package/src/codec/{signed-int-codec.ts → int-as-4bytes-codec.ts} +6 -10
- package/src/codec/lockup-script-codec.ts +28 -76
- package/src/codec/method-codec.ts +23 -61
- package/src/codec/option-codec.ts +13 -36
- package/src/codec/output-codec.ts +2 -2
- package/src/codec/reader.ts +56 -0
- package/src/codec/script-codec.ts +9 -31
- package/src/codec/signature-codec.ts +3 -18
- package/src/codec/timestamp-codec.ts +42 -0
- package/src/codec/token-codec.ts +7 -26
- package/src/codec/transaction-codec.ts +29 -58
- package/src/codec/unlock-script-codec.ts +44 -171
- package/src/codec/unsigned-tx-codec.ts +34 -63
- package/src/codec/val.ts +40 -0
- package/src/contract/contract.ts +24 -20
- package/src/contract/index.ts +1 -0
- package/src/contract/ralph.ts +76 -172
- package/src/contract/script-simulator.ts +838 -0
- package/src/exchange/exchange.ts +1 -1
- package/dist/src/codec/long-codec.d.ts +0 -8
- package/dist/src/codec/long-codec.js +0 -55
- package/dist/src/codec/signed-int-codec.d.ts +0 -8
- package/src/codec/long-codec.ts +0 -58
|
@@ -106,7 +106,7 @@ function getAddressFromUnlockScript(unlockScript) {
|
|
|
106
106
|
if (unlockScriptType === UnlockScriptType.P2SH) {
|
|
107
107
|
let p2sh;
|
|
108
108
|
try {
|
|
109
|
-
p2sh = unlock_script_codec_1.unlockScriptCodec.decode(decoded).
|
|
109
|
+
p2sh = unlock_script_codec_1.unlockScriptCodec.decode(decoded).value;
|
|
110
110
|
}
|
|
111
111
|
catch (_) {
|
|
112
112
|
throw new Error(`Invalid p2sh unlock script: ${unlockScript}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alephium/web3",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "A JS/TS library to interact with the Alephium platform",
|
|
5
5
|
"license": "GPL",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"author": "Alephium dev <dev@alephium.org>",
|
|
35
35
|
"config": {
|
|
36
|
-
"alephium_version": "3.
|
|
36
|
+
"alephium_version": "3.5.2",
|
|
37
37
|
"explorer_backend_version": "2.0.0"
|
|
38
38
|
},
|
|
39
39
|
"type": "commonjs",
|
|
@@ -48,8 +48,7 @@
|
|
|
48
48
|
"elliptic": "6.5.4",
|
|
49
49
|
"eventemitter3": "^4.0.7",
|
|
50
50
|
"path-browserify": "^1.0.1",
|
|
51
|
-
"stream-browserify": "^3.0.0"
|
|
52
|
-
"binary-parser": "2.2.1"
|
|
51
|
+
"stream-browserify": "^3.0.0"
|
|
53
52
|
},
|
|
54
53
|
"devDependencies": {
|
|
55
54
|
"@babel/eslint-parser": "^7.21.3",
|
package/src/address/address.ts
CHANGED
|
@@ -22,10 +22,10 @@ import { TOTAL_NUMBER_OF_GROUPS } from '../constants'
|
|
|
22
22
|
import blake from 'blakejs'
|
|
23
23
|
import bs58 from '../utils/bs58'
|
|
24
24
|
import djb2 from '../utils/djb2'
|
|
25
|
-
import { binToHex, concatBytes, hexToBinUnsafe } from '../utils'
|
|
25
|
+
import { binToHex, concatBytes, hexToBinUnsafe, isHexString } from '../utils'
|
|
26
26
|
import { KeyType } from '../signer'
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
27
|
+
import { P2MPKH, lockupScriptCodec } from '../codec/lockup-script-codec'
|
|
28
|
+
import { i32Codec } from '../codec'
|
|
29
29
|
|
|
30
30
|
const ec = new EC('secp256k1')
|
|
31
31
|
const PublicKeyHashSize = 32
|
|
@@ -61,19 +61,19 @@ function decodeAndValidateAddress(address: string): Uint8Array {
|
|
|
61
61
|
if (decoded.length === 0) throw new Error('Address is empty')
|
|
62
62
|
const addressType = decoded[0]
|
|
63
63
|
if (addressType === AddressType.P2MPKH) {
|
|
64
|
-
let multisig:
|
|
64
|
+
let multisig: P2MPKH
|
|
65
65
|
try {
|
|
66
|
-
multisig = lockupScriptCodec.decode(decoded).
|
|
66
|
+
multisig = lockupScriptCodec.decode(decoded).value as P2MPKH
|
|
67
67
|
} catch (_) {
|
|
68
68
|
throw new Error(`Invalid multisig address: ${address}`)
|
|
69
69
|
}
|
|
70
|
-
const n = multisig.publicKeyHashes.
|
|
71
|
-
const m =
|
|
70
|
+
const n = multisig.publicKeyHashes.length
|
|
71
|
+
const m = multisig.m
|
|
72
72
|
if (n < m || m <= 0) {
|
|
73
73
|
throw new Error(`Invalid multisig address, n: ${n}, m: ${m}`)
|
|
74
74
|
}
|
|
75
|
-
const encodedNSize =
|
|
76
|
-
const encodedMSize =
|
|
75
|
+
const encodedNSize = i32Codec.encode(n).length
|
|
76
|
+
const encodedMSize = i32Codec.encode(m).length
|
|
77
77
|
const size = encodedNSize + PublicKeyHashSize * n + encodedMSize + 1 // 1 for the P2MPKH prefix
|
|
78
78
|
if (decoded.length === size) return decoded
|
|
79
79
|
} else if (addressType === AddressType.P2PKH || addressType === AddressType.P2SH || addressType === AddressType.P2C) {
|
|
@@ -211,6 +211,12 @@ export function subContractId(parentContractId: string, pathInHex: string, group
|
|
|
211
211
|
if (group < 0 || group >= TOTAL_NUMBER_OF_GROUPS) {
|
|
212
212
|
throw new Error(`Invalid group ${group}`)
|
|
213
213
|
}
|
|
214
|
+
if (!isHexString(parentContractId)) {
|
|
215
|
+
throw new Error(`Invalid parent contract ID: ${parentContractId}, expected hex string`)
|
|
216
|
+
}
|
|
217
|
+
if (!isHexString(pathInHex)) {
|
|
218
|
+
throw new Error(`Invalid path: ${pathInHex}, expected hex string`)
|
|
219
|
+
}
|
|
214
220
|
const data = concatBytes([hexToBinUnsafe(parentContractId), hexToBinUnsafe(pathInHex)])
|
|
215
221
|
const bytes = new Uint8Array([
|
|
216
222
|
...blake.blake2b(blake.blake2b(data, undefined, 32), undefined, 32).slice(0, -1),
|
package/src/api/api-alephium.ts
CHANGED
|
@@ -21,7 +21,6 @@ export interface AddressBalance {
|
|
|
21
21
|
lockedBalance: string
|
|
22
22
|
/** @format x.x ALPH */
|
|
23
23
|
lockedBalanceHint: string
|
|
24
|
-
warning?: string
|
|
25
24
|
}
|
|
26
25
|
|
|
27
26
|
/** AddressInfo */
|
|
@@ -93,7 +92,6 @@ export interface Balance {
|
|
|
93
92
|
lockedTokenBalances?: Token[]
|
|
94
93
|
/** @format int32 */
|
|
95
94
|
utxoNum: number
|
|
96
|
-
warning?: string
|
|
97
95
|
}
|
|
98
96
|
|
|
99
97
|
/** Balances */
|
|
@@ -527,6 +525,7 @@ export interface CompilerOptions {
|
|
|
527
525
|
ignoreUnusedPrivateFunctionsWarnings?: boolean
|
|
528
526
|
ignoreUpdateFieldsCheckWarnings?: boolean
|
|
529
527
|
ignoreCheckExternalCallerWarnings?: boolean
|
|
528
|
+
ignoreUnusedFunctionReturnWarnings?: boolean
|
|
530
529
|
}
|
|
531
530
|
|
|
532
531
|
/** Confirmed */
|
|
@@ -1146,7 +1145,6 @@ export interface UTXO {
|
|
|
1146
1145
|
/** UTXOs */
|
|
1147
1146
|
export interface UTXOs {
|
|
1148
1147
|
utxos: UTXO[]
|
|
1149
|
-
warning?: string
|
|
1150
1148
|
}
|
|
1151
1149
|
|
|
1152
1150
|
/** Unauthorized */
|
|
@@ -1495,7 +1493,7 @@ export class HttpClient<SecurityDataType = unknown> {
|
|
|
1495
1493
|
|
|
1496
1494
|
/**
|
|
1497
1495
|
* @title Alephium API
|
|
1498
|
-
* @version 3.
|
|
1496
|
+
* @version 3.5.2
|
|
1499
1497
|
* @baseUrl ../
|
|
1500
1498
|
*/
|
|
1501
1499
|
export class Api<SecurityDataType extends unknown> extends HttpClient<SecurityDataType> {
|
package/src/codec/array-codec.ts
CHANGED
|
@@ -15,48 +15,30 @@ 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 {
|
|
19
|
-
import { compactSignedIntCodec, DecodedCompactInt } from './compact-int-codec'
|
|
18
|
+
import { i32Codec } from './compact-int-codec'
|
|
20
19
|
import { Codec } from './codec'
|
|
20
|
+
import { Reader } from './reader'
|
|
21
|
+
import { concatBytes } from '../utils'
|
|
21
22
|
|
|
22
|
-
export
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class ArrayCodec<T> implements Codec<T[]> {
|
|
28
|
-
constructor(private childCodec: Codec<T>, public parser = ArrayCodec.arrayParser(childCodec.parser)) {}
|
|
23
|
+
export class ArrayCodec<T> extends Codec<T[]> {
|
|
24
|
+
constructor(private childCodec: Codec<T>) {
|
|
25
|
+
super()
|
|
26
|
+
}
|
|
29
27
|
|
|
30
28
|
encode(input: T[]): Uint8Array {
|
|
31
|
-
const
|
|
29
|
+
const bytes: Uint8Array[] = [i32Codec.encode(input.length)]
|
|
32
30
|
for (const element of input) {
|
|
33
|
-
|
|
31
|
+
bytes.push(this.childCodec.encode(element))
|
|
34
32
|
}
|
|
35
|
-
return
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
decode(input: Uint8Array): T[] {
|
|
39
|
-
const result = this.parser.parse(input)
|
|
40
|
-
return result.value.map((v) => this.childCodec.decode(v.value))
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
static arrayParser(parser: Parser) {
|
|
44
|
-
return new Parser()
|
|
45
|
-
.nest('length', {
|
|
46
|
-
type: compactSignedIntCodec.parser
|
|
47
|
-
})
|
|
48
|
-
.array('value', {
|
|
49
|
-
length: function (ctx) {
|
|
50
|
-
return compactSignedIntCodec.toI32(this['length']! as any as DecodedCompactInt)
|
|
51
|
-
},
|
|
52
|
-
type: parser
|
|
53
|
-
})
|
|
33
|
+
return concatBytes(bytes)
|
|
54
34
|
}
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
36
|
+
_decode(input: Reader): T[] {
|
|
37
|
+
const length = i32Codec._decode(input)
|
|
38
|
+
const array: T[] = []
|
|
39
|
+
for (let index = 0; index < length; index += 1) {
|
|
40
|
+
array.push(this.childCodec._decode(input))
|
|
60
41
|
}
|
|
42
|
+
return array
|
|
61
43
|
}
|
|
62
44
|
}
|
|
@@ -15,89 +15,54 @@ 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 {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import { longCodec } from './long-codec'
|
|
18
|
+
import { ArrayCodec } from './array-codec'
|
|
19
|
+
import { u256Codec } from './compact-int-codec'
|
|
20
|
+
import { intAs4BytesCodec } from './int-as-4bytes-codec'
|
|
21
|
+
import { timestampCodec } from './timestamp-codec'
|
|
23
22
|
import { ByteString, byteStringCodec } from './bytestring-codec'
|
|
24
|
-
import { LockupScript,
|
|
23
|
+
import { LockupScript, P2MPKH, P2PKH, P2SH, lockupScriptCodec } from './lockup-script-codec'
|
|
25
24
|
import { FixedAssetOutput } from '../api/api-alephium'
|
|
26
25
|
import { blakeHash, createHint } from './hash'
|
|
27
26
|
import { bs58, binToHex, hexToBinUnsafe, concatBytes } from '../utils'
|
|
28
|
-
import {
|
|
29
|
-
import { PublicKeyHash } from './lockup-script-codec'
|
|
27
|
+
import { ObjectCodec } from './codec'
|
|
30
28
|
import { Token, tokensCodec } from './token-codec'
|
|
31
29
|
|
|
32
30
|
export interface AssetOutput {
|
|
33
|
-
amount:
|
|
31
|
+
amount: bigint
|
|
34
32
|
lockupScript: LockupScript
|
|
35
|
-
lockTime:
|
|
36
|
-
tokens:
|
|
33
|
+
lockTime: bigint
|
|
34
|
+
tokens: Token[]
|
|
37
35
|
additionalData: ByteString
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
export class AssetOutputCodec
|
|
41
|
-
parser = Parser.start()
|
|
42
|
-
.nest('amount', {
|
|
43
|
-
type: compactSignedIntCodec.parser
|
|
44
|
-
})
|
|
45
|
-
.nest('lockupScript', {
|
|
46
|
-
type: lockupScriptCodec.parser
|
|
47
|
-
})
|
|
48
|
-
.buffer('lockTime', {
|
|
49
|
-
length: 8
|
|
50
|
-
})
|
|
51
|
-
.nest('tokens', {
|
|
52
|
-
type: tokensCodec.parser
|
|
53
|
-
})
|
|
54
|
-
.nest('additionalData', {
|
|
55
|
-
type: byteStringCodec.parser
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
encode(input: AssetOutput): Uint8Array {
|
|
59
|
-
const amount = compactUnsignedIntCodec.encode(input.amount)
|
|
60
|
-
const lockupScript = lockupScriptCodec.encode(input.lockupScript)
|
|
61
|
-
const tokens = tokensCodec.encode(input.tokens.value)
|
|
62
|
-
const additionalData = byteStringCodec.encode(input.additionalData)
|
|
63
|
-
|
|
64
|
-
return concatBytes([amount, lockupScript, input.lockTime, tokens, additionalData])
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
decode(input: Uint8Array): AssetOutput {
|
|
68
|
-
return this.parser.parse(input)
|
|
69
|
-
}
|
|
70
|
-
|
|
38
|
+
export class AssetOutputCodec extends ObjectCodec<AssetOutput> {
|
|
71
39
|
static toFixedAssetOutputs(txIdBytes: Uint8Array, outputs: AssetOutput[]): FixedAssetOutput[] {
|
|
72
40
|
return outputs.map((output, index) => AssetOutputCodec.toFixedAssetOutput(txIdBytes, output, index))
|
|
73
41
|
}
|
|
74
42
|
|
|
75
43
|
static toFixedAssetOutput(txIdBytes: Uint8Array, output: AssetOutput, index: number): FixedAssetOutput {
|
|
76
|
-
const attoAlphAmount =
|
|
77
|
-
const lockTime = Number(
|
|
78
|
-
const tokens = output.tokens.
|
|
44
|
+
const attoAlphAmount = output.amount.toString()
|
|
45
|
+
const lockTime = Number(output.lockTime)
|
|
46
|
+
const tokens = output.tokens.map((token) => {
|
|
79
47
|
return {
|
|
80
48
|
id: binToHex(token.tokenId),
|
|
81
|
-
amount:
|
|
49
|
+
amount: token.amount.toString()
|
|
82
50
|
}
|
|
83
51
|
})
|
|
84
|
-
const message = binToHex(output.additionalData
|
|
85
|
-
const scriptType = output.lockupScript.
|
|
86
|
-
const key = binToHex(blakeHash(concatBytes([txIdBytes,
|
|
87
|
-
const outputLockupScript = output.lockupScript.
|
|
52
|
+
const message = binToHex(output.additionalData)
|
|
53
|
+
const scriptType = output.lockupScript.kind
|
|
54
|
+
const key = binToHex(blakeHash(concatBytes([txIdBytes, intAs4BytesCodec.encode(index)])))
|
|
55
|
+
const outputLockupScript = output.lockupScript.value
|
|
88
56
|
const address = bs58.encode(lockupScriptCodec.encode(output.lockupScript))
|
|
89
57
|
|
|
90
58
|
let hint: number | undefined = undefined
|
|
91
|
-
if (scriptType ===
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
hint = createHint(
|
|
97
|
-
} else if (scriptType ===
|
|
98
|
-
// P2SH
|
|
99
|
-
hint = createHint((outputLockupScript as P2SH).scriptHash)
|
|
100
|
-
} else if (scriptType === 3) {
|
|
59
|
+
if (scriptType === 'P2PKH') {
|
|
60
|
+
hint = createHint(outputLockupScript as P2PKH)
|
|
61
|
+
} else if (scriptType === 'P2MPKH') {
|
|
62
|
+
hint = createHint((outputLockupScript as P2MPKH).publicKeyHashes[0])
|
|
63
|
+
} else if (scriptType === 'P2SH') {
|
|
64
|
+
hint = createHint(outputLockupScript as P2SH)
|
|
65
|
+
} else if (scriptType === 'P2C') {
|
|
101
66
|
throw new Error(`P2C script type not allowed for asset output`)
|
|
102
67
|
} else {
|
|
103
68
|
throw new Error(`Unexpected output script type: ${scriptType}`)
|
|
@@ -113,35 +78,25 @@ export class AssetOutputCodec implements Codec<AssetOutput> {
|
|
|
113
78
|
}
|
|
114
79
|
|
|
115
80
|
static fromFixedAssetOutput(fixedOutput: FixedAssetOutput): AssetOutput {
|
|
116
|
-
const amount
|
|
117
|
-
|
|
118
|
-
const lockTime = longCodec.encode(BigInt(fixedOutput.lockTime))
|
|
81
|
+
const amount = BigInt(fixedOutput.attoAlphAmount)
|
|
82
|
+
const lockTime = BigInt(fixedOutput.lockTime)
|
|
119
83
|
const lockupScript: LockupScript = lockupScriptCodec.decode(bs58.decode(fixedOutput.address))
|
|
120
|
-
const
|
|
84
|
+
const tokens = fixedOutput.tokens.map((token) => {
|
|
121
85
|
return {
|
|
122
86
|
tokenId: hexToBinUnsafe(token.id),
|
|
123
|
-
amount:
|
|
87
|
+
amount: BigInt(token.amount)
|
|
124
88
|
}
|
|
125
89
|
})
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
value: tokensValue
|
|
129
|
-
}
|
|
130
|
-
const additionalDataValue = hexToBinUnsafe(fixedOutput.message)
|
|
131
|
-
const additionalData: ByteString = {
|
|
132
|
-
length: compactSignedIntCodec.fromI32(additionalDataValue.length),
|
|
133
|
-
value: additionalDataValue
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return {
|
|
137
|
-
amount,
|
|
138
|
-
lockupScript,
|
|
139
|
-
lockTime,
|
|
140
|
-
tokens,
|
|
141
|
-
additionalData
|
|
142
|
-
}
|
|
90
|
+
const additionalData = hexToBinUnsafe(fixedOutput.message)
|
|
91
|
+
return { amount, lockupScript, lockTime, tokens, additionalData }
|
|
143
92
|
}
|
|
144
93
|
}
|
|
145
94
|
|
|
146
|
-
export const assetOutputCodec = new AssetOutputCodec(
|
|
95
|
+
export const assetOutputCodec = new AssetOutputCodec({
|
|
96
|
+
amount: u256Codec,
|
|
97
|
+
lockupScript: lockupScriptCodec,
|
|
98
|
+
lockTime: timestampCodec,
|
|
99
|
+
tokens: tokensCodec,
|
|
100
|
+
additionalData: byteStringCodec
|
|
101
|
+
})
|
|
147
102
|
export const assetOutputsCodec = new ArrayCodec(assetOutputCodec)
|
|
@@ -64,14 +64,28 @@ export class BigIntCodec {
|
|
|
64
64
|
return new Uint8Array(bytes.reverse())
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
static
|
|
67
|
+
static decodeUnsigned(encoded: Uint8Array): bigint {
|
|
68
|
+
// Special case for zero.
|
|
69
|
+
if (encoded.length === 1 && encoded[0] === 0) {
|
|
70
|
+
return 0n
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Convert the byte array to a bigint
|
|
74
|
+
let value = 0n
|
|
75
|
+
for (const byte of encoded) {
|
|
76
|
+
value = (value << 8n) | BigInt(byte)
|
|
77
|
+
}
|
|
78
|
+
return value
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
static decodeSigned(encoded: Uint8Array): bigint {
|
|
68
82
|
// Special case for zero.
|
|
69
83
|
if (encoded.length === 1 && encoded[0] === 0) {
|
|
70
84
|
return 0n
|
|
71
85
|
}
|
|
72
86
|
|
|
73
87
|
// Determine if the number is negative by checking the most significant byte (MSB)
|
|
74
|
-
const isNegative =
|
|
88
|
+
const isNegative = (encoded[0] & 0x80) !== 0
|
|
75
89
|
|
|
76
90
|
// Convert the byte array to a bigint
|
|
77
91
|
let value = 0n
|
|
@@ -15,42 +15,24 @@ 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 {
|
|
19
|
-
import { DecodedCompactInt, compactSignedIntCodec } from './compact-int-codec'
|
|
18
|
+
import { i32Codec } from './compact-int-codec'
|
|
20
19
|
import { Codec } from './codec'
|
|
21
20
|
import { concatBytes } from '../utils'
|
|
21
|
+
import { Reader } from './reader'
|
|
22
|
+
import { ArrayCodec } from './array-codec'
|
|
22
23
|
|
|
23
|
-
export
|
|
24
|
-
length: DecodedCompactInt
|
|
25
|
-
value: Uint8Array
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export class ByteStringCodec implements Codec<ByteString> {
|
|
29
|
-
parser = new Parser()
|
|
30
|
-
.nest('length', {
|
|
31
|
-
type: compactSignedIntCodec.parser
|
|
32
|
-
})
|
|
33
|
-
.buffer('value', {
|
|
34
|
-
length: function (ctx) {
|
|
35
|
-
return compactSignedIntCodec.toI32(this['length']! as any as DecodedCompactInt)
|
|
36
|
-
}
|
|
37
|
-
})
|
|
24
|
+
export type ByteString = Uint8Array
|
|
38
25
|
|
|
26
|
+
export class ByteStringCodec extends Codec<ByteString> {
|
|
39
27
|
encode(input: ByteString): Uint8Array {
|
|
40
|
-
return concatBytes([
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
decode(input: Uint8Array): ByteString {
|
|
44
|
-
return this.parser.parse(input)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
encodeBytes(input: Uint8Array): Uint8Array {
|
|
48
|
-
return concatBytes([compactSignedIntCodec.encodeI32(input.length), input])
|
|
28
|
+
return concatBytes([i32Codec.encode(input.length), input])
|
|
49
29
|
}
|
|
50
30
|
|
|
51
|
-
|
|
52
|
-
|
|
31
|
+
_decode(input: Reader): ByteString {
|
|
32
|
+
const length = i32Codec._decode(input)
|
|
33
|
+
return input.consumeBytes(length)
|
|
53
34
|
}
|
|
54
35
|
}
|
|
55
36
|
|
|
56
37
|
export const byteStringCodec = new ByteStringCodec()
|
|
38
|
+
export const byteStringsCodec = new ArrayCodec(byteStringCodec)
|
package/src/codec/codec.ts
CHANGED
|
@@ -15,12 +15,33 @@ 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
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
import { concatBytes } from '../utils'
|
|
20
|
+
import { Reader } from './reader'
|
|
21
|
+
|
|
22
|
+
export abstract class Codec<T> {
|
|
23
|
+
abstract encode(input: T): Uint8Array
|
|
24
|
+
decode(input: Uint8Array): T {
|
|
25
|
+
const reader = new Reader(input)
|
|
26
|
+
return this._decode(reader)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
abstract _decode(input: Reader): T
|
|
30
|
+
|
|
31
|
+
bimap<R>(from: (v: T) => R, to: (v: R) => T): Codec<R> {
|
|
32
|
+
return new (class extends Codec<R> {
|
|
33
|
+
constructor(private readonly codecT: Codec<T>) {
|
|
34
|
+
super()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
encode(input: R): Uint8Array {
|
|
38
|
+
return this.codecT.encode(to(input))
|
|
39
|
+
}
|
|
40
|
+
_decode(input: Reader): R {
|
|
41
|
+
return from(this.codecT._decode(input))
|
|
42
|
+
}
|
|
43
|
+
})(this)
|
|
44
|
+
}
|
|
24
45
|
}
|
|
25
46
|
|
|
26
47
|
export function assert(value: boolean, message: string) {
|
|
@@ -29,15 +50,100 @@ export function assert(value: boolean, message: string) {
|
|
|
29
50
|
}
|
|
30
51
|
}
|
|
31
52
|
|
|
32
|
-
export
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
53
|
+
export class FixedSizeCodec extends Codec<Uint8Array> {
|
|
54
|
+
constructor(private readonly size: number) {
|
|
55
|
+
super()
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
encode(input: Uint8Array): Uint8Array {
|
|
59
|
+
assert(input.length === this.size, `Invalid length, expected ${this.size}, got ${input.length}`)
|
|
60
|
+
return input
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_decode(input: Reader): Uint8Array {
|
|
64
|
+
return input.consumeBytes(this.size)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class ObjectCodec<T> extends Codec<T> {
|
|
69
|
+
private keys: (keyof T)[]
|
|
70
|
+
|
|
71
|
+
constructor(private codecs: { [K in keyof T]: Codec<T[K]> }) {
|
|
72
|
+
super()
|
|
73
|
+
this.keys = Object.keys(codecs) as (keyof T)[]
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
encode(value: T): Uint8Array {
|
|
77
|
+
const bytes: Uint8Array[] = []
|
|
78
|
+
for (const key of this.keys) {
|
|
79
|
+
bytes.push(this.codecs[key].encode(value[key]))
|
|
80
|
+
}
|
|
81
|
+
return concatBytes(bytes)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_decode(input: Reader): T {
|
|
85
|
+
const result: T = {} as T
|
|
86
|
+
for (const key of this.keys) {
|
|
87
|
+
result[key] = this.codecs[key]._decode(input)
|
|
41
88
|
}
|
|
42
|
-
|
|
89
|
+
return result as T
|
|
90
|
+
}
|
|
43
91
|
}
|
|
92
|
+
|
|
93
|
+
type ExtractKind<T> = T extends { kind: infer U extends string } ? U : never
|
|
94
|
+
type ExtractValue<T, K> = T extends { kind: K; value: infer V } ? V : never
|
|
95
|
+
|
|
96
|
+
export class EnumCodec<T extends { kind: ExtractKind<T>; value: ExtractValue<T, ExtractKind<T>> }> extends Codec<T> {
|
|
97
|
+
private kinds: ExtractKind<T>[]
|
|
98
|
+
|
|
99
|
+
constructor(private name: string, private codecs: { [K in ExtractKind<T>]: Codec<ExtractValue<T, K>> }) {
|
|
100
|
+
super()
|
|
101
|
+
this.kinds = Object.keys(codecs) as ExtractKind<T>[]
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
encode(value: T): Uint8Array {
|
|
105
|
+
const index = this.kinds.findIndex((t) => t === value.kind)
|
|
106
|
+
if (index === -1) {
|
|
107
|
+
throw new Error(`Invalid ${this.name} kind ${value.kind}, expected one of ${this.kinds}`)
|
|
108
|
+
}
|
|
109
|
+
const codec = this.codecs[value.kind]
|
|
110
|
+
return new Uint8Array([index, ...codec.encode(value.value)])
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
_decode(input: Reader): T {
|
|
114
|
+
const index = input.consumeByte()
|
|
115
|
+
if (index >= 0 && index < this.kinds.length) {
|
|
116
|
+
const kind = this.kinds[`${index}`]
|
|
117
|
+
const codec = this.codecs[kind as ExtractKind<T>]
|
|
118
|
+
return { kind, value: codec._decode(input) } as T
|
|
119
|
+
}
|
|
120
|
+
throw new Error(`Invalid encoded ${this.name} kind: ${index}`)
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const byte32Codec = new FixedSizeCodec(32)
|
|
125
|
+
export const byteCodec = new (class extends Codec<number> {
|
|
126
|
+
encode(input: number): Uint8Array {
|
|
127
|
+
assert(input >= 0 && input < 256, `Invalid byte: ${input}`)
|
|
128
|
+
return new Uint8Array([input])
|
|
129
|
+
}
|
|
130
|
+
_decode(input: Reader): number {
|
|
131
|
+
return input.consumeByte()
|
|
132
|
+
}
|
|
133
|
+
})()
|
|
134
|
+
|
|
135
|
+
export const boolCodec = new (class extends Codec<boolean> {
|
|
136
|
+
encode(input: boolean): Uint8Array {
|
|
137
|
+
return new Uint8Array([input ? 1 : 0])
|
|
138
|
+
}
|
|
139
|
+
_decode(input: Reader): boolean {
|
|
140
|
+
const byte = input.consumeByte()
|
|
141
|
+
if (byte === 1) {
|
|
142
|
+
return true
|
|
143
|
+
} else if (byte === 0) {
|
|
144
|
+
return false
|
|
145
|
+
} else {
|
|
146
|
+
throw new Error(`Invalid encoded bool value ${byte}, expected 0 or 1`)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
})()
|