@smartledger/bsv 3.1.0 → 3.2.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/CHANGELOG.md +123 -1
- package/README.md +233 -277
- package/bsv.bundle.js +39 -0
- package/bsv.min.js +8 -8
- package/docs/ADVANCED_COVENANT_DEVELOPMENT.md +533 -0
- package/docs/COVENANT_DEVELOPMENT_RESOLVED.md +169 -0
- package/docs/CUSTOM_SCRIPT_DEVELOPMENT.md +320 -0
- package/docs/README.md +201 -0
- package/docs/block.md +46 -0
- package/docs/ecies.md +102 -0
- package/docs/index.md +104 -0
- package/docs/nchain.md +958 -0
- package/docs/networks.md +55 -0
- package/docs/preimage.md +126 -0
- package/docs/script.md +139 -0
- package/docs/transaction.md +174 -0
- package/docs/unspentoutput.md +32 -0
- package/examples/README.md +200 -0
- package/examples/basic/transaction-creation.js +534 -0
- package/examples/basic/transaction_signature_api_gap.js +178 -0
- package/examples/covenants/advanced_covenant_demo.js +219 -0
- package/examples/covenants/covenant_interface_demo.js +270 -0
- package/examples/covenants/covenant_manual_signature_resolved.js +212 -0
- package/examples/covenants/covenant_signature_template.js +117 -0
- package/examples/covenants2/covenant_bidirectional_example.js +262 -0
- package/examples/covenants2/covenant_utils_demo.js +120 -0
- package/examples/covenants2/preimage_covenant_utils.js +287 -0
- package/examples/covenants2/production_integration.js +256 -0
- package/examples/data/covenant_utxos.json +28 -0
- package/examples/data/utxos.json +26 -0
- package/examples/preimage/README.md +178 -0
- package/examples/preimage/extract_preimage_bidirectional.js +421 -0
- package/examples/preimage/generate_sample_preimage.js +208 -0
- package/examples/preimage/generate_sighash_examples.js +152 -0
- package/examples/preimage/parse_preimage.js +117 -0
- package/examples/preimage/test_preimage_extractor.js +53 -0
- package/examples/preimage/test_varint_extraction.js +95 -0
- package/examples/scripts/custom_script_helper_example.js +273 -0
- package/examples/scripts/custom_script_signature_test.js +344 -0
- package/examples/scripts/script_interpreter.js +193 -0
- package/examples/smart_contract/complete_workflow_demo.js +343 -0
- package/examples/smart_contract/covenant_builder_demo.js +176 -0
- package/examples/smart_contract/script_testing_integration.js +198 -0
- package/index.js +3 -0
- package/lib/covenant-interface.js +713 -0
- package/lib/opcode.js +14 -7
- package/lib/smart_contract/API_REFERENCE.md +754 -0
- package/lib/smart_contract/DOCUMENTATION_SUMMARY.md +201 -0
- package/lib/smart_contract/EXAMPLES.md +751 -0
- package/lib/smart_contract/QUICK_START.md +549 -0
- package/lib/smart_contract/README.md +395 -0
- package/lib/smart_contract/builder.js +452 -0
- package/lib/smart_contract/covenant.js +336 -0
- package/lib/smart_contract/covenant_builder.js +512 -0
- package/lib/smart_contract/index.js +311 -0
- package/lib/smart_contract/opcode_list.js +30 -0
- package/lib/smart_contract/opcode_map.js +1174 -0
- package/lib/smart_contract/opcodes.md +1173 -0
- package/lib/smart_contract/preimage.js +903 -0
- package/lib/smart_contract/script_tester.js +487 -0
- package/lib/smart_contract/script_utils.js +609 -0
- package/lib/smart_contract/sighash.js +310 -0
- package/lib/smart_contract/smartledger-opcode_review.md +70 -0
- package/lib/smart_contract/test_integration.js +269 -0
- package/lib/smart_contract/utxo_generator.js +367 -0
- package/package.json +43 -10
- package/utilities/blockchain-state.json +20478 -3
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SmartContract.Builder Class
|
|
3
|
+
* ============================
|
|
4
|
+
*
|
|
5
|
+
* Advanced covenant builder with:
|
|
6
|
+
* - Multi-field preimage validation
|
|
7
|
+
* - Dynamic script construction
|
|
8
|
+
* - Template-based covenant creation
|
|
9
|
+
* - Complex condition chaining
|
|
10
|
+
*
|
|
11
|
+
* Based on examples/covenants2/covenant_bidirectional_example.js
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
'use strict'
|
|
15
|
+
|
|
16
|
+
var bsv = require('../..')
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Builder Class - Advanced covenant construction
|
|
20
|
+
* @param {PrivateKey} privateKey - Private key for covenant operations
|
|
21
|
+
* @param {Object} options - Configuration options
|
|
22
|
+
*/
|
|
23
|
+
function Builder(privateKey, options) {
|
|
24
|
+
if (!(this instanceof Builder)) {
|
|
25
|
+
return new Builder(privateKey, options)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
this.privateKey = privateKey
|
|
29
|
+
this.publicKey = privateKey ? privateKey.publicKey : null
|
|
30
|
+
this.options = options || {}
|
|
31
|
+
|
|
32
|
+
// Builder state
|
|
33
|
+
this.conditions = []
|
|
34
|
+
this.preimageFields = []
|
|
35
|
+
this.scriptTemplate = null
|
|
36
|
+
this.validationRules = []
|
|
37
|
+
|
|
38
|
+
this.sighashType = this.options.sighashType ||
|
|
39
|
+
(bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Add preimage field validation
|
|
44
|
+
* @param {string} field - Preimage field name
|
|
45
|
+
* @param {string|Buffer} expectedValue - Expected value or validation rule
|
|
46
|
+
* @param {Object} options - Validation options
|
|
47
|
+
* @returns {Builder} Builder instance for chaining
|
|
48
|
+
*/
|
|
49
|
+
Builder.prototype.validateField = function(field, expectedValue, options) {
|
|
50
|
+
options = options || {}
|
|
51
|
+
|
|
52
|
+
var validation = {
|
|
53
|
+
field: field,
|
|
54
|
+
expectedValue: expectedValue,
|
|
55
|
+
operator: options.operator || 'EQUAL',
|
|
56
|
+
required: options.required !== false,
|
|
57
|
+
description: options.description || 'Validate ' + field
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.validationRules.push(validation)
|
|
61
|
+
return this
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Add custom script condition
|
|
66
|
+
* @param {string|Function} condition - Script opcode or custom function
|
|
67
|
+
* @param {Object} options - Condition options
|
|
68
|
+
* @returns {Builder} Builder instance for chaining
|
|
69
|
+
*/
|
|
70
|
+
Builder.prototype.addCondition = function(condition, options) {
|
|
71
|
+
options = options || {}
|
|
72
|
+
|
|
73
|
+
var conditionObj = {
|
|
74
|
+
type: typeof condition === 'function' ? 'CUSTOM' : 'OPCODE',
|
|
75
|
+
condition: condition,
|
|
76
|
+
description: options.description || 'Custom condition',
|
|
77
|
+
required: options.required !== false
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
this.conditions.push(conditionObj)
|
|
81
|
+
return this
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Set script template for covenant construction
|
|
86
|
+
* @param {string} template - Script template name or custom script
|
|
87
|
+
* @param {Object} params - Template parameters
|
|
88
|
+
* @returns {Builder} Builder instance for chaining
|
|
89
|
+
*/
|
|
90
|
+
Builder.prototype.useTemplate = function(template, params) {
|
|
91
|
+
this.scriptTemplate = {
|
|
92
|
+
name: template,
|
|
93
|
+
params: params || {},
|
|
94
|
+
customScript: typeof template === 'object' ? template : null
|
|
95
|
+
}
|
|
96
|
+
return this
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Build covenant locking script
|
|
101
|
+
* @param {Object} preimageData - Preimage data for validation setup
|
|
102
|
+
* @returns {Script} Constructed locking script
|
|
103
|
+
*/
|
|
104
|
+
Builder.prototype.buildLockingScript = function(preimageData) {
|
|
105
|
+
var script = new bsv.Script()
|
|
106
|
+
|
|
107
|
+
if (this.scriptTemplate) {
|
|
108
|
+
return this._buildFromTemplate(preimageData)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Default multi-field validation covenant
|
|
112
|
+
return this._buildMultiFieldCovenant(preimageData)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Build unlocking script for spending covenant
|
|
117
|
+
* @param {Transaction} spendingTx - Transaction being signed
|
|
118
|
+
* @param {number} inputIndex - Input index
|
|
119
|
+
* @param {Object} covenantData - Original covenant data
|
|
120
|
+
* @returns {Script} Constructed unlocking script
|
|
121
|
+
*/
|
|
122
|
+
Builder.prototype.buildUnlockingScript = function(spendingTx, inputIndex, covenantData) {
|
|
123
|
+
var script = new bsv.Script()
|
|
124
|
+
|
|
125
|
+
// Add signature
|
|
126
|
+
var covenantScript = bsv.Script.fromHex(covenantData.script)
|
|
127
|
+
var signature = bsv.Transaction.sighash.sign(
|
|
128
|
+
spendingTx,
|
|
129
|
+
this.privateKey,
|
|
130
|
+
this.sighashType,
|
|
131
|
+
inputIndex,
|
|
132
|
+
covenantScript,
|
|
133
|
+
new bsv.crypto.BN(covenantData.satoshis)
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
var fullSignature = Buffer.concat([
|
|
137
|
+
signature.toDER(),
|
|
138
|
+
Buffer.from([this.sighashType])
|
|
139
|
+
])
|
|
140
|
+
|
|
141
|
+
script.add(fullSignature)
|
|
142
|
+
|
|
143
|
+
// Add preimage if required
|
|
144
|
+
if (covenantData.originalPreimage) {
|
|
145
|
+
script.add(Buffer.from(covenantData.originalPreimage, 'hex'))
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Add any additional unlock conditions
|
|
149
|
+
this.conditions.forEach(function(condition) {
|
|
150
|
+
if (condition.type === 'UNLOCK_DATA') {
|
|
151
|
+
script.add(condition.data)
|
|
152
|
+
}
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
return script
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Create complete covenant from P2PKH
|
|
160
|
+
* @param {Object} utxo - P2PKH UTXO
|
|
161
|
+
* @param {Object} buildOptions - Build options
|
|
162
|
+
* @returns {Object} Created covenant with metadata
|
|
163
|
+
*/
|
|
164
|
+
Builder.prototype.createCovenant = function(utxo, buildOptions) {
|
|
165
|
+
buildOptions = buildOptions || {}
|
|
166
|
+
|
|
167
|
+
// Create covenant creation transaction
|
|
168
|
+
var creationTx = new bsv.Transaction()
|
|
169
|
+
.from({
|
|
170
|
+
txId: utxo.txid,
|
|
171
|
+
outputIndex: utxo.vout,
|
|
172
|
+
script: utxo.script,
|
|
173
|
+
satoshis: utxo.satoshis
|
|
174
|
+
})
|
|
175
|
+
.to(this.privateKey.toAddress(), utxo.satoshis - (buildOptions.fee || 1000))
|
|
176
|
+
|
|
177
|
+
// Generate creation preimage
|
|
178
|
+
var p2pkhScript = bsv.Script.fromHex(utxo.script)
|
|
179
|
+
var creationPreimage = bsv.Transaction.sighash.sighashPreimage(
|
|
180
|
+
creationTx,
|
|
181
|
+
this.sighashType,
|
|
182
|
+
0,
|
|
183
|
+
p2pkhScript,
|
|
184
|
+
new bsv.crypto.BN(utxo.satoshis)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
// Extract preimage fields for covenant construction
|
|
188
|
+
var Preimage = require('./preimage')
|
|
189
|
+
var preimageObj = new Preimage(creationPreimage)
|
|
190
|
+
var preimageFields = preimageObj.extract()
|
|
191
|
+
|
|
192
|
+
// Build covenant locking script
|
|
193
|
+
var covenantScript = this.buildLockingScript({
|
|
194
|
+
preimage: creationPreimage,
|
|
195
|
+
fields: preimageFields,
|
|
196
|
+
transaction: creationTx
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
// Update transaction output
|
|
200
|
+
creationTx.outputs[0].setScript(covenantScript)
|
|
201
|
+
|
|
202
|
+
// Sign creation transaction
|
|
203
|
+
creationTx.sign(this.privateKey)
|
|
204
|
+
|
|
205
|
+
var covenantUtxo = {
|
|
206
|
+
txid: creationTx.id,
|
|
207
|
+
vout: 0,
|
|
208
|
+
satoshis: utxo.satoshis - (buildOptions.fee || 1000),
|
|
209
|
+
script: covenantScript.toHex(),
|
|
210
|
+
originalPreimage: creationPreimage.toString('hex'),
|
|
211
|
+
preimageFields: preimageFields,
|
|
212
|
+
validationRules: this.validationRules.slice(), // Copy rules
|
|
213
|
+
conditions: this.conditions.slice(), // Copy conditions
|
|
214
|
+
template: this.scriptTemplate,
|
|
215
|
+
createdAt: new Date().toISOString(),
|
|
216
|
+
type: 'builder_covenant'
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return {
|
|
220
|
+
creationTx: creationTx,
|
|
221
|
+
covenantUtxo: covenantUtxo,
|
|
222
|
+
lockingScript: covenantScript,
|
|
223
|
+
preimageData: {
|
|
224
|
+
preimage: creationPreimage,
|
|
225
|
+
fields: preimageFields
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Validate covenant spending transaction
|
|
232
|
+
* @param {Transaction} spendingTx - Transaction to validate
|
|
233
|
+
* @param {Object} covenantUtxo - Original covenant UTXO
|
|
234
|
+
* @returns {Object} Validation result
|
|
235
|
+
*/
|
|
236
|
+
Builder.prototype.validateSpending = function(spendingTx, covenantUtxo) {
|
|
237
|
+
var validation = {
|
|
238
|
+
valid: true,
|
|
239
|
+
errors: [],
|
|
240
|
+
warnings: [],
|
|
241
|
+
fieldValidations: []
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Generate spending preimage
|
|
245
|
+
var covenantScript = bsv.Script.fromHex(covenantUtxo.script)
|
|
246
|
+
var spendingPreimage = bsv.Transaction.sighash.sighashPreimage(
|
|
247
|
+
spendingTx,
|
|
248
|
+
this.sighashType,
|
|
249
|
+
0,
|
|
250
|
+
covenantScript,
|
|
251
|
+
new bsv.crypto.BN(covenantUtxo.satoshis)
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
var Preimage = require('./preimage')
|
|
255
|
+
var preimageObj = new Preimage(spendingPreimage)
|
|
256
|
+
var spendingFields = preimageObj.extract()
|
|
257
|
+
|
|
258
|
+
// Validate against original rules
|
|
259
|
+
if (covenantUtxo.validationRules) {
|
|
260
|
+
covenantUtxo.validationRules.forEach(function(rule) {
|
|
261
|
+
var fieldValidation = this._validateFieldRule(rule, spendingFields, covenantUtxo.preimageFields)
|
|
262
|
+
validation.fieldValidations.push(fieldValidation)
|
|
263
|
+
|
|
264
|
+
if (!fieldValidation.passed && rule.required) {
|
|
265
|
+
validation.valid = false
|
|
266
|
+
validation.errors.push(fieldValidation.error)
|
|
267
|
+
}
|
|
268
|
+
}.bind(this))
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Run Script.Interpreter validation
|
|
272
|
+
var interpreter = new bsv.Script.Interpreter()
|
|
273
|
+
var flags = bsv.Script.Interpreter.SCRIPT_VERIFY_P2SH |
|
|
274
|
+
bsv.Script.Interpreter.SCRIPT_VERIFY_STRICTENC |
|
|
275
|
+
bsv.Script.Interpreter.SCRIPT_VERIFY_DERSIG |
|
|
276
|
+
bsv.Script.Interpreter.SCRIPT_VERIFY_LOW_S |
|
|
277
|
+
bsv.Script.Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID
|
|
278
|
+
|
|
279
|
+
var unlockingScript = spendingTx.inputs[0].script
|
|
280
|
+
var lockingScript = bsv.Script.fromHex(covenantUtxo.script)
|
|
281
|
+
|
|
282
|
+
var interpreterResult = interpreter.verify(
|
|
283
|
+
unlockingScript,
|
|
284
|
+
lockingScript,
|
|
285
|
+
spendingTx,
|
|
286
|
+
0,
|
|
287
|
+
flags,
|
|
288
|
+
new bsv.crypto.BN(covenantUtxo.satoshis)
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
if (!interpreterResult) {
|
|
292
|
+
validation.valid = false
|
|
293
|
+
validation.errors.push('Script interpreter validation failed: ' + interpreter.errstr)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
return validation
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Private helper methods
|
|
301
|
+
*/
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Build covenant from template
|
|
305
|
+
* @private
|
|
306
|
+
*/
|
|
307
|
+
Builder.prototype._buildFromTemplate = function(preimageData) {
|
|
308
|
+
var template = this.scriptTemplate
|
|
309
|
+
|
|
310
|
+
if (template.name === 'HASH_LOCK') {
|
|
311
|
+
return this._buildHashLockTemplate(preimageData, template.params)
|
|
312
|
+
} else if (template.name === 'MULTI_FIELD') {
|
|
313
|
+
return this._buildMultiFieldTemplate(preimageData, template.params)
|
|
314
|
+
} else if (template.customScript) {
|
|
315
|
+
return template.customScript
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
throw new Error('Unknown template: ' + template.name)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Build multi-field validation covenant
|
|
323
|
+
* @private
|
|
324
|
+
*/
|
|
325
|
+
Builder.prototype._buildMultiFieldCovenant = function(preimageData) {
|
|
326
|
+
var script = new bsv.Script()
|
|
327
|
+
|
|
328
|
+
// Duplicate preimage for multiple validations
|
|
329
|
+
script.add('OP_DUP')
|
|
330
|
+
|
|
331
|
+
// Add field validation opcodes based on rules
|
|
332
|
+
this.validationRules.forEach(function(rule, index) {
|
|
333
|
+
if (index > 0) script.add('OP_DUP') // Duplicate for next validation
|
|
334
|
+
|
|
335
|
+
script.add('OP_HASH256')
|
|
336
|
+
|
|
337
|
+
if (rule.expectedValue) {
|
|
338
|
+
var expectedHash = bsv.crypto.Hash.sha256sha256(Buffer.from(rule.expectedValue, 'hex'))
|
|
339
|
+
script.add(expectedHash)
|
|
340
|
+
script.add('OP_EQUALVERIFY')
|
|
341
|
+
}
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
// Clean up stack and add signature check
|
|
345
|
+
script.add('OP_DROP')
|
|
346
|
+
|
|
347
|
+
if (this.publicKey) {
|
|
348
|
+
script.add(this.publicKey.toBuffer())
|
|
349
|
+
script.add('OP_CHECKSIG')
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return script
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Build hash lock template
|
|
357
|
+
* @private
|
|
358
|
+
*/
|
|
359
|
+
Builder.prototype._buildHashLockTemplate = function(preimageData, params) {
|
|
360
|
+
var script = new bsv.Script()
|
|
361
|
+
|
|
362
|
+
script.add('OP_DUP')
|
|
363
|
+
script.add('OP_HASH256')
|
|
364
|
+
|
|
365
|
+
var expectedHash = params.hash || bsv.crypto.Hash.sha256sha256(preimageData.preimage)
|
|
366
|
+
script.add(expectedHash)
|
|
367
|
+
script.add('OP_EQUALVERIFY')
|
|
368
|
+
script.add('OP_DROP')
|
|
369
|
+
|
|
370
|
+
if (this.publicKey) {
|
|
371
|
+
script.add(this.publicKey.toBuffer())
|
|
372
|
+
script.add('OP_CHECKSIG')
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return script
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Validate individual field rule
|
|
380
|
+
* @private
|
|
381
|
+
*/
|
|
382
|
+
Builder.prototype._validateFieldRule = function(rule, spendingFields, originalFields) {
|
|
383
|
+
var fieldValue = spendingFields[rule.field]
|
|
384
|
+
var expectedValue = rule.expectedValue
|
|
385
|
+
|
|
386
|
+
// If expected value references original field
|
|
387
|
+
if (typeof expectedValue === 'string' && expectedValue.startsWith('ORIGINAL_')) {
|
|
388
|
+
var originalField = expectedValue.replace('ORIGINAL_', '')
|
|
389
|
+
expectedValue = originalFields[originalField]
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
var passed = false
|
|
393
|
+
var error = null
|
|
394
|
+
|
|
395
|
+
switch (rule.operator) {
|
|
396
|
+
case 'EQUAL':
|
|
397
|
+
passed = fieldValue && fieldValue.equals ? fieldValue.equals(expectedValue) : fieldValue === expectedValue
|
|
398
|
+
if (!passed) error = rule.field + ' does not equal expected value'
|
|
399
|
+
break
|
|
400
|
+
case 'NOT_EQUAL':
|
|
401
|
+
passed = fieldValue && fieldValue.equals ? !fieldValue.equals(expectedValue) : fieldValue !== expectedValue
|
|
402
|
+
if (!passed) error = rule.field + ' should not equal specified value'
|
|
403
|
+
break
|
|
404
|
+
case 'PRESENT':
|
|
405
|
+
passed = !!fieldValue
|
|
406
|
+
if (!passed) error = rule.field + ' is required but not present'
|
|
407
|
+
break
|
|
408
|
+
default:
|
|
409
|
+
error = 'Unknown validation operator: ' + rule.operator
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
return {
|
|
413
|
+
field: rule.field,
|
|
414
|
+
operator: rule.operator,
|
|
415
|
+
passed: passed,
|
|
416
|
+
error: error,
|
|
417
|
+
description: rule.description
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
/**
|
|
422
|
+
* Static utility methods
|
|
423
|
+
*/
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Create simple hash-lock covenant builder
|
|
427
|
+
* @param {PrivateKey} privateKey - Private key for covenant
|
|
428
|
+
* @param {Buffer} expectedHash - Expected preimage hash
|
|
429
|
+
* @returns {Builder} Configured builder
|
|
430
|
+
*/
|
|
431
|
+
Builder.createHashLock = function(privateKey, expectedHash) {
|
|
432
|
+
return new Builder(privateKey)
|
|
433
|
+
.useTemplate('HASH_LOCK', { hash: expectedHash })
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Create multi-field validation covenant builder
|
|
438
|
+
* @param {PrivateKey} privateKey - Private key for covenant
|
|
439
|
+
* @param {Array} fieldRules - Array of field validation rules
|
|
440
|
+
* @returns {Builder} Configured builder
|
|
441
|
+
*/
|
|
442
|
+
Builder.createMultiField = function(privateKey, fieldRules) {
|
|
443
|
+
var builder = new Builder(privateKey)
|
|
444
|
+
|
|
445
|
+
fieldRules.forEach(function(rule) {
|
|
446
|
+
builder.validateField(rule.field, rule.expectedValue, rule.options)
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
return builder
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
module.exports = Builder
|