@xyo-network/xl1-validation 1.7.16
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/LICENSE +165 -0
- package/README.md +250 -0
- package/dist/neutral/boundwitness/index.d.ts +2 -0
- package/dist/neutral/boundwitness/index.d.ts.map +1 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessReferences.d.ts +5 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessReferences.d.ts.map +1 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessSignatures.d.ts +3 -0
- package/dist/neutral/boundwitness/validators/BoundWitnessSignatures.d.ts.map +1 -0
- package/dist/neutral/boundwitness/validators/index.d.ts +3 -0
- package/dist/neutral/boundwitness/validators/index.d.ts.map +1 -0
- package/dist/neutral/index.d.ts +3 -0
- package/dist/neutral/index.d.ts.map +1 -0
- package/dist/neutral/index.mjs +258 -0
- package/dist/neutral/index.mjs.map +1 -0
- package/dist/neutral/transaction/index.d.ts +3 -0
- package/dist/neutral/transaction/index.d.ts.map +1 -0
- package/dist/neutral/transaction/validateTransaction.d.ts +4 -0
- package/dist/neutral/transaction/validateTransaction.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/TransactionDurationValidator.d.ts +3 -0
- package/dist/neutral/transaction/validators/TransactionDurationValidator.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/TransactionElevationValidator.d.ts +3 -0
- package/dist/neutral/transaction/validators/TransactionElevationValidator.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/TransactionFromValidator.d.ts +3 -0
- package/dist/neutral/transaction/validators/TransactionFromValidator.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/TransactionGasValidator.d.ts +3 -0
- package/dist/neutral/transaction/validators/TransactionGasValidator.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/TransactionJsonSchemaValidator.d.ts +3 -0
- package/dist/neutral/transaction/validators/TransactionJsonSchemaValidator.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/TransactionProtocolValidator.d.ts +3 -0
- package/dist/neutral/transaction/validators/TransactionProtocolValidator.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/index.d.ts +7 -0
- package/dist/neutral/transaction/validators/index.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/spec/TransactionDurationValidator.spec.d.ts +2 -0
- package/dist/neutral/transaction/validators/spec/TransactionDurationValidator.spec.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/spec/TransactionElevationValidator.spec.d.ts +2 -0
- package/dist/neutral/transaction/validators/spec/TransactionElevationValidator.spec.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/spec/TransactionFromValidator.spec.d.ts +2 -0
- package/dist/neutral/transaction/validators/spec/TransactionFromValidator.spec.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/spec/TransactionGasValidator.spec.d.ts +2 -0
- package/dist/neutral/transaction/validators/spec/TransactionGasValidator.spec.d.ts.map +1 -0
- package/dist/neutral/transaction/validators/spec/TransactionJsonSchemaValidator.spec.d.ts +2 -0
- package/dist/neutral/transaction/validators/spec/TransactionJsonSchemaValidator.spec.d.ts.map +1 -0
- package/package.json +75 -0
- package/src/boundwitness/index.ts +1 -0
- package/src/boundwitness/validators/BoundWitnessReferences.ts +57 -0
- package/src/boundwitness/validators/BoundWitnessSignatures.ts +28 -0
- package/src/boundwitness/validators/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/transaction/index.ts +2 -0
- package/src/transaction/validateTransaction.ts +33 -0
- package/src/transaction/validators/TransactionDurationValidator.ts +33 -0
- package/src/transaction/validators/TransactionElevationValidator.ts +27 -0
- package/src/transaction/validators/TransactionFromValidator.ts +33 -0
- package/src/transaction/validators/TransactionGasValidator.ts +97 -0
- package/src/transaction/validators/TransactionJsonSchemaValidator.ts +34 -0
- package/src/transaction/validators/TransactionProtocolValidator.ts +20 -0
- package/src/transaction/validators/index.ts +6 -0
- package/src/transaction/validators/spec/TransactionDurationValidator.spec.ts +49 -0
- package/src/transaction/validators/spec/TransactionElevationValidator.spec.ts +39 -0
- package/src/transaction/validators/spec/TransactionFromValidator.spec.ts +43 -0
- package/src/transaction/validators/spec/TransactionGasValidator.spec.ts +88 -0
- package/src/transaction/validators/spec/TransactionJsonSchemaValidator.spec.ts +33 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Address } from '@xylabs/hex'
|
|
2
|
+
import type { HydratedTransaction, HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import { isTransactionBoundWitness } from '@xyo-network/xl1-protocol'
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
TransactionDurationValidator,
|
|
7
|
+
TransactionElevationValidator, TransactionFromValidator, TransactionGasValidator, TransactionJsonSchemaValidator, TransactionProtocolValidator,
|
|
8
|
+
} from './validators/index.ts'
|
|
9
|
+
|
|
10
|
+
export async function validateTransaction(
|
|
11
|
+
tx: HydratedTransaction,
|
|
12
|
+
chainId?: Address,
|
|
13
|
+
additionalValidators: HydratedTransactionValidationFunction[] = [],
|
|
14
|
+
) {
|
|
15
|
+
try {
|
|
16
|
+
if (!isTransactionBoundWitness(tx[0])) {
|
|
17
|
+
return [new Error('failed isTransactionBoundWitness identity check')]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const validators: HydratedTransactionValidationFunction[] = [
|
|
21
|
+
TransactionProtocolValidator,
|
|
22
|
+
TransactionJsonSchemaValidator,
|
|
23
|
+
TransactionDurationValidator,
|
|
24
|
+
TransactionFromValidator,
|
|
25
|
+
TransactionGasValidator,
|
|
26
|
+
TransactionElevationValidator,
|
|
27
|
+
...additionalValidators,
|
|
28
|
+
]
|
|
29
|
+
return (await Promise.all(validators.map(v => v(tx, chainId)))).flat()
|
|
30
|
+
} catch (ex) {
|
|
31
|
+
return [(new Error(`Failed TransactionGasValidator: ${ex}`))]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import type {
|
|
3
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
4
|
+
} from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
6
|
+
|
|
7
|
+
// eslint-disable-next-line complexity
|
|
8
|
+
export const TransactionDurationValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
9
|
+
tx: HydratedTransaction,
|
|
10
|
+
) => {
|
|
11
|
+
const errors: HydratedTransactionValidationError[] = []
|
|
12
|
+
try {
|
|
13
|
+
const { exp, nbf } = tx[0]
|
|
14
|
+
if (nbf < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction nbf must be positive'))
|
|
15
|
+
|
|
16
|
+
if (exp < 0) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must be positive'))
|
|
17
|
+
if (exp <= nbf) errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Transaction exp must greater than nbf'))
|
|
18
|
+
if (exp - nbf > 10_000) errors.push(new HydratedTransactionValidationError(
|
|
19
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
20
|
+
tx,
|
|
21
|
+
'Transaction exp must not be too far in the future',
|
|
22
|
+
))
|
|
23
|
+
} catch (ex) {
|
|
24
|
+
errors.push(new HydratedTransactionValidationError(
|
|
25
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
26
|
+
tx,
|
|
27
|
+
`Failed TransactionDurationValidator: ${ex}`,
|
|
28
|
+
ex,
|
|
29
|
+
))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return errors
|
|
33
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import type {
|
|
3
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
4
|
+
} from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
6
|
+
import { extractElevatedHashes } from '@xyo-network/xl1-protocol-sdk'
|
|
7
|
+
|
|
8
|
+
export const TransactionElevationValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
9
|
+
tx: HydratedTransaction,
|
|
10
|
+
) => {
|
|
11
|
+
const errors: HydratedTransactionValidationError[] = []
|
|
12
|
+
try {
|
|
13
|
+
try {
|
|
14
|
+
extractElevatedHashes(tx)
|
|
15
|
+
} catch {
|
|
16
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'Hydrated transaction does not include all script hashes'))
|
|
17
|
+
}
|
|
18
|
+
} catch (ex) {
|
|
19
|
+
errors.push(new HydratedTransactionValidationError(
|
|
20
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
21
|
+
tx,
|
|
22
|
+
`Failed TransactionElevationValidator: ${ex}`,
|
|
23
|
+
ex,
|
|
24
|
+
))
|
|
25
|
+
}
|
|
26
|
+
return errors
|
|
27
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { asAddress, ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import { addressesContains } from '@xyo-network/boundwitness-validator'
|
|
3
|
+
import type {
|
|
4
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
5
|
+
} from '@xyo-network/xl1-protocol'
|
|
6
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
7
|
+
|
|
8
|
+
export const TransactionFromValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
9
|
+
tx: HydratedTransaction,
|
|
10
|
+
) => {
|
|
11
|
+
const errors: HydratedTransactionValidationError[] = []
|
|
12
|
+
try {
|
|
13
|
+
const from = asAddress(tx[0].from)
|
|
14
|
+
if (from === undefined)errors.push(new HydratedTransactionValidationError(
|
|
15
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
16
|
+
tx,
|
|
17
|
+
'Transaction from is not a valid address',
|
|
18
|
+
))
|
|
19
|
+
else if (!addressesContains(tx[0], from)) errors.push(new HydratedTransactionValidationError(
|
|
20
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
21
|
+
tx,
|
|
22
|
+
'Transaction from address must be listed in addresses',
|
|
23
|
+
))
|
|
24
|
+
} catch (ex) {
|
|
25
|
+
errors.push(new HydratedTransactionValidationError(
|
|
26
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
27
|
+
tx,
|
|
28
|
+
`Failed TransactionFromValidator: ${ex}`,
|
|
29
|
+
ex,
|
|
30
|
+
))
|
|
31
|
+
}
|
|
32
|
+
return errors
|
|
33
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { hexToBigInt, ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import type {
|
|
3
|
+
HydratedTransaction,
|
|
4
|
+
HydratedTransactionValidationFunction,
|
|
5
|
+
TransactionBoundWitness, TransactionFeesBigInt, TransactionFeesHex,
|
|
6
|
+
} from '@xyo-network/xl1-protocol'
|
|
7
|
+
import {
|
|
8
|
+
AttoXL1,
|
|
9
|
+
HydratedTransactionValidationError,
|
|
10
|
+
minTransactionFees,
|
|
11
|
+
} from '@xyo-network/xl1-protocol'
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line complexity
|
|
14
|
+
export const TransactionGasValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
15
|
+
tx: HydratedTransaction,
|
|
16
|
+
) => {
|
|
17
|
+
const errors: HydratedTransactionValidationError[] = []
|
|
18
|
+
try {
|
|
19
|
+
if (tx?.[0].fees === undefined) {
|
|
20
|
+
errors.push(new HydratedTransactionValidationError(
|
|
21
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
22
|
+
tx,
|
|
23
|
+
'Missing fees',
|
|
24
|
+
))
|
|
25
|
+
} else {
|
|
26
|
+
const {
|
|
27
|
+
base, gasLimit, gasPrice, priority,
|
|
28
|
+
} = parseFees(tx[0].fees)
|
|
29
|
+
|
|
30
|
+
if (base === undefined) errors.push(new HydratedTransactionValidationError(
|
|
31
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
32
|
+
tx,
|
|
33
|
+
'fees.base must be defined and a valid number',
|
|
34
|
+
))
|
|
35
|
+
else if (base < minTransactionFees.base) errors.push(new HydratedTransactionValidationError(
|
|
36
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
37
|
+
tx,
|
|
38
|
+
`fees.base must be >= ${minTransactionFees.base}`,
|
|
39
|
+
))
|
|
40
|
+
|
|
41
|
+
if (gasLimit === undefined) errors.push(new HydratedTransactionValidationError(
|
|
42
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
43
|
+
tx,
|
|
44
|
+
'fees.gasLimit must be defined and a valid number',
|
|
45
|
+
))
|
|
46
|
+
else if (gasLimit < minTransactionFees.gasLimit) errors.push(new HydratedTransactionValidationError(
|
|
47
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
48
|
+
tx,
|
|
49
|
+
`fees.gasLimit must be >= ${minTransactionFees.gasLimit}`,
|
|
50
|
+
))
|
|
51
|
+
|
|
52
|
+
if (gasPrice === undefined) errors.push(
|
|
53
|
+
new HydratedTransactionValidationError(
|
|
54
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
55
|
+
tx,
|
|
56
|
+
'fees.gasPrice must be defined and a valid number',
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
else if (gasPrice < minTransactionFees.gasPrice) errors.push(new HydratedTransactionValidationError(
|
|
60
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
61
|
+
tx,
|
|
62
|
+
`fees.gasPrice must be >= ${minTransactionFees.gasPrice}`,
|
|
63
|
+
))
|
|
64
|
+
|
|
65
|
+
if (priority === undefined) errors.push(new HydratedTransactionValidationError(
|
|
66
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
67
|
+
tx,
|
|
68
|
+
'fees.priority must be defined and a valid number',
|
|
69
|
+
))
|
|
70
|
+
else if (priority < minTransactionFees.priority) errors.push(new HydratedTransactionValidationError(
|
|
71
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
72
|
+
tx,
|
|
73
|
+
`fees.priority must be >= ${minTransactionFees.priority}`,
|
|
74
|
+
))
|
|
75
|
+
}
|
|
76
|
+
} catch (ex) {
|
|
77
|
+
errors.push(new HydratedTransactionValidationError(
|
|
78
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
79
|
+
tx,
|
|
80
|
+
`Failed TransactionGasValidator: ${ex}`,
|
|
81
|
+
ex,
|
|
82
|
+
))
|
|
83
|
+
}
|
|
84
|
+
return errors
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const parseFees = (fees: TransactionFeesHex): Partial<TransactionFeesBigInt> => {
|
|
88
|
+
const ret: Partial<TransactionFeesBigInt> = {}
|
|
89
|
+
const {
|
|
90
|
+
base, gasLimit, gasPrice, priority,
|
|
91
|
+
} = fees
|
|
92
|
+
if (base !== undefined) ret.base = AttoXL1(hexToBigInt(base))
|
|
93
|
+
if (gasLimit !== undefined) ret.gasLimit = AttoXL1(hexToBigInt(gasLimit))
|
|
94
|
+
if (gasPrice !== undefined) ret.gasPrice = AttoXL1(hexToBigInt(gasPrice))
|
|
95
|
+
if (priority !== undefined) ret.priority = AttoXL1(hexToBigInt(priority))
|
|
96
|
+
return ret
|
|
97
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import { PayloadBuilder } from '@xyo-network/payload-builder'
|
|
3
|
+
import type {
|
|
4
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
5
|
+
} from '@xyo-network/xl1-protocol'
|
|
6
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
7
|
+
import { TransactionBoundWitnessJsonSchema } from '@xyo-network/xl1-schema'
|
|
8
|
+
import type { ValidateFunction } from 'ajv'
|
|
9
|
+
import { Ajv } from 'ajv'
|
|
10
|
+
|
|
11
|
+
const ajv = new Ajv({ allErrors: true, strict: true })
|
|
12
|
+
|
|
13
|
+
let validate: ValidateFunction<TransactionBoundWitness> | undefined
|
|
14
|
+
|
|
15
|
+
export const TransactionJsonSchemaValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = (
|
|
16
|
+
tx: HydratedTransaction,
|
|
17
|
+
) => {
|
|
18
|
+
const errors: HydratedTransactionValidationError[] = []
|
|
19
|
+
try {
|
|
20
|
+
if (validate === undefined) validate = ajv.compile(TransactionBoundWitnessJsonSchema)
|
|
21
|
+
if (!validate(PayloadBuilder.omitStorageMeta(tx[0]))) {
|
|
22
|
+
const error = new HydratedTransactionValidationError(
|
|
23
|
+
tx?.[0]?._hash ?? ZERO_HASH,
|
|
24
|
+
tx,
|
|
25
|
+
`failed JSON schema validation: ${ajv.errorsText(validate.errors, { separator: '\n' })}`,
|
|
26
|
+
)
|
|
27
|
+
error.cause = validate.errors
|
|
28
|
+
errors.push(error)
|
|
29
|
+
}
|
|
30
|
+
} catch (ex) {
|
|
31
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))
|
|
32
|
+
}
|
|
33
|
+
return errors
|
|
34
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type Address, ZERO_HASH } from '@xylabs/hex'
|
|
2
|
+
import type {
|
|
3
|
+
HydratedTransaction, HydratedTransactionValidationFunction, TransactionBoundWitness,
|
|
4
|
+
} from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol'
|
|
6
|
+
|
|
7
|
+
export const TransactionProtocolValidator: HydratedTransactionValidationFunction<TransactionBoundWitness> = async (
|
|
8
|
+
tx: HydratedTransaction,
|
|
9
|
+
chainId?: Address,
|
|
10
|
+
) => {
|
|
11
|
+
const errors: HydratedTransactionValidationError[] = []
|
|
12
|
+
try {
|
|
13
|
+
if (chainId !== undefined && tx[0].chain !== chainId) {
|
|
14
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'invalid chain id'))
|
|
15
|
+
}
|
|
16
|
+
} catch (ex) {
|
|
17
|
+
errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))
|
|
18
|
+
}
|
|
19
|
+
return await Promise.resolve(errors)
|
|
20
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export * from './TransactionDurationValidator.ts'
|
|
2
|
+
export * from './TransactionElevationValidator.ts'
|
|
3
|
+
export * from './TransactionFromValidator.ts'
|
|
4
|
+
export * from './TransactionGasValidator.ts'
|
|
5
|
+
export * from './TransactionJsonSchemaValidator.ts'
|
|
6
|
+
export * from './TransactionProtocolValidator.ts'
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Account } from '@xyo-network/account'
|
|
2
|
+
import type { AccountInstance } from '@xyo-network/account-model'
|
|
3
|
+
import { buildTransaction } from '@xyo-network/xl1-protocol-sdk'
|
|
4
|
+
import {
|
|
5
|
+
beforeAll, describe, expect, it,
|
|
6
|
+
} from 'vitest'
|
|
7
|
+
|
|
8
|
+
import { TransactionDurationValidator } from '../TransactionDurationValidator.ts'
|
|
9
|
+
|
|
10
|
+
describe('TransactionDurationValidator', () => {
|
|
11
|
+
const chain = 'a82920051db4fcbb804463440dd45e03f72442fd'
|
|
12
|
+
let signer: AccountInstance
|
|
13
|
+
beforeAll(async () => {
|
|
14
|
+
signer = await Account.random()
|
|
15
|
+
})
|
|
16
|
+
describe('with valid duration', () => {
|
|
17
|
+
it('should return no errors', async () => {
|
|
18
|
+
const hydratedTransaction = await buildTransaction(chain, [], [], signer, 0, 1000)
|
|
19
|
+
const errors = await TransactionDurationValidator(hydratedTransaction, chain)
|
|
20
|
+
expect(errors.length).toBe(0)
|
|
21
|
+
})
|
|
22
|
+
})
|
|
23
|
+
describe('with invalid', () => {
|
|
24
|
+
describe('nbf', () => {
|
|
25
|
+
it('should return error if nbf too low', async () => {
|
|
26
|
+
const hydratedTransaction = await buildTransaction(chain, [], [], signer, -1, 1000)
|
|
27
|
+
const errors = await TransactionDurationValidator(hydratedTransaction, chain)
|
|
28
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
describe('exp', () => {
|
|
32
|
+
it('should return error if exp less than nbf', async () => {
|
|
33
|
+
const hydratedTransaction = await buildTransaction(chain, [], [], signer, 1, 0)
|
|
34
|
+
const errors = await TransactionDurationValidator(hydratedTransaction, chain)
|
|
35
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
36
|
+
})
|
|
37
|
+
it('should return error if exp is equal to nbf', async () => {
|
|
38
|
+
const hydratedTransaction = await buildTransaction(chain, [], [], signer, 0, 0)
|
|
39
|
+
const errors = await TransactionDurationValidator(hydratedTransaction, chain)
|
|
40
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
41
|
+
})
|
|
42
|
+
it('should return error if exp too high', async () => {
|
|
43
|
+
const hydratedTransaction = await buildTransaction(chain, [], [], signer, 0, Number.MAX_SAFE_INTEGER)
|
|
44
|
+
const errors = await TransactionDurationValidator(hydratedTransaction, chain)
|
|
45
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
46
|
+
})
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
})
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Account } from '@xyo-network/account'
|
|
2
|
+
import type { AccountInstance } from '@xyo-network/account-model'
|
|
3
|
+
import { buildRandomTransaction } from '@xyo-network/chain-protocol'
|
|
4
|
+
import type { HydratedTransaction, TransactionBoundWitness } from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { buildTransaction } from '@xyo-network/xl1-protocol-sdk'
|
|
6
|
+
import {
|
|
7
|
+
beforeAll, describe, expect, it,
|
|
8
|
+
} from 'vitest'
|
|
9
|
+
|
|
10
|
+
import { TransactionElevationValidator } from '../TransactionElevationValidator.ts'
|
|
11
|
+
|
|
12
|
+
describe('TransactionDurationValidator', () => {
|
|
13
|
+
const chain = 'a82920051db4fcbb804463440dd45e03f72442fd'
|
|
14
|
+
let signer: AccountInstance
|
|
15
|
+
beforeAll(async () => {
|
|
16
|
+
signer = await Account.random()
|
|
17
|
+
})
|
|
18
|
+
describe('should return no errors', () => {
|
|
19
|
+
it('if all script hash payloads are supplied', async () => {
|
|
20
|
+
const tx = await buildRandomTransaction(chain, [], signer)
|
|
21
|
+
const result = await TransactionElevationValidator(tx, chain)
|
|
22
|
+
expect(result.length).toBe(0)
|
|
23
|
+
})
|
|
24
|
+
it('when no payloads referenced in script hash', async () => {
|
|
25
|
+
const sample = await buildRandomTransaction(chain, [], signer)
|
|
26
|
+
const tx = await buildTransaction(chain, [], sample[1], signer, 1, 2)
|
|
27
|
+
const result = await TransactionElevationValidator(tx, chain)
|
|
28
|
+
expect(result.length).toBe(0)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
describe('should return errors', () => {
|
|
32
|
+
it('if not all script hash payloads are supplied', async () => {
|
|
33
|
+
const [bw] = await buildRandomTransaction(chain, [], signer)
|
|
34
|
+
const tx = [bw, []] as HydratedTransaction<TransactionBoundWitness>
|
|
35
|
+
const result = await TransactionElevationValidator(tx, chain)
|
|
36
|
+
expect(result.length).toBe(1)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
39
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Account } from '@xyo-network/account'
|
|
2
|
+
import type { AccountInstance } from '@xyo-network/account-model'
|
|
3
|
+
import type { WithStorageMeta } from '@xyo-network/payload-model'
|
|
4
|
+
import type { HydratedTransaction, TransactionBoundWitness } from '@xyo-network/xl1-protocol'
|
|
5
|
+
import { buildTransaction } from '@xyo-network/xl1-protocol-sdk'
|
|
6
|
+
import {
|
|
7
|
+
beforeAll,
|
|
8
|
+
beforeEach,
|
|
9
|
+
describe, expect, it,
|
|
10
|
+
} from 'vitest'
|
|
11
|
+
|
|
12
|
+
import { TransactionFromValidator } from '../TransactionFromValidator.ts'
|
|
13
|
+
|
|
14
|
+
describe('TransactionFromValidator', () => {
|
|
15
|
+
const chain = 'a82920051db4fcbb804463440dd45e03f72442fd'
|
|
16
|
+
let signer: AccountInstance
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
signer = await Account.random()
|
|
19
|
+
})
|
|
20
|
+
describe('with from empty', () => {
|
|
21
|
+
let hydratedTransaction: HydratedTransaction
|
|
22
|
+
beforeEach(async () => {
|
|
23
|
+
const transaction = await buildTransaction(chain, [], [], signer, 0, Number.MAX_SAFE_INTEGER)
|
|
24
|
+
const { from, ...tx } = transaction[0]
|
|
25
|
+
hydratedTransaction = [tx as WithStorageMeta<TransactionBoundWitness>, transaction[1]]
|
|
26
|
+
})
|
|
27
|
+
it('should return error', async () => {
|
|
28
|
+
const errors = await TransactionFromValidator(hydratedTransaction, chain)
|
|
29
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
describe('with from not in addresses', () => {
|
|
33
|
+
let hydratedTransaction: HydratedTransaction
|
|
34
|
+
beforeEach(async () => {
|
|
35
|
+
const from = await Account.random()
|
|
36
|
+
hydratedTransaction = await buildTransaction(chain, [], [], signer, 0, Number.MAX_SAFE_INTEGER, from.address)
|
|
37
|
+
})
|
|
38
|
+
it('should return error', async () => {
|
|
39
|
+
const errors = await TransactionFromValidator(hydratedTransaction, chain)
|
|
40
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
})
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { type Address, hexFromBigInt } from '@xylabs/hex'
|
|
2
|
+
import { Account } from '@xyo-network/account'
|
|
3
|
+
import { buildRandomTransaction } from '@xyo-network/chain-protocol'
|
|
4
|
+
import type {
|
|
5
|
+
HydratedTransaction, TransactionBoundWitness, TransactionFeesHex,
|
|
6
|
+
} from '@xyo-network/xl1-protocol'
|
|
7
|
+
import {
|
|
8
|
+
beforeAll, beforeEach, describe, expect, it,
|
|
9
|
+
} from 'vitest'
|
|
10
|
+
|
|
11
|
+
import { TransactionGasValidator } from '../TransactionGasValidator.ts'
|
|
12
|
+
|
|
13
|
+
describe('TransactionGasValidator', () => {
|
|
14
|
+
let chainId: Address
|
|
15
|
+
let transaction: HydratedTransaction
|
|
16
|
+
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
chainId = (await Account.random()).address
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
beforeEach(async () => {
|
|
22
|
+
transaction = await buildRandomTransaction(chainId)
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
describe('with valid transaction', () => {
|
|
26
|
+
it('should return no errors for valid fees', async () => {
|
|
27
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
28
|
+
expect(result).toEqual([])
|
|
29
|
+
})
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
describe('with invalid transaction', () => {
|
|
33
|
+
describe('fees', () => {
|
|
34
|
+
it('should return an error if fees are missing', async () => {
|
|
35
|
+
delete (transaction[0] as Partial<TransactionBoundWitness>).fees
|
|
36
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
37
|
+
expect(result[0].message).toEqual('Missing fees')
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('base', () => {
|
|
42
|
+
it('should return an error if fees.base is undefined', async () => {
|
|
43
|
+
delete (transaction[0].fees as Partial<TransactionFeesHex>)?.base
|
|
44
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
45
|
+
expect(result[0].message).toEqual('fees.base must be defined and a valid number')
|
|
46
|
+
})
|
|
47
|
+
it('should return an error if fees.base is less than or equal to 0', async () => {
|
|
48
|
+
transaction[0].fees.base = hexFromBigInt(0n)
|
|
49
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
50
|
+
expect(result.length).toEqual(1)
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
describe('gasLimit', () => {
|
|
55
|
+
it('should return an error if fees.gasLimit is undefined', async () => {
|
|
56
|
+
delete (transaction[0].fees as Partial<TransactionFeesHex>)?.gasLimit
|
|
57
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
58
|
+
expect(result[0].message).toEqual('fees.gasLimit must be defined and a valid number')
|
|
59
|
+
})
|
|
60
|
+
it('should return an error if fees.gasLimit is less than or equal to 0', async () => {
|
|
61
|
+
transaction[0].fees.gasLimit = hexFromBigInt(0n)
|
|
62
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
63
|
+
expect(result.length).toEqual(1)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
describe('gasPrice', () => {
|
|
69
|
+
it('should return an error if fees.gasPrice is undefined', async () => {
|
|
70
|
+
delete (transaction[0].fees as Partial<TransactionFeesHex>)?.gasPrice
|
|
71
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
72
|
+
expect(result[0].message).toEqual('fees.gasPrice must be defined and a valid number')
|
|
73
|
+
})
|
|
74
|
+
it('should return an error if fees.gasPrice is less than or equal to 0', async () => {
|
|
75
|
+
transaction[0].fees.gasPrice = hexFromBigInt(0n)
|
|
76
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
77
|
+
expect(result.length).toEqual(1)
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
describe('priority', () => {
|
|
82
|
+
it('should return an error if fees.priority is undefined', async () => {
|
|
83
|
+
delete (transaction[0].fees as Partial<TransactionFeesHex>)?.priority
|
|
84
|
+
const result = await TransactionGasValidator(transaction, chainId)
|
|
85
|
+
expect(result[0].message).toEqual('fees.priority must be defined and a valid number')
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
})
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { buildRandomTransaction } from '@xyo-network/chain-protocol'
|
|
2
|
+
import type { HydratedTransaction } from '@xyo-network/xl1-protocol'
|
|
3
|
+
import {
|
|
4
|
+
beforeEach, describe, expect, it,
|
|
5
|
+
} from 'vitest'
|
|
6
|
+
|
|
7
|
+
import { TransactionJsonSchemaValidator } from '../TransactionJsonSchemaValidator.ts'
|
|
8
|
+
|
|
9
|
+
describe('TransactionJsonSchemaValidator', () => {
|
|
10
|
+
const chain = 'a82920051db4fcbb804463440dd45e03f72442fd'
|
|
11
|
+
|
|
12
|
+
describe('with valid transaction', () => {
|
|
13
|
+
let hydratedTransaction: HydratedTransaction
|
|
14
|
+
beforeEach(async () => {
|
|
15
|
+
hydratedTransaction = await buildRandomTransaction(chain)
|
|
16
|
+
})
|
|
17
|
+
it('should return no errors', async () => {
|
|
18
|
+
const errors = await TransactionJsonSchemaValidator(hydratedTransaction, chain)
|
|
19
|
+
expect(errors).toEqual([])
|
|
20
|
+
})
|
|
21
|
+
})
|
|
22
|
+
describe('with invalid transaction', () => {
|
|
23
|
+
let hydratedTransaction: HydratedTransaction
|
|
24
|
+
beforeEach(async () => {
|
|
25
|
+
hydratedTransaction = await buildRandomTransaction(chain)
|
|
26
|
+
hydratedTransaction[0].chain = 'invalid'
|
|
27
|
+
})
|
|
28
|
+
it('should return error', async () => {
|
|
29
|
+
const errors = await TransactionJsonSchemaValidator(hydratedTransaction, chain)
|
|
30
|
+
expect(errors.length).toBeGreaterThan(0)
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
})
|