@alephium/web3 1.4.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 +5 -5
- package/dist/src/api/api-alephium.d.ts +1 -1
- 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.js +6 -6
- 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 +8 -8
- package/src/api/api-alephium.ts +1 -1
- 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 +9 -13
- 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
|
@@ -16,9 +16,6 @@ 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 { DecodedArray } from './array-codec'
|
|
21
|
-
|
|
22
19
|
import { UnsignedTxCodec, UnsignedTx, unsignedTxCodec } from './unsigned-tx-codec'
|
|
23
20
|
import { Signature, signaturesCodec } from './signature-codec'
|
|
24
21
|
import { ContractOutputRef, contractOutputRefsCodec } from './contract-output-ref-codec'
|
|
@@ -26,61 +23,28 @@ import { Either } from './either-codec'
|
|
|
26
23
|
import { AssetOutput, AssetOutputCodec } from './asset-output-codec'
|
|
27
24
|
import { ContractOutput, ContractOutputCodec } from './contract-output-codec'
|
|
28
25
|
import { FixedAssetOutput, Transaction as ApiTransaction } from '../api/api-alephium'
|
|
29
|
-
import { binToHex, hexToBinUnsafe
|
|
26
|
+
import { binToHex, hexToBinUnsafe } from '../utils'
|
|
30
27
|
import { ContractOutput as ApiContractOutput } from '../api/api-alephium'
|
|
31
|
-
import {
|
|
28
|
+
import { byteCodec, ObjectCodec } from './codec'
|
|
32
29
|
import { Output, outputCodec, outputsCodec } from './output-codec'
|
|
33
30
|
|
|
34
31
|
export interface Transaction {
|
|
35
32
|
unsigned: UnsignedTx
|
|
36
33
|
scriptExecutionOk: number
|
|
37
|
-
contractInputs:
|
|
38
|
-
generatedOutputs:
|
|
39
|
-
inputSignatures:
|
|
40
|
-
scriptSignatures:
|
|
34
|
+
contractInputs: ContractOutputRef[]
|
|
35
|
+
generatedOutputs: Output[]
|
|
36
|
+
inputSignatures: Signature[]
|
|
37
|
+
scriptSignatures: Signature[]
|
|
41
38
|
}
|
|
42
39
|
|
|
43
|
-
export class TransactionCodec
|
|
44
|
-
parser = new Parser()
|
|
45
|
-
.nest('unsigned', {
|
|
46
|
-
type: unsignedTxCodec.parser
|
|
47
|
-
})
|
|
48
|
-
.uint8('scriptExecutionOk')
|
|
49
|
-
.nest('contractInputs', {
|
|
50
|
-
type: contractOutputRefsCodec.parser
|
|
51
|
-
})
|
|
52
|
-
.nest('generatedOutputs', {
|
|
53
|
-
type: outputsCodec.parser
|
|
54
|
-
})
|
|
55
|
-
.nest('inputSignatures', {
|
|
56
|
-
type: signaturesCodec.parser
|
|
57
|
-
})
|
|
58
|
-
.nest('scriptSignatures', {
|
|
59
|
-
type: signaturesCodec.parser
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
encode(decodedTx: Transaction): Uint8Array {
|
|
63
|
-
return concatBytes([
|
|
64
|
-
unsignedTxCodec.encode(decodedTx.unsigned),
|
|
65
|
-
new Uint8Array([decodedTx.scriptExecutionOk]),
|
|
66
|
-
contractOutputRefsCodec.encode(decodedTx.contractInputs.value),
|
|
67
|
-
outputsCodec.encode(decodedTx.generatedOutputs.value),
|
|
68
|
-
signaturesCodec.encode(decodedTx.inputSignatures.value),
|
|
69
|
-
signaturesCodec.encode(decodedTx.scriptSignatures.value)
|
|
70
|
-
])
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
decode(input: Uint8Array): Transaction {
|
|
74
|
-
return this.parser.parse(input)
|
|
75
|
-
}
|
|
76
|
-
|
|
40
|
+
export class TransactionCodec extends ObjectCodec<Transaction> {
|
|
77
41
|
encodeApiTransaction(input: ApiTransaction): Uint8Array {
|
|
78
42
|
const decodedTx = TransactionCodec.fromApiTransaction(input)
|
|
79
43
|
return this.encode(decodedTx)
|
|
80
44
|
}
|
|
81
45
|
|
|
82
46
|
decodeApiTransaction(input: Uint8Array): ApiTransaction {
|
|
83
|
-
const decodedTx = this.
|
|
47
|
+
const decodedTx = this.decode(input)
|
|
84
48
|
return TransactionCodec.toApiTransaction(decodedTx)
|
|
85
49
|
}
|
|
86
50
|
|
|
@@ -88,14 +52,14 @@ export class TransactionCodec implements Codec<Transaction> {
|
|
|
88
52
|
const txId = UnsignedTxCodec.txId(transaction.unsigned)
|
|
89
53
|
const unsigned = UnsignedTxCodec.toApiUnsignedTx(transaction.unsigned)
|
|
90
54
|
const scriptExecutionOk = !!transaction.scriptExecutionOk
|
|
91
|
-
const contractInputs = transaction.contractInputs.
|
|
55
|
+
const contractInputs = transaction.contractInputs.map((contractInput) => {
|
|
92
56
|
const hint = contractInput.hint
|
|
93
57
|
const key = binToHex(contractInput.key)
|
|
94
58
|
return { hint, key }
|
|
95
59
|
})
|
|
96
60
|
const txIdBytes = hexToBinUnsafe(txId)
|
|
97
|
-
const generatedOutputs = transaction.generatedOutputs.
|
|
98
|
-
if (output.
|
|
61
|
+
const generatedOutputs = transaction.generatedOutputs.map((output, index) => {
|
|
62
|
+
if (output.kind === 'Left') {
|
|
99
63
|
const fixedAssetOutput = AssetOutputCodec.toFixedAssetOutput(txIdBytes, output.value as AssetOutput, index)
|
|
100
64
|
return { ...fixedAssetOutput, type: 'AssetOutput' }
|
|
101
65
|
} else {
|
|
@@ -103,8 +67,8 @@ export class TransactionCodec implements Codec<Transaction> {
|
|
|
103
67
|
}
|
|
104
68
|
})
|
|
105
69
|
|
|
106
|
-
const inputSignatures = transaction.inputSignatures.
|
|
107
|
-
const scriptSignatures = transaction.scriptSignatures.
|
|
70
|
+
const inputSignatures = transaction.inputSignatures.map((signature) => binToHex(signature))
|
|
71
|
+
const scriptSignatures = transaction.scriptSignatures.map((signature) => binToHex(signature))
|
|
108
72
|
|
|
109
73
|
return { unsigned, scriptExecutionOk, contractInputs, generatedOutputs, inputSignatures, scriptSignatures }
|
|
110
74
|
}
|
|
@@ -117,30 +81,37 @@ export class TransactionCodec implements Codec<Transaction> {
|
|
|
117
81
|
})
|
|
118
82
|
const generatedOutputs: Either<AssetOutput, ContractOutput>[] = tx.generatedOutputs.map((output) => {
|
|
119
83
|
if (output.type === 'AssetOutput') {
|
|
120
|
-
return
|
|
84
|
+
return { kind: 'Left', value: AssetOutputCodec.fromFixedAssetOutput(output as FixedAssetOutput) }
|
|
121
85
|
} else if (output.type === 'ContractOutput') {
|
|
122
|
-
return
|
|
86
|
+
return { kind: 'Right', value: ContractOutputCodec.convertToOutput(output as ApiContractOutput) }
|
|
123
87
|
} else {
|
|
124
88
|
throw new Error('Invalid output type')
|
|
125
89
|
}
|
|
126
90
|
})
|
|
127
91
|
|
|
128
92
|
const inputSignatures: Signature[] = tx.inputSignatures.map((signature) => {
|
|
129
|
-
return
|
|
93
|
+
return hexToBinUnsafe(signature)
|
|
130
94
|
})
|
|
131
95
|
const scriptSignatures: Signature[] = tx.scriptSignatures.map((signature) => {
|
|
132
|
-
return
|
|
96
|
+
return hexToBinUnsafe(signature)
|
|
133
97
|
})
|
|
134
98
|
|
|
135
99
|
return {
|
|
136
100
|
unsigned,
|
|
137
101
|
scriptExecutionOk,
|
|
138
|
-
contractInputs:
|
|
139
|
-
generatedOutputs:
|
|
140
|
-
inputSignatures:
|
|
141
|
-
scriptSignatures:
|
|
102
|
+
contractInputs: contractInputs,
|
|
103
|
+
generatedOutputs: generatedOutputs,
|
|
104
|
+
inputSignatures: inputSignatures,
|
|
105
|
+
scriptSignatures: scriptSignatures
|
|
142
106
|
}
|
|
143
107
|
}
|
|
144
108
|
}
|
|
145
109
|
|
|
146
|
-
export const transactionCodec = new TransactionCodec(
|
|
110
|
+
export const transactionCodec = new TransactionCodec({
|
|
111
|
+
unsigned: unsignedTxCodec,
|
|
112
|
+
scriptExecutionOk: byteCodec,
|
|
113
|
+
contractInputs: contractOutputRefsCodec,
|
|
114
|
+
generatedOutputs: outputsCodec,
|
|
115
|
+
inputSignatures: signaturesCodec,
|
|
116
|
+
scriptSignatures: signaturesCodec
|
|
117
|
+
})
|
|
@@ -15,179 +15,52 @@ 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 {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
publicKey: Uint8Array
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
class P2PKHCodec implements Codec<P2PKH> {
|
|
32
|
-
parser = fixedSizeBytes('publicKey', 33)
|
|
33
|
-
|
|
34
|
-
encode(input: P2PKH): Uint8Array {
|
|
35
|
-
return input.publicKey
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
decode(input: Uint8Array): P2PKH {
|
|
39
|
-
return this.parser.parse(input)
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const p2pkhCodec = new P2PKHCodec()
|
|
43
|
-
|
|
44
|
-
export interface P2MPKH {
|
|
45
|
-
publicKeys: DecodedArray<{
|
|
46
|
-
publicKey: P2PKH
|
|
47
|
-
index: DecodedCompactInt
|
|
48
|
-
}>
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
class P2MPKHCodec implements Codec<P2MPKH> {
|
|
52
|
-
parser = Parser.start().nest('publicKeys', {
|
|
53
|
-
type: ArrayCodec.arrayParser(
|
|
54
|
-
Parser.start()
|
|
55
|
-
.nest('publicKey', { type: p2pkhCodec.parser })
|
|
56
|
-
.nest('index', { type: compactUnsignedIntCodec.parser })
|
|
57
|
-
)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
encode(input: P2MPKH): Uint8Array {
|
|
61
|
-
return concatBytes([
|
|
62
|
-
compactUnsignedIntCodec.encode(input.publicKeys.length),
|
|
63
|
-
...input.publicKeys.value.map((v) => {
|
|
64
|
-
return concatBytes([v.publicKey.publicKey, compactUnsignedIntCodec.encode(v.index)])
|
|
65
|
-
})
|
|
66
|
-
])
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
decode(input: Uint8Array): any {
|
|
70
|
-
return this.parser.parse(input)
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const p2mpkhCodec = new P2MPKHCodec()
|
|
74
|
-
|
|
75
|
-
export interface Val {
|
|
76
|
-
type: number
|
|
77
|
-
val: number | DecodedCompactInt | ByteString | LockupScript
|
|
78
|
-
}
|
|
79
|
-
class ValCodec implements Codec<Val> {
|
|
80
|
-
parser = Parser.start()
|
|
81
|
-
.int8('type')
|
|
82
|
-
.choice('val', {
|
|
83
|
-
tag: 'type',
|
|
84
|
-
choices: {
|
|
85
|
-
0x00: new Parser().uint8('value'), // Boolean
|
|
86
|
-
0x01: compactSignedIntCodec.parser, // I256
|
|
87
|
-
0x02: compactUnsignedIntCodec.parser, // U256
|
|
88
|
-
0x03: byteStringCodec.parser, // ByteVec
|
|
89
|
-
0x04: lockupScriptCodec.parser // Address
|
|
90
|
-
}
|
|
91
|
-
})
|
|
92
|
-
|
|
93
|
-
encode(input: Val): Uint8Array {
|
|
94
|
-
const valType = input.type
|
|
95
|
-
|
|
96
|
-
if (valType === 0x00) {
|
|
97
|
-
// Boolean
|
|
98
|
-
return new Uint8Array([valType, input.val as number])
|
|
99
|
-
} else if (valType === 0x01) {
|
|
100
|
-
// I256
|
|
101
|
-
return new Uint8Array([valType, ...compactUnsignedIntCodec.encode(input.val as DecodedCompactInt)])
|
|
102
|
-
} else if (valType === 0x02) {
|
|
103
|
-
// U256
|
|
104
|
-
return new Uint8Array([valType, ...compactUnsignedIntCodec.encode(input.val as DecodedCompactInt)])
|
|
105
|
-
} else if (valType === 0x03) {
|
|
106
|
-
// ByteVec
|
|
107
|
-
return new Uint8Array([valType, ...byteStringCodec.encode(input.val as ByteString)])
|
|
108
|
-
} else if (valType === 0x04) {
|
|
109
|
-
// Address
|
|
110
|
-
return new Uint8Array([valType, ...lockupScriptCodec.encode(input.val as LockupScript)])
|
|
111
|
-
} else {
|
|
112
|
-
throw new Error(`ValCodec: unsupported val type: ${valType}`)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
decode(input: Uint8Array): Val {
|
|
117
|
-
return this.parser.parse(input)
|
|
118
|
-
}
|
|
18
|
+
import { ArrayCodec } from './array-codec'
|
|
19
|
+
import { i32Codec } from './compact-int-codec'
|
|
20
|
+
import { Codec, EnumCodec, FixedSizeCodec, ObjectCodec } from './codec'
|
|
21
|
+
import { Script, scriptCodec } from './script-codec'
|
|
22
|
+
import { Val, valsCodec } from './val'
|
|
23
|
+
|
|
24
|
+
export type P2PKH = Uint8Array
|
|
25
|
+
export interface KeyWithIndex {
|
|
26
|
+
publicKey: P2PKH
|
|
27
|
+
index: number
|
|
119
28
|
}
|
|
120
|
-
|
|
121
|
-
const valCodec = new ValCodec()
|
|
122
|
-
const valsCodec = new ArrayCodec(valCodec)
|
|
123
|
-
|
|
29
|
+
export type P2MPKH = KeyWithIndex[]
|
|
124
30
|
export interface P2SH {
|
|
125
|
-
script:
|
|
126
|
-
params:
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
export class P2SHCodec implements Codec<P2SH> {
|
|
130
|
-
parser = Parser.start()
|
|
131
|
-
.nest('script', {
|
|
132
|
-
type: scriptCodec.parser
|
|
133
|
-
})
|
|
134
|
-
.nest('params', {
|
|
135
|
-
type: valsCodec.parser
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
encode(input: P2SH): Uint8Array {
|
|
139
|
-
return concatBytes([scriptCodec.encode(input.script), valsCodec.encode(input.params.value)])
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
decode(input: Uint8Array): P2SH {
|
|
143
|
-
return this.parser.parse(input)
|
|
144
|
-
}
|
|
31
|
+
script: Script
|
|
32
|
+
params: Val[]
|
|
145
33
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
encode(input: UnlockScript): Uint8Array {
|
|
168
|
-
const scriptType = input.scriptType
|
|
169
|
-
const inputUnLockScript = input.script
|
|
170
|
-
|
|
171
|
-
if (scriptType === 0) {
|
|
172
|
-
// P2PKH
|
|
173
|
-
return new Uint8Array([scriptType, ...p2pkhCodec.encode(inputUnLockScript as P2PKH)])
|
|
174
|
-
} else if (scriptType === 1) {
|
|
175
|
-
// P2MPKH
|
|
176
|
-
return new Uint8Array([scriptType, ...p2mpkhCodec.encode(inputUnLockScript as P2MPKH)])
|
|
177
|
-
} else if (scriptType === 2) {
|
|
178
|
-
// P2SH
|
|
179
|
-
return new Uint8Array([scriptType, ...p2shCodec.encode(inputUnLockScript as P2SH)])
|
|
180
|
-
} else if (scriptType === 3) {
|
|
181
|
-
// SameAsPrevious
|
|
182
|
-
return new Uint8Array([scriptType])
|
|
183
|
-
} else {
|
|
184
|
-
throw new Error(`TODO: encode unlock script: ${scriptType}`)
|
|
185
|
-
}
|
|
34
|
+
export type SameAsPrevious = 'SameAsPrevious'
|
|
35
|
+
|
|
36
|
+
export type UnlockScript =
|
|
37
|
+
| { kind: 'P2PKH'; value: P2PKH }
|
|
38
|
+
| { kind: 'P2MPKH'; value: P2MPKH }
|
|
39
|
+
| { kind: 'P2SH'; value: P2SH }
|
|
40
|
+
| { kind: 'SameAsPrevious'; value: SameAsPrevious }
|
|
41
|
+
|
|
42
|
+
const p2pkhCodec = new FixedSizeCodec(33)
|
|
43
|
+
const keyWithIndexCodec = new ObjectCodec<KeyWithIndex>({
|
|
44
|
+
publicKey: p2pkhCodec,
|
|
45
|
+
index: i32Codec
|
|
46
|
+
})
|
|
47
|
+
const p2mpkhCodec: Codec<P2MPKH> = new ArrayCodec(keyWithIndexCodec)
|
|
48
|
+
const p2shCodec = new ObjectCodec<P2SH>({
|
|
49
|
+
script: scriptCodec,
|
|
50
|
+
params: valsCodec
|
|
51
|
+
})
|
|
52
|
+
const sameAsPreviousCodec = new (class extends Codec<SameAsPrevious> {
|
|
53
|
+
encode(): Uint8Array {
|
|
54
|
+
return new Uint8Array([])
|
|
186
55
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
return this.parser.parse(input)
|
|
56
|
+
_decode(): SameAsPrevious {
|
|
57
|
+
return 'SameAsPrevious'
|
|
190
58
|
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export const unlockScriptCodec = new
|
|
59
|
+
})()
|
|
60
|
+
|
|
61
|
+
export const unlockScriptCodec = new EnumCodec<UnlockScript>('unlock script', {
|
|
62
|
+
P2PKH: p2pkhCodec,
|
|
63
|
+
P2MPKH: p2mpkhCodec,
|
|
64
|
+
P2SH: p2shCodec,
|
|
65
|
+
SameAsPrevious: sameAsPreviousCodec
|
|
66
|
+
})
|
|
@@ -15,70 +15,34 @@ 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 { UnsignedTx as ApiUnsignedTx } from '../api/api-alephium'
|
|
20
|
-
import { binToHex,
|
|
21
|
-
import {
|
|
19
|
+
import { binToHex, hexToBinUnsafe } from '../utils'
|
|
20
|
+
import { Script, scriptCodec, statefulScriptCodecOpt } from './script-codec'
|
|
22
21
|
import { Option } from './option-codec'
|
|
23
|
-
import {
|
|
22
|
+
import { i32Codec, u256Codec } from './compact-int-codec'
|
|
24
23
|
import { Input, InputCodec, inputsCodec } from './input-codec'
|
|
25
24
|
import { AssetOutput, AssetOutputCodec, assetOutputsCodec } from './asset-output-codec'
|
|
26
|
-
import { DecodedArray } from './array-codec'
|
|
27
25
|
import { blakeHash } from './hash'
|
|
28
|
-
import {
|
|
26
|
+
import { byteCodec, ObjectCodec } from './codec'
|
|
29
27
|
|
|
30
28
|
export interface UnsignedTx {
|
|
31
29
|
version: number
|
|
32
30
|
networkId: number
|
|
33
|
-
statefulScript: Option<
|
|
34
|
-
gasAmount:
|
|
35
|
-
gasPrice:
|
|
36
|
-
inputs:
|
|
37
|
-
fixedOutputs:
|
|
31
|
+
statefulScript: Option<Script>
|
|
32
|
+
gasAmount: number
|
|
33
|
+
gasPrice: bigint
|
|
34
|
+
inputs: Input[]
|
|
35
|
+
fixedOutputs: AssetOutput[]
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
export class UnsignedTxCodec
|
|
41
|
-
parser = new Parser()
|
|
42
|
-
.uint8('version')
|
|
43
|
-
.uint8('networkId')
|
|
44
|
-
.nest('statefulScript', {
|
|
45
|
-
type: statefulScriptCodecOpt.parser
|
|
46
|
-
})
|
|
47
|
-
.nest('gasAmount', {
|
|
48
|
-
type: compactSignedIntCodec.parser
|
|
49
|
-
})
|
|
50
|
-
.nest('gasPrice', {
|
|
51
|
-
type: compactUnsignedIntCodec.parser
|
|
52
|
-
})
|
|
53
|
-
.nest('inputs', {
|
|
54
|
-
type: inputsCodec.parser
|
|
55
|
-
})
|
|
56
|
-
.nest('fixedOutputs', {
|
|
57
|
-
type: assetOutputsCodec.parser
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
encode(decodedUnsignedTx: UnsignedTx): Uint8Array {
|
|
61
|
-
return concatBytes([
|
|
62
|
-
new Uint8Array([decodedUnsignedTx.version, decodedUnsignedTx.networkId]),
|
|
63
|
-
statefulScriptCodecOpt.encode(decodedUnsignedTx.statefulScript),
|
|
64
|
-
compactSignedIntCodec.encode(decodedUnsignedTx.gasAmount),
|
|
65
|
-
compactUnsignedIntCodec.encode(decodedUnsignedTx.gasPrice),
|
|
66
|
-
inputsCodec.encode(decodedUnsignedTx.inputs.value),
|
|
67
|
-
assetOutputsCodec.encode(decodedUnsignedTx.fixedOutputs.value)
|
|
68
|
-
])
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
decode(input: Uint8Array): UnsignedTx {
|
|
72
|
-
return this.parser.parse(input)
|
|
73
|
-
}
|
|
74
|
-
|
|
38
|
+
export class UnsignedTxCodec extends ObjectCodec<UnsignedTx> {
|
|
75
39
|
encodeApiUnsignedTx(input: ApiUnsignedTx): Uint8Array {
|
|
76
40
|
const decoded = UnsignedTxCodec.fromApiUnsignedTx(input)
|
|
77
41
|
return this.encode(decoded)
|
|
78
42
|
}
|
|
79
43
|
|
|
80
44
|
decodeApiUnsignedTx(input: Uint8Array): ApiUnsignedTx {
|
|
81
|
-
const decoded = this.
|
|
45
|
+
const decoded = this.decode(input)
|
|
82
46
|
return UnsignedTxCodec.toApiUnsignedTx(decoded)
|
|
83
47
|
}
|
|
84
48
|
|
|
@@ -91,13 +55,13 @@ export class UnsignedTxCodec implements Codec<UnsignedTx> {
|
|
|
91
55
|
const txIdBytes = hexToBinUnsafe(txId)
|
|
92
56
|
const version = unsigned.version
|
|
93
57
|
const networkId = unsigned.networkId
|
|
94
|
-
const gasAmount =
|
|
95
|
-
const gasPrice =
|
|
96
|
-
const inputs = InputCodec.toAssetInputs(unsigned.inputs
|
|
97
|
-
const fixedOutputs = AssetOutputCodec.toFixedAssetOutputs(txIdBytes, unsigned.fixedOutputs
|
|
58
|
+
const gasAmount = unsigned.gasAmount
|
|
59
|
+
const gasPrice = unsigned.gasPrice.toString()
|
|
60
|
+
const inputs = InputCodec.toAssetInputs(unsigned.inputs)
|
|
61
|
+
const fixedOutputs = AssetOutputCodec.toFixedAssetOutputs(txIdBytes, unsigned.fixedOutputs)
|
|
98
62
|
let scriptOpt: string | undefined = undefined
|
|
99
|
-
if (unsigned.statefulScript.
|
|
100
|
-
scriptOpt = binToHex(scriptCodec.encode(unsigned.statefulScript.value
|
|
63
|
+
if (unsigned.statefulScript.kind === 'Some') {
|
|
64
|
+
scriptOpt = binToHex(scriptCodec.encode(unsigned.statefulScript.value))
|
|
101
65
|
}
|
|
102
66
|
|
|
103
67
|
return { txId, version, networkId, gasAmount, scriptOpt, gasPrice, inputs, fixedOutputs }
|
|
@@ -106,18 +70,25 @@ export class UnsignedTxCodec implements Codec<UnsignedTx> {
|
|
|
106
70
|
static fromApiUnsignedTx(unsignedTx: ApiUnsignedTx): UnsignedTx {
|
|
107
71
|
const version = unsignedTx.version
|
|
108
72
|
const networkId = unsignedTx.networkId
|
|
109
|
-
const gasAmount =
|
|
110
|
-
const gasPrice =
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
73
|
+
const gasAmount = unsignedTx.gasAmount
|
|
74
|
+
const gasPrice = BigInt(unsignedTx.gasPrice)
|
|
75
|
+
const inputs = InputCodec.fromAssetInputs(unsignedTx.inputs)
|
|
76
|
+
const fixedOutputs = AssetOutputCodec.fromFixedAssetOutputs(unsignedTx.fixedOutputs)
|
|
77
|
+
const statefulScript: Option<Script> =
|
|
78
|
+
unsignedTx.scriptOpt !== undefined
|
|
79
|
+
? { kind: 'Some', value: scriptCodec.decode(hexToBinUnsafe(unsignedTx.scriptOpt)) }
|
|
80
|
+
: { kind: 'None', value: undefined }
|
|
118
81
|
|
|
119
82
|
return { version, networkId, gasAmount, gasPrice, inputs, fixedOutputs, statefulScript }
|
|
120
83
|
}
|
|
121
84
|
}
|
|
122
85
|
|
|
123
|
-
export const unsignedTxCodec = new UnsignedTxCodec(
|
|
86
|
+
export const unsignedTxCodec = new UnsignedTxCodec({
|
|
87
|
+
version: byteCodec,
|
|
88
|
+
networkId: byteCodec,
|
|
89
|
+
statefulScript: statefulScriptCodecOpt,
|
|
90
|
+
gasAmount: i32Codec,
|
|
91
|
+
gasPrice: u256Codec,
|
|
92
|
+
inputs: inputsCodec,
|
|
93
|
+
fixedOutputs: assetOutputsCodec
|
|
94
|
+
})
|
package/src/codec/val.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
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
|
+
|
|
19
|
+
import { i256Codec, u256Codec } from './compact-int-codec'
|
|
20
|
+
import { ByteString, byteStringCodec } from './bytestring-codec'
|
|
21
|
+
import { boolCodec, EnumCodec } from './codec'
|
|
22
|
+
import { LockupScript, lockupScriptCodec } from './lockup-script-codec'
|
|
23
|
+
import { ArrayCodec } from './array-codec'
|
|
24
|
+
|
|
25
|
+
export type ValBool = { kind: 'Bool'; value: boolean }
|
|
26
|
+
export type ValI256 = { kind: 'I256'; value: bigint }
|
|
27
|
+
export type ValU256 = { kind: 'U256'; value: bigint }
|
|
28
|
+
export type ValByteVec = { kind: 'ByteVec'; value: ByteString }
|
|
29
|
+
export type ValAddress = { kind: 'Address'; value: LockupScript }
|
|
30
|
+
|
|
31
|
+
export type Val = ValBool | ValI256 | ValU256 | ValByteVec | ValAddress
|
|
32
|
+
|
|
33
|
+
export const valCodec = new EnumCodec<Val>('val', {
|
|
34
|
+
Bool: boolCodec,
|
|
35
|
+
I256: i256Codec,
|
|
36
|
+
U256: u256Codec,
|
|
37
|
+
ByteVec: byteStringCodec,
|
|
38
|
+
Address: lockupScriptCodec
|
|
39
|
+
})
|
|
40
|
+
export const valsCodec = new ArrayCodec(valCodec)
|
package/src/contract/contract.ts
CHANGED
|
@@ -64,8 +64,6 @@ import * as blake from 'blakejs'
|
|
|
64
64
|
import { isContractDebugMessageEnabled } from '../debug'
|
|
65
65
|
import {
|
|
66
66
|
contract,
|
|
67
|
-
compactUnsignedIntCodec,
|
|
68
|
-
compactSignedIntCodec,
|
|
69
67
|
Method,
|
|
70
68
|
LoadLocal,
|
|
71
69
|
LoadImmFieldByIndex,
|
|
@@ -86,7 +84,8 @@ import {
|
|
|
86
84
|
CallExternal,
|
|
87
85
|
Dup,
|
|
88
86
|
CallerAddress,
|
|
89
|
-
|
|
87
|
+
i32Codec,
|
|
88
|
+
BytesConst
|
|
90
89
|
} from '../codec'
|
|
91
90
|
|
|
92
91
|
const crypto = new WebCrypto()
|
|
@@ -1737,6 +1736,10 @@ function getBytecodeTemplate(
|
|
|
1737
1736
|
const argsLength = '00'
|
|
1738
1737
|
const returnsLength = '00'
|
|
1739
1738
|
|
|
1739
|
+
if (methodUsePreapprovedAssets && !scriptUseApprovedAssets) {
|
|
1740
|
+
throw new Error('The contract call requires preapproved assets but none are provided')
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1740
1743
|
const [templateVarStoreLocalInstrs, templateVarsLength] = getTemplateVarStoreLocalInstrs(functionSig, structs)
|
|
1741
1744
|
|
|
1742
1745
|
const approveAlphInstrs: string[] = getApproveAlphInstrs(methodUsePreapprovedAssets ? attoAlphAmount : undefined)
|
|
@@ -1805,14 +1808,7 @@ function getApproveTokensInstrs(tokens?: Token[]): string[] {
|
|
|
1805
1808
|
if (tokens) {
|
|
1806
1809
|
tokens.forEach((token) => {
|
|
1807
1810
|
const tokenIdBin = hexToBinUnsafe(token.id)
|
|
1808
|
-
approveTokensInstrs.push(
|
|
1809
|
-
encodeInstr(
|
|
1810
|
-
ByteConst({
|
|
1811
|
-
length: compactSignedIntCodec.fromI32(tokenIdBin.length),
|
|
1812
|
-
value: tokenIdBin
|
|
1813
|
-
})
|
|
1814
|
-
)
|
|
1815
|
-
)
|
|
1811
|
+
approveTokensInstrs.push(encodeInstr(BytesConst(tokenIdBin)))
|
|
1816
1812
|
approveTokensInstrs.push(encodeU256Const(BigInt(token.amount)))
|
|
1817
1813
|
approveTokensInstrs.push(encodeInstr(ApproveToken))
|
|
1818
1814
|
})
|
|
@@ -1899,7 +1895,7 @@ function encodeLoadLocalInstr(index: number): string {
|
|
|
1899
1895
|
}
|
|
1900
1896
|
|
|
1901
1897
|
function encodeI32(value: number): string {
|
|
1902
|
-
return binToHex(
|
|
1898
|
+
return binToHex(i32Codec.encode(value))
|
|
1903
1899
|
}
|
|
1904
1900
|
|
|
1905
1901
|
function encodeU256Const(value: bigint): string {
|
|
@@ -1910,7 +1906,7 @@ function encodeU256Const(value: bigint): string {
|
|
|
1910
1906
|
if (value < 6) {
|
|
1911
1907
|
return (BigInt(0x0c) + value).toString(16).padStart(2, '0')
|
|
1912
1908
|
} else {
|
|
1913
|
-
return encodeInstr(U256Const(
|
|
1909
|
+
return encodeInstr(U256Const(value))
|
|
1914
1910
|
}
|
|
1915
1911
|
}
|
|
1916
1912
|
|
package/src/contract/index.ts
CHANGED