@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
|
@@ -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()
|
|
@@ -112,7 +111,8 @@ export const DEFAULT_NODE_COMPILER_OPTIONS: node.CompilerOptions = {
|
|
|
112
111
|
ignoreUnusedFieldsWarnings: false,
|
|
113
112
|
ignoreUnusedPrivateFunctionsWarnings: false,
|
|
114
113
|
ignoreUpdateFieldsCheckWarnings: false,
|
|
115
|
-
ignoreCheckExternalCallerWarnings: false
|
|
114
|
+
ignoreCheckExternalCallerWarnings: false,
|
|
115
|
+
ignoreUnusedFunctionReturnWarnings: false
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { errorOnWarnings: true, ...DEFAULT_NODE_COMPILER_OPTIONS }
|
|
@@ -1010,6 +1010,12 @@ export abstract class ContractFactory<I extends ContractInstance, F extends Fiel
|
|
|
1010
1010
|
}
|
|
1011
1011
|
}
|
|
1012
1012
|
|
|
1013
|
+
async deployTemplate(signer: SignerProvider): Promise<DeployContractResult<I>> {
|
|
1014
|
+
return this.deploy(signer, {
|
|
1015
|
+
initialFields: this.contract.getInitialFieldsWithDefaultValues() as F
|
|
1016
|
+
})
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1013
1019
|
// This is used for testing contract functions
|
|
1014
1020
|
stateForTest(initFields: F, asset?: Asset, address?: string): ContractState<F> {
|
|
1015
1021
|
const newAsset = {
|
|
@@ -1681,10 +1687,10 @@ export async function signExecuteMethod<I extends ContractInstance, F extends Fi
|
|
|
1681
1687
|
): Promise<SignExecuteScriptTxResult> {
|
|
1682
1688
|
const methodIndex = contract.contract.getMethodIndex(methodName)
|
|
1683
1689
|
const functionSig = contract.contract.functions[methodIndex]
|
|
1684
|
-
const
|
|
1690
|
+
const methodUsePreapprovedAssets = contract.contract.decodedMethods[methodIndex].usePreapprovedAssets
|
|
1685
1691
|
const bytecodeTemplate = getBytecodeTemplate(
|
|
1686
1692
|
methodIndex,
|
|
1687
|
-
|
|
1693
|
+
methodUsePreapprovedAssets,
|
|
1688
1694
|
functionSig,
|
|
1689
1695
|
contract.contract.structs,
|
|
1690
1696
|
params.attoAlphAmount,
|
|
@@ -1716,7 +1722,7 @@ export async function signExecuteMethod<I extends ContractInstance, F extends Fi
|
|
|
1716
1722
|
|
|
1717
1723
|
function getBytecodeTemplate(
|
|
1718
1724
|
methodIndex: number,
|
|
1719
|
-
|
|
1725
|
+
methodUsePreapprovedAssets: boolean,
|
|
1720
1726
|
functionSig: FunctionSig,
|
|
1721
1727
|
structs: Struct[],
|
|
1722
1728
|
attoAlphAmount?: Number256,
|
|
@@ -1725,14 +1731,19 @@ function getBytecodeTemplate(
|
|
|
1725
1731
|
// For the default TxScript main function
|
|
1726
1732
|
const numberOfMethods = '01'
|
|
1727
1733
|
const isPublic = '01'
|
|
1728
|
-
const
|
|
1734
|
+
const scriptUseApprovedAssets = attoAlphAmount !== undefined || tokens !== undefined
|
|
1735
|
+
const modifier = scriptUseApprovedAssets ? '03' : '00'
|
|
1729
1736
|
const argsLength = '00'
|
|
1730
1737
|
const returnsLength = '00'
|
|
1731
1738
|
|
|
1739
|
+
if (methodUsePreapprovedAssets && !scriptUseApprovedAssets) {
|
|
1740
|
+
throw new Error('The contract call requires preapproved assets but none are provided')
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1732
1743
|
const [templateVarStoreLocalInstrs, templateVarsLength] = getTemplateVarStoreLocalInstrs(functionSig, structs)
|
|
1733
1744
|
|
|
1734
|
-
const approveAlphInstrs: string[] = getApproveAlphInstrs(
|
|
1735
|
-
const approveTokensInstrs: string[] = getApproveTokensInstrs(
|
|
1745
|
+
const approveAlphInstrs: string[] = getApproveAlphInstrs(methodUsePreapprovedAssets ? attoAlphAmount : undefined)
|
|
1746
|
+
const approveTokensInstrs: string[] = getApproveTokensInstrs(methodUsePreapprovedAssets ? tokens : undefined)
|
|
1736
1747
|
const callerInstrs: string[] = getCallAddressInstrs(approveAlphInstrs.length / 2 + approveTokensInstrs.length / 3)
|
|
1737
1748
|
|
|
1738
1749
|
// First template var is the contract
|
|
@@ -1797,14 +1808,7 @@ function getApproveTokensInstrs(tokens?: Token[]): string[] {
|
|
|
1797
1808
|
if (tokens) {
|
|
1798
1809
|
tokens.forEach((token) => {
|
|
1799
1810
|
const tokenIdBin = hexToBinUnsafe(token.id)
|
|
1800
|
-
approveTokensInstrs.push(
|
|
1801
|
-
encodeInstr(
|
|
1802
|
-
ByteConst({
|
|
1803
|
-
length: compactSignedIntCodec.fromI32(tokenIdBin.length),
|
|
1804
|
-
value: tokenIdBin
|
|
1805
|
-
})
|
|
1806
|
-
)
|
|
1807
|
-
)
|
|
1811
|
+
approveTokensInstrs.push(encodeInstr(BytesConst(tokenIdBin)))
|
|
1808
1812
|
approveTokensInstrs.push(encodeU256Const(BigInt(token.amount)))
|
|
1809
1813
|
approveTokensInstrs.push(encodeInstr(ApproveToken))
|
|
1810
1814
|
})
|
|
@@ -1891,7 +1895,7 @@ function encodeLoadLocalInstr(index: number): string {
|
|
|
1891
1895
|
}
|
|
1892
1896
|
|
|
1893
1897
|
function encodeI32(value: number): string {
|
|
1894
|
-
return binToHex(
|
|
1898
|
+
return binToHex(i32Codec.encode(value))
|
|
1895
1899
|
}
|
|
1896
1900
|
|
|
1897
1901
|
function encodeU256Const(value: bigint): string {
|
|
@@ -1902,7 +1906,7 @@ function encodeU256Const(value: bigint): string {
|
|
|
1902
1906
|
if (value < 6) {
|
|
1903
1907
|
return (BigInt(0x0c) + value).toString(16).padStart(2, '0')
|
|
1904
1908
|
} else {
|
|
1905
|
-
return encodeInstr(U256Const(
|
|
1909
|
+
return encodeInstr(U256Const(value))
|
|
1906
1910
|
}
|
|
1907
1911
|
}
|
|
1908
1912
|
|