@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.
Files changed (62) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +250 -0
  3. package/dist/neutral/boundwitness/index.d.ts +2 -0
  4. package/dist/neutral/boundwitness/index.d.ts.map +1 -0
  5. package/dist/neutral/boundwitness/validators/BoundWitnessReferences.d.ts +5 -0
  6. package/dist/neutral/boundwitness/validators/BoundWitnessReferences.d.ts.map +1 -0
  7. package/dist/neutral/boundwitness/validators/BoundWitnessSignatures.d.ts +3 -0
  8. package/dist/neutral/boundwitness/validators/BoundWitnessSignatures.d.ts.map +1 -0
  9. package/dist/neutral/boundwitness/validators/index.d.ts +3 -0
  10. package/dist/neutral/boundwitness/validators/index.d.ts.map +1 -0
  11. package/dist/neutral/index.d.ts +3 -0
  12. package/dist/neutral/index.d.ts.map +1 -0
  13. package/dist/neutral/index.mjs +258 -0
  14. package/dist/neutral/index.mjs.map +1 -0
  15. package/dist/neutral/transaction/index.d.ts +3 -0
  16. package/dist/neutral/transaction/index.d.ts.map +1 -0
  17. package/dist/neutral/transaction/validateTransaction.d.ts +4 -0
  18. package/dist/neutral/transaction/validateTransaction.d.ts.map +1 -0
  19. package/dist/neutral/transaction/validators/TransactionDurationValidator.d.ts +3 -0
  20. package/dist/neutral/transaction/validators/TransactionDurationValidator.d.ts.map +1 -0
  21. package/dist/neutral/transaction/validators/TransactionElevationValidator.d.ts +3 -0
  22. package/dist/neutral/transaction/validators/TransactionElevationValidator.d.ts.map +1 -0
  23. package/dist/neutral/transaction/validators/TransactionFromValidator.d.ts +3 -0
  24. package/dist/neutral/transaction/validators/TransactionFromValidator.d.ts.map +1 -0
  25. package/dist/neutral/transaction/validators/TransactionGasValidator.d.ts +3 -0
  26. package/dist/neutral/transaction/validators/TransactionGasValidator.d.ts.map +1 -0
  27. package/dist/neutral/transaction/validators/TransactionJsonSchemaValidator.d.ts +3 -0
  28. package/dist/neutral/transaction/validators/TransactionJsonSchemaValidator.d.ts.map +1 -0
  29. package/dist/neutral/transaction/validators/TransactionProtocolValidator.d.ts +3 -0
  30. package/dist/neutral/transaction/validators/TransactionProtocolValidator.d.ts.map +1 -0
  31. package/dist/neutral/transaction/validators/index.d.ts +7 -0
  32. package/dist/neutral/transaction/validators/index.d.ts.map +1 -0
  33. package/dist/neutral/transaction/validators/spec/TransactionDurationValidator.spec.d.ts +2 -0
  34. package/dist/neutral/transaction/validators/spec/TransactionDurationValidator.spec.d.ts.map +1 -0
  35. package/dist/neutral/transaction/validators/spec/TransactionElevationValidator.spec.d.ts +2 -0
  36. package/dist/neutral/transaction/validators/spec/TransactionElevationValidator.spec.d.ts.map +1 -0
  37. package/dist/neutral/transaction/validators/spec/TransactionFromValidator.spec.d.ts +2 -0
  38. package/dist/neutral/transaction/validators/spec/TransactionFromValidator.spec.d.ts.map +1 -0
  39. package/dist/neutral/transaction/validators/spec/TransactionGasValidator.spec.d.ts +2 -0
  40. package/dist/neutral/transaction/validators/spec/TransactionGasValidator.spec.d.ts.map +1 -0
  41. package/dist/neutral/transaction/validators/spec/TransactionJsonSchemaValidator.spec.d.ts +2 -0
  42. package/dist/neutral/transaction/validators/spec/TransactionJsonSchemaValidator.spec.d.ts.map +1 -0
  43. package/package.json +75 -0
  44. package/src/boundwitness/index.ts +1 -0
  45. package/src/boundwitness/validators/BoundWitnessReferences.ts +57 -0
  46. package/src/boundwitness/validators/BoundWitnessSignatures.ts +28 -0
  47. package/src/boundwitness/validators/index.ts +2 -0
  48. package/src/index.ts +2 -0
  49. package/src/transaction/index.ts +2 -0
  50. package/src/transaction/validateTransaction.ts +33 -0
  51. package/src/transaction/validators/TransactionDurationValidator.ts +33 -0
  52. package/src/transaction/validators/TransactionElevationValidator.ts +27 -0
  53. package/src/transaction/validators/TransactionFromValidator.ts +33 -0
  54. package/src/transaction/validators/TransactionGasValidator.ts +97 -0
  55. package/src/transaction/validators/TransactionJsonSchemaValidator.ts +34 -0
  56. package/src/transaction/validators/TransactionProtocolValidator.ts +20 -0
  57. package/src/transaction/validators/index.ts +6 -0
  58. package/src/transaction/validators/spec/TransactionDurationValidator.spec.ts +49 -0
  59. package/src/transaction/validators/spec/TransactionElevationValidator.spec.ts +39 -0
  60. package/src/transaction/validators/spec/TransactionFromValidator.spec.ts +43 -0
  61. package/src/transaction/validators/spec/TransactionGasValidator.spec.ts +88 -0
  62. 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
+ })