@xyo-network/xl1-validation 1.26.11 → 1.26.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xyo-network/xl1-validation",
3
- "version": "1.26.11",
3
+ "version": "1.26.13",
4
4
  "description": "XYO Layer One SDK Validation",
5
5
  "homepage": "https://xylabs.com",
6
6
  "bugs": {
@@ -22,7 +22,6 @@
22
22
  "exports": {
23
23
  ".": {
24
24
  "types": "./dist/neutral/index.d.ts",
25
- "source": "./src/index.ts",
26
25
  "default": "./dist/neutral/index.mjs"
27
26
  },
28
27
  "./package.json": "./package.json"
@@ -32,29 +31,47 @@
32
31
  "types": "./dist/neutral/index.d.ts",
33
32
  "files": [
34
33
  "dist",
35
- "src",
36
34
  "!**/*.bench.*",
37
35
  "!**/*.spec.*",
38
- "!**/*.test.*"
36
+ "!**/*.test.*",
37
+ "README.md"
39
38
  ],
40
39
  "dependencies": {
41
- "@xyo-network/xl1-protocol-lib": "~1.26.11",
42
- "@xyo-network/xl1-protocol-sdk": "~1.26.11",
43
- "@xyo-network/xl1-schema": "~1.26.11"
40
+ "@xyo-network/xl1-protocol-lib": "~1.26.13",
41
+ "@xyo-network/xl1-protocol-sdk": "~1.26.13",
42
+ "@xyo-network/xl1-schema": "~1.26.13"
44
43
  },
45
44
  "devDependencies": {
45
+ "@firebase/app": "0.x",
46
+ "@firebase/app-compat": "0.x",
47
+ "@firebase/app-types": "0.x",
48
+ "@firebase/util": "1.x",
49
+ "@metamask/providers": "^22",
46
50
  "@opentelemetry/api": "^1.9.1",
47
51
  "@types/node": "^25.5.0",
48
- "@xylabs/sdk-js": "^5.0.90",
49
- "@xylabs/ts-scripts-common": "~7.5.6",
50
- "@xylabs/ts-scripts-yarn3": "~7.5.6",
51
- "@xylabs/tsconfig": "~7.5.6",
52
- "@xyo-network/sdk-js": "^5.3.17",
52
+ "@xylabs/geo": "^5",
53
+ "@xylabs/sdk-js": "^5.0.91",
54
+ "@xylabs/ts-scripts-common": "~7.6.13",
55
+ "@xylabs/ts-scripts-yarn3": "~7.6.13",
56
+ "@xylabs/tsconfig": "~7.6.13",
57
+ "@xyo-network/sdk-js": "^5.3.22",
58
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0",
53
59
  "ajv": "^8.18.0",
54
- "axios": "^1.13.6",
60
+ "axios": "^1.14.0",
61
+ "cosmiconfig": ">=9",
62
+ "esbuild": ">=0.18",
63
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0",
55
64
  "ethers": "^6.16.0",
65
+ "firebase": "^12",
66
+ "lru-cache": "^11",
67
+ "mapbox-gl": "^3",
68
+ "mongodb": "^6 || ^7",
69
+ "rollup": "^3.29.4 || ^4",
70
+ "tslib": "^2.8.1",
56
71
  "typescript": "~5.9.3",
72
+ "vite": "^8.0.3",
57
73
  "vitest": "~4.1.2",
74
+ "webextension-polyfill": "^0.10.0 || ^0.11.0 || ^0.12.0",
58
75
  "zod": "~4.3.6"
59
76
  },
60
77
  "peerDependencies": {
@@ -64,6 +81,8 @@
64
81
  "ajv": "^8",
65
82
  "axios": "^1",
66
83
  "ethers": "^6",
84
+ "mongodb": "^6 || ^7",
85
+ "typescript": ">=4.9.5",
67
86
  "zod": "^4"
68
87
  },
69
88
  "engines": {
@@ -1 +0,0 @@
1
- export * from './validators/index.ts'
@@ -1,90 +0,0 @@
1
- import {
2
- type Address, type Hex, hexToBigInt,
3
- } from '@xylabs/sdk-js'
4
- import type {
5
- HydratedBlockStateValidationFunction,
6
- HydratedBlockWithHashMeta,
7
- TransactionBoundWitnessWithHashMeta,
8
- } from '@xyo-network/xl1-protocol-lib'
9
- import {
10
- HydratedBlockStateValidationError,
11
- isTransactionBoundWitnessWithHashMeta,
12
- isTransfer,
13
- XYO_ZERO_ADDRESS,
14
- } from '@xyo-network/xl1-protocol-lib'
15
-
16
- /** Compute the maximum fee commitment for a transaction (base + priority + gasLimit). */
17
- function maxTransactionFeeCost(tx: TransactionBoundWitnessWithHashMeta): bigint {
18
- const {
19
- base, gasLimit, priority,
20
- } = tx.fees
21
- return hexToBigInt(base) + hexToBigInt(priority) + hexToBigInt(gasLimit)
22
- }
23
-
24
- /** Accumulate outflows per address from fees and transfers in the given transactions. */
25
- export function accumulateOutflows(
26
- transactions: TransactionBoundWitnessWithHashMeta[],
27
- payloads: HydratedBlockWithHashMeta[1],
28
- ): Record<Address, bigint> {
29
- const outflows: Record<Address, bigint> = {}
30
-
31
- for (const tx of transactions) {
32
- // Fee cost charged to the transaction sender
33
- const feeCost = maxTransactionFeeCost(tx)
34
- const feePayer = tx.from
35
- outflows[feePayer] = (outflows[feePayer] ?? 0n) + feeCost
36
-
37
- // Find transfer payloads belonging to this transaction
38
- const txPayloadHashes = new Set(tx.payload_hashes)
39
- for (const payload of payloads) {
40
- if (!txPayloadHashes.has(payload._hash) || !isTransfer(payload)) continue
41
- const { from } = payload
42
- for (const [to, amount] of Object.entries(payload.transfers) as [Address, Hex][]) {
43
- if (to === from) continue // self-transfers are not outflows
44
- outflows[from] = (outflows[from] ?? 0n) + hexToBigInt(amount)
45
- }
46
- }
47
- }
48
-
49
- return outflows
50
- }
51
-
52
- /** Creates a block state validator that checks cumulative outflows per address do not exceed pre-block balances. */
53
- export function BlockCumulativeBalanceValidatorFactory(): HydratedBlockStateValidationFunction {
54
- return async (context, hydratedBlock) => {
55
- const [blockBw, payloads] = hydratedBlock
56
-
57
- // Find all transactions in the block
58
- const transactions = payloads.filter(isTransactionBoundWitnessWithHashMeta)
59
-
60
- if (transactions.length === 0) return []
61
-
62
- const outflows = accumulateOutflows(transactions, payloads)
63
-
64
- // Query pre-block balances for all addresses with outflows
65
- const addresses = Object.keys(outflows) as Address[]
66
- if (addresses.length === 0) return []
67
-
68
- const balances = await context.accountBalance.accountBalances(addresses)
69
-
70
- // Check each address
71
- const chainId = await context.chainIdAtBlockNumber(blockBw.block)
72
- const errors: HydratedBlockStateValidationError[] = []
73
- for (const address of addresses) {
74
- if (address === XYO_ZERO_ADDRESS) continue // Skip zero address as it's used for burn transactions and doesn't have a balance
75
- // TODO: Add specific validation for block reward transfer
76
- const balance = balances[address] ?? 0n
77
- const totalOutflow = outflows[address]
78
- if (totalOutflow > balance) {
79
- errors.push(new HydratedBlockStateValidationError(
80
- blockBw._hash,
81
- chainId,
82
- hydratedBlock,
83
- `Cumulative outflow for address ${address} exceeds available balance: outflow ${totalOutflow} > balance ${balance}`,
84
- ))
85
- }
86
- }
87
-
88
- return errors
89
- }
90
- }
@@ -1 +0,0 @@
1
- export * from './BlockCumulativeBalanceValidator.ts'
@@ -1 +0,0 @@
1
- export * from './validators/index.ts'
@@ -1,58 +0,0 @@
1
- import type { Hash, Promisable } from '@xylabs/sdk-js'
2
- import { ZERO_HASH } from '@xylabs/sdk-js'
3
- import type {
4
- BoundWitness,
5
- Payload,
6
- Schema,
7
- WithHashMeta,
8
- } from '@xyo-network/sdk-js'
9
- import { isAnyPayload } from '@xyo-network/sdk-js'
10
- import type { HydratedBoundWitnessValidationFunction, HydratedBoundWitnessWithHashMeta } from '@xyo-network/xl1-protocol-lib'
11
- import { HydratedBoundWitnessValidationError } from '@xyo-network/xl1-protocol-lib'
12
-
13
- function getPayloadsFromPayloadArray(payloads: WithHashMeta<Payload>[], hashes: Hash[]): (WithHashMeta<Payload> | undefined)[] {
14
- return hashes.map(hash => payloads.find(payload => payload._hash === hash || payload._dataHash === hash))
15
- }
16
-
17
- /** Creates a validator that checks all payload references in a BoundWitness are present, have matching schemas, and optionally conform to an allowed schema list. */
18
- export const BoundWitnessReferencesValidator
19
-
20
- = <T extends BoundWitness = BoundWitness>(allowedSchemas?: Schema[]): HydratedBoundWitnessValidationFunction<T> => (
21
- [bw, payloadSet]: HydratedBoundWitnessWithHashMeta<T>,
22
- // eslint-disable-next-line complexity
23
- ): Promisable<HydratedBoundWitnessValidationError[]> => {
24
- const errors: HydratedBoundWitnessValidationError[] = []
25
- try {
26
- const payloads = getPayloadsFromPayloadArray(payloadSet, bw.payload_hashes)
27
- if (payloads.length !== bw.payload_hashes.length) {
28
- errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'unable to locate payloads'))
29
- }
30
-
31
- // check if payloads are valid and if their schemas match the declared schemas
32
- for (let payload of payloads) {
33
- if (isAnyPayload(payload)) {
34
- const payloadHashIndex = bw.payload_hashes.indexOf(payload._hash)
35
- const payloadDataHashIndex = bw.payload_hashes.indexOf(payload._dataHash)
36
- const payloadIndex = Math.max(payloadHashIndex, payloadDataHashIndex)
37
- if (payloadIndex === -1) {
38
- errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'payload hash not found'))
39
- }
40
-
41
- const declaredSchema = bw.payload_schemas[payloadIndex]
42
- if (declaredSchema !== payload.schema) {
43
- errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'mismatched schema'))
44
- }
45
-
46
- if (allowedSchemas && !allowedSchemas.includes(payload.schema)) {
47
- errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `disallowed schema [${payload.schema}]`))
48
- }
49
- } else {
50
- errors.push(new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], 'invalid payload'))
51
- }
52
- }
53
- } catch (ex) {
54
- const error = new HydratedBoundWitnessValidationError(bw?._hash ?? ZERO_HASH, [bw, payloadSet], `validation excepted: ${ex}`, ex)
55
- errors.push(error)
56
- }
57
- return errors
58
- }
@@ -1,31 +0,0 @@
1
- import { type Address, ZERO_HASH } from '@xylabs/sdk-js'
2
- import { toArrayBuffer } from '@xylabs/sdk-js'
3
- import type { BoundWitness, WithStorageMeta } from '@xyo-network/sdk-js'
4
- import { BoundWitnessBuilder, BoundWitnessValidator } from '@xyo-network/sdk-js'
5
- import type { BoundWitnessValidationFunction } from '@xyo-network/xl1-protocol-lib'
6
- import { BoundWitnessValidationError } from '@xyo-network/xl1-protocol-lib'
7
-
8
- /** Validates that all signatures on a BoundWitness are cryptographically valid for their corresponding addresses. */
9
- export const BoundWitnessSignaturesValidator: BoundWitnessValidationFunction = async (
10
- bw: BoundWitness,
11
- ) => {
12
- const errors: BoundWitnessValidationError[] = []
13
- try {
14
- const dataHash = await BoundWitnessBuilder.dataHash(bw)
15
- const results: [Address, Error[]][] = await Promise.all(bw.addresses.map(async (address, index) => {
16
- return [address, await BoundWitnessValidator.validateSignature(
17
- toArrayBuffer(dataHash),
18
- toArrayBuffer(address),
19
- toArrayBuffer(bw.$signatures[index] ?? undefined),
20
- )]
21
- }))
22
- for (const [, bwErrors] of results) {
23
- for (const bwError of bwErrors) {
24
- errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation errors', bwError))
25
- }
26
- }
27
- } catch (ex) {
28
- errors.push(new BoundWitnessValidationError((bw as WithStorageMeta<BoundWitness>)?._hash ?? ZERO_HASH, bw, 'validation excepted', ex))
29
- }
30
- return errors
31
- }
@@ -1,2 +0,0 @@
1
- export * from './BoundWitnessReferences.ts'
2
- export * from './BoundWitnessSignatures.ts'
package/src/index.ts DELETED
@@ -1,3 +0,0 @@
1
- export * from './block/index.ts'
2
- export * from './boundwitness/index.ts'
3
- export * from './transaction/index.ts'
@@ -1,2 +0,0 @@
1
- export * from './validateTransaction.ts'
2
- export * from './validators/index.ts'
@@ -1,36 +0,0 @@
1
- import type {
2
- HydratedTransactionValidationFunction,
3
- HydratedTransactionValidationFunctionContext,
4
- HydratedTransactionWithHashMeta,
5
- } from '@xyo-network/xl1-protocol-lib'
6
- import { isTransactionBoundWitness } from '@xyo-network/xl1-protocol-lib'
7
-
8
- import {
9
- TransactionDurationValidator,
10
- TransactionElevationValidator, TransactionFromValidator, TransactionGasValidator, TransactionProtocolValidator,
11
- } from './validators/index.ts'
12
-
13
- /** Validates a hydrated transaction using built-in validators plus any additional validators provided. */
14
- export async function validateTransaction(
15
- context: HydratedTransactionValidationFunctionContext,
16
- tx: HydratedTransactionWithHashMeta,
17
- additionalValidators?: HydratedTransactionValidationFunction[],
18
- ) {
19
- try {
20
- if (!isTransactionBoundWitness(tx[0])) {
21
- return [new Error('failed isTransactionBoundWitness identity check')]
22
- }
23
-
24
- const validators: HydratedTransactionValidationFunction<HydratedTransactionValidationFunctionContext>[] = [
25
- TransactionProtocolValidator,
26
- TransactionDurationValidator,
27
- TransactionFromValidator,
28
- TransactionGasValidator,
29
- TransactionElevationValidator,
30
- ...(additionalValidators ?? []),
31
- ]
32
- return (await Promise.all(validators.map(v => v(context, tx)))).flat()
33
- } catch (ex) {
34
- return [(new Error(`Failed TransactionGasValidator: ${ex}`))]
35
- }
36
- }
@@ -1,33 +0,0 @@
1
- import { ZERO_HASH } from '@xylabs/sdk-js'
2
- import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol-lib'
3
- import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol-lib'
4
-
5
- /** Validates that transaction timing fields (nbf and exp) are positive, correctly ordered, and within allowed duration limits. */
6
- export const TransactionDurationValidator: HydratedTransactionValidationFunction = (
7
- context,
8
- tx,
9
- // eslint-disable-next-line complexity
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
- }
@@ -1,27 +0,0 @@
1
- import { ZERO_HASH } from '@xylabs/sdk-js'
2
- import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol-lib'
3
- import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol-lib'
4
- import { extractElevatedHashes } from '@xyo-network/xl1-protocol-sdk'
5
-
6
- /** Validates that a hydrated transaction includes all required elevated script hashes. */
7
- export const TransactionElevationValidator: HydratedTransactionValidationFunction = (
8
- context,
9
- tx,
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
- }
@@ -1,33 +0,0 @@
1
- import { asAddress, ZERO_HASH } from '@xylabs/sdk-js'
2
- import { addressesContains } from '@xyo-network/sdk-js'
3
- import type { HydratedTransactionValidationFunction } from '@xyo-network/xl1-protocol-lib'
4
- import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol-lib'
5
-
6
- /** Validates that the transaction's from field is a valid address and is included in the BoundWitness addresses. */
7
- export const TransactionFromValidator: HydratedTransactionValidationFunction = (
8
- context,
9
- tx,
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
- }
@@ -1,98 +0,0 @@
1
- import { hexToBigInt, ZERO_HASH } from '@xylabs/sdk-js'
2
- import type {
3
- HydratedTransactionValidationFunction,
4
- TransactionFeesBigInt, TransactionFeesHex,
5
- } from '@xyo-network/xl1-protocol-lib'
6
- import {
7
- AttoXL1,
8
- HydratedTransactionValidationError,
9
- minTransactionFees,
10
- } from '@xyo-network/xl1-protocol-lib'
11
-
12
- /** Validates that transaction fee fields (base, gasLimit, gasPrice, priority) are present and meet minimum requirements. */
13
- export const TransactionGasValidator: HydratedTransactionValidationFunction = (
14
- context,
15
- tx,
16
- // eslint-disable-next-line complexity
17
- ) => {
18
- const errors: HydratedTransactionValidationError[] = []
19
- try {
20
- if (tx?.[0].fees === undefined) {
21
- errors.push(new HydratedTransactionValidationError(
22
- tx?.[0]?._hash ?? ZERO_HASH,
23
- tx,
24
- 'Missing fees',
25
- ))
26
- } else {
27
- const {
28
- base, gasLimit, gasPrice, priority,
29
- } = parseFees(tx[0].fees)
30
-
31
- if (base === undefined) errors.push(new HydratedTransactionValidationError(
32
- tx?.[0]?._hash ?? ZERO_HASH,
33
- tx,
34
- 'fees.base must be defined and a valid number',
35
- ))
36
- else if (base < minTransactionFees.base) errors.push(new HydratedTransactionValidationError(
37
- tx?.[0]?._hash ?? ZERO_HASH,
38
- tx,
39
- `fees.base must be >= ${minTransactionFees.base}`,
40
- ))
41
-
42
- if (gasLimit === undefined) errors.push(new HydratedTransactionValidationError(
43
- tx?.[0]?._hash ?? ZERO_HASH,
44
- tx,
45
- 'fees.gasLimit must be defined and a valid number',
46
- ))
47
- else if (gasLimit < minTransactionFees.gasLimit) errors.push(new HydratedTransactionValidationError(
48
- tx?.[0]?._hash ?? ZERO_HASH,
49
- tx,
50
- `fees.gasLimit must be >= ${minTransactionFees.gasLimit}`,
51
- ))
52
-
53
- if (gasPrice === undefined) errors.push(
54
- new HydratedTransactionValidationError(
55
- tx?.[0]?._hash ?? ZERO_HASH,
56
- tx,
57
- 'fees.gasPrice must be defined and a valid number',
58
- ),
59
- )
60
- else if (gasPrice < minTransactionFees.gasPrice) errors.push(new HydratedTransactionValidationError(
61
- tx?.[0]?._hash ?? ZERO_HASH,
62
- tx,
63
- `fees.gasPrice must be >= ${minTransactionFees.gasPrice}`,
64
- ))
65
-
66
- if (priority === undefined) errors.push(new HydratedTransactionValidationError(
67
- tx?.[0]?._hash ?? ZERO_HASH,
68
- tx,
69
- 'fees.priority must be defined and a valid number',
70
- ))
71
- else if (priority < minTransactionFees.priority) errors.push(new HydratedTransactionValidationError(
72
- tx?.[0]?._hash ?? ZERO_HASH,
73
- tx,
74
- `fees.priority must be >= ${minTransactionFees.priority}`,
75
- ))
76
- }
77
- } catch (ex) {
78
- errors.push(new HydratedTransactionValidationError(
79
- tx?.[0]?._hash ?? ZERO_HASH,
80
- tx,
81
- `Failed TransactionGasValidator: ${ex}`,
82
- ex,
83
- ))
84
- }
85
- return errors
86
- }
87
-
88
- const parseFees = (fees: TransactionFeesHex): Partial<TransactionFeesBigInt> => {
89
- const ret: Partial<TransactionFeesBigInt> = {}
90
- const {
91
- base, gasLimit, gasPrice, priority,
92
- } = fees
93
- if (base !== undefined) ret.base = AttoXL1(hexToBigInt(base))
94
- if (gasLimit !== undefined) ret.gasLimit = AttoXL1(hexToBigInt(gasLimit))
95
- if (gasPrice !== undefined) ret.gasPrice = AttoXL1(hexToBigInt(gasPrice))
96
- if (priority !== undefined) ret.priority = AttoXL1(hexToBigInt(priority))
97
- return ret
98
- }
@@ -1,34 +0,0 @@
1
- import { ZERO_HASH } from '@xylabs/sdk-js'
2
- import { PayloadBuilder } from '@xyo-network/sdk-js'
3
- import type { HydratedTransactionValidationFunction, TransactionBoundWitness } from '@xyo-network/xl1-protocol-lib'
4
- import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol-lib'
5
- import { TransactionBoundWitnessJsonSchema } from '@xyo-network/xl1-schema'
6
- import type { ValidateFunction } from 'ajv'
7
- import { Ajv } from 'ajv'
8
-
9
- const ajv = new Ajv({ allErrors: true, strict: true })
10
-
11
- let validate: ValidateFunction<TransactionBoundWitness> | undefined
12
-
13
- /** Validates a transaction against the TransactionBoundWitness JSON schema using AJV. */
14
- export const TransactionJsonSchemaValidator: HydratedTransactionValidationFunction = (
15
- context,
16
- tx,
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
- validate.errors,
27
- )
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
- }
@@ -1,22 +0,0 @@
1
- import { ZERO_HASH } from '@xylabs/sdk-js'
2
- import type {
3
- ChainId,
4
- HydratedTransactionValidationFunction,
5
- } from '@xyo-network/xl1-protocol-lib'
6
- import { HydratedTransactionValidationError } from '@xyo-network/xl1-protocol-lib'
7
-
8
- /** Validates that the transaction's chain ID matches the expected chain ID from the validation context. */
9
- export const TransactionProtocolValidator: HydratedTransactionValidationFunction = async (
10
- context: { chainId?: ChainId },
11
- tx,
12
- ) => {
13
- const errors: HydratedTransactionValidationError[] = []
14
- try {
15
- if (context?.chainId !== undefined && tx[0].chain !== context.chainId) {
16
- errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, `invalid chain id [${context.chainId}, ${tx[0].chain}]`))
17
- }
18
- } catch (ex) {
19
- errors.push(new HydratedTransactionValidationError(tx?.[0]?._hash ?? ZERO_HASH, tx, 'validation excepted', ex))
20
- }
21
- return await Promise.resolve(errors)
22
- }
@@ -1,81 +0,0 @@
1
- import type { Address } from '@xylabs/sdk-js'
2
- import { isDefined, isUndefined } from '@xylabs/sdk-js'
3
- import type {
4
- HydratedTransactionValidationFunction, StepIdentity,
5
- Transfer,
6
- } from '@xyo-network/xl1-protocol-lib'
7
- import { HydratedTransactionValidationError, isTransfer } from '@xyo-network/xl1-protocol-lib'
8
- import {
9
- completedStepRewardAddress, derivedReceiveAddress, elevatedPayloads,
10
- } from '@xyo-network/xl1-protocol-sdk'
11
-
12
- /** Function type that checks whether a signer is authorized to sign for a given signee address. */
13
- export type SignerValidator = (signer: Address, signee: Address, context?: { address?: Address; scope?: string; step?: StepIdentity }) => boolean
14
-
15
- /** Maps addresses to their list of authorized signer addresses. */
16
- export type SignerMapping = Map<Address, Address[]>
17
-
18
- /** A signer validator that only allows an address to sign for itself. */
19
- export const SelfSignerValidator: SignerValidator = (signer: Address, signee: Address) => signer === signee
20
-
21
- /** Creates a signer validator that authorizes specified signers to sign for completed step reward addresses. */
22
- export const CompletedStepRewardAddressValidatorFactory = (allowedSigners: Address[]): SignerValidator => (
23
- signer: Address,
24
- signee: Address,
25
- context?: { step?: StepIdentity },
26
- ) => {
27
- const step = context?.step
28
- if (isDefined(step)) {
29
- const contextAddress = completedStepRewardAddress(step)
30
- return allowedSigners.includes(signer) && signee === contextAddress
31
- } else {
32
- return false
33
- }
34
- }
35
-
36
- /** Creates a signer validator that authorizes specified signers to sign for derived receive addresses within a given scope. */
37
- export const DerivedReceiveAddressValidatorFactory = (allowedSigners: Address[], allowedScope: string): SignerValidator => (
38
- signer: Address,
39
- signee: Address,
40
- context?: { address?: Address; scope?: string },
41
- ) => {
42
- const { address, scope } = context ?? {}
43
- if (scope !== allowedScope) {
44
- return false
45
- }
46
- if (isDefined(address)) {
47
- const derivedAddress = derivedReceiveAddress(address, scope)
48
- return allowedSigners.includes(signer) && signee === derivedAddress
49
- } else {
50
- return false
51
- }
52
- }
53
-
54
- /** Creates a transaction validator that checks all transfers are authorized by the transaction signer. */
55
- export function TransactionTransfersValidatorFactory(
56
- signerValidators: SignerValidator[] = [SelfSignerValidator],
57
- ): HydratedTransactionValidationFunction {
58
- return async (
59
- context,
60
- hydratedTx,
61
- ) => {
62
- const errors: HydratedTransactionValidationError[] = []
63
- const signer = hydratedTx[0].from
64
- try {
65
- const payloads = elevatedPayloads(hydratedTx)
66
- const transfers = payloads.filter(isTransfer) as Transfer[]
67
- for (const transfer of transfers) {
68
- if (isUndefined(signerValidators.find(v => v(signer, transfer.from, transfer.context)))) {
69
- errors.push(new HydratedTransactionValidationError(
70
- hydratedTx[0]._hash,
71
- hydratedTx,
72
- `transfer from address ${transfer.from} is not authorized by signer ${signer}`,
73
- ))
74
- }
75
- }
76
- } catch (ex) {
77
- errors.push(new HydratedTransactionValidationError(hydratedTx[0]._hash, hydratedTx, 'validation excepted', ex))
78
- }
79
- return await Promise.resolve(errors)
80
- }
81
- }
@@ -1,7 +0,0 @@
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'
7
- export * from './TransactionTransfersValidator.ts'