text:
/* This is free and unencumbered software released into the public domain. */

import { matchTopics } from '../src/topics';

describe('Match topics', () => {
  test('null in transactionTopics', async () => {
    const filterTopics = [
      '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    ]

    const transactionTopics = null

    expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
  })

  test('[] in transactionTopics', async () => {
    const filterTopics = [
      '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
    ]

    const transactionTopics: [] = []

    expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
  })

  describe('with null params', () => {
    test('with one topic as filter', async () => {
      const filterTopics = [
        null,
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test('with one topic as filter and three null', async () => {
      const filterTopics = [
        null,
        null,
        null,
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      const transactionTopics = [
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test(`three null, topics don't exist in the transaction`, async () => {
      const filterTopics = [
        null,
        null,
        '0x000000000000000000000000dd58a0e3db99a98839086ccdabfa49e979290812',
        null,
      ]

      const transactionTopics = [
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })
  })

  describe('with empty array and null in params', () => {
    test('empty array as first param, with one topic as filter', async () => {
      const filterTopics = [
        [],
        null,
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test('empty array as first param, with one topic as filter at the start of transaction', async () => {
      const filterTopics = [
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
        [],
        null,
      ]

      const transactionTopics = [
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })
  })

  describe('with empty array in params', () => {
    test('empty array as first param, with one topic as filter', async () => {
      const filterTopics = [
        [],
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test('empty array as first param, with one topic as filter in first index', async () => {
      const filterTopics = [
        [],
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
        "0x0000000000000000000000003cae5c23bfca0a1e2834fa6ffd2c55a32c11ddc9",
        "0x0000000000000000000000003838956710bcc9d122dd23863a0549ca8d5675d6"
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })

    test(`empty array as first param, topics don't exist in the transaction`, async () => {
      const filterTopics = [
        [],
        '0x000000000000000000000000dd58a0e3db99a98839086ccdabfa49e979290812',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })

    test('empty array as second param, with one topic as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        [],
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test(`empty array as second param, topics don't exist in the transaction`, async () => {
      const filterTopics = [
        '0x000000000000000000000000dd58a0e3db99a98839086ccdabfa49e979290812',
        [],
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })
  })

  describe('with array in params', () => {
    test('[] in filterTopics', async () => {
      const filterTopics = [[]]

      const transactionTopics: [] = []

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test('with one topic as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        [
          '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
          '0x000000000000000000000000dd58a0e3db99a98839086ccdabfa49e979290812',
        ],
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test(`with one topic as filter, topics don't exist in the transaction`, async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        [
          '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
          '0x000000000000000000000000adf9d0c77c70fcb1fdb868f54211288fce9937df',
        ],
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })

    test(`with one topic as filter, topics don't exist in the transaction`, async () => {
      const filterTopics = [
        null,
        [
          '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
          '0x000000000000000000000000adf9d0c77c70fcb1fdb868f54211288fce9937df',
        ],
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })
  })

  describe('string params', () => {
    test('with one topic as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test(`with one topic as filter, topics don't exist in the transaction`, async () => {
      const filterTopics = [
        '0x000000000000000000000000dd58a0e3db99a98839086ccdabfa49e979290812',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })

    test('with two topics as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })

    test('with three topics as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0x000000000000000000000000a5df6d8d59a7fbdb8a11e23fda9d11c4103dc49f',
        '0x00000000000000000000000003ddd5a675e2cfa35b9ae2b207a7dbd95fe24646',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })

    test('with three topics as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(true)
    })

    test('with four topics as filter', async () => {
      const filterTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      const transactionTopics = [
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
        '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
      ]

      expect(matchTopics(filterTopics, transactionTopics)).toBe(false)
    })
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { compileTopics } from '../src/topics';

// See: https://eth.wiki/json-rpc/API#eth_newFilter

const A = '0xAA';
const B = '0xBB';

import sql from 'sql-bricks';
const sqlConvert = (sql as any).convert;
(sql as any).convert = (val: unknown) => {
  if (val instanceof Uint8Array) {
    return `'\\x${Buffer.from(val).toString('hex')}'`;
  }
  return sqlConvert(val);
};

test('[] matches anything', () => {
  const where = compileTopics([]);
  expect(where).toEqual(null);
});

test('[A] matches A in topics[0]', () => {
  const where = compileTopics([A]);
  expect(where!.toString()).toEqual("e.topics[1] = '\\xaa'");
});

test('[null, B] matches anything in topics[0] and B in topics[2]', () => {
  const where = compileTopics([null, B]);
  expect(where!.toString()).toEqual("e.topics[2] = '\\xbb'");
});

test('[A, B] matches A in topics[1] and B in topics[2]', () => {
  const where = compileTopics([A, B]);
  expect(where!.toString()).toEqual(
    "(e.topics[1] = '\\xaa' AND e.topics[2] = '\\xbb')"
  );
});

test('[[A, B]] matches A or B in topics[1]', () => {
  const where = compileTopics([[A, B]]);
  expect(where!.toString()).toEqual(
    "(e.topics[1] = '\\xaa' OR e.topics[1] = '\\xbb')"
  );
});

test('[[A, B], [A, B]] matches A or B in topics[1] and A or B in topics[2]', () => {
  const where = compileTopics([
    [A, B],
    [A, B],
  ]);
  expect(where!.toString()).toEqual(
    "((e.topics[1] = '\\xaa' OR e.topics[1] = '\\xbb') AND (e.topics[2] = '\\xaa' OR e.topics[2] = '\\xbb'))"
  );
});

repo_name: aurora-is-near/aurora-relayer

repo_language: TypeScript

mime_type: text/plain


text:
/* This is free and unencumbered software released into the public domain. */

import { createApp } from '../lib/app.js';
import { Engine } from '@aurora-is-near/engine';
import externalConfig from 'config';
import os from 'os';
import pino from 'pino';

export const createServer = async({port = 0, attachAppToPort = true} = {}) => {
  const logger = pino();
  const engine = await Engine.connect(externalConfig, {
    HOME: os.homedir(),
  })
  const app = await createApp(
    {
      ...externalConfig,
      getLogsLimit: 5,
    },
    logger,
    engine
  )

  if (attachAppToPort) {
    const server = app.listen(port)
    return server
  }

  return app
}


text:
/// Creates a meta call from given arguments and auxiliary types.
export function createMetaCall(
  evmId,
  nonce,
  feeAmount,
  feeAddress,
  contractAddress,
  value,
  contractMethod,
  args,
  extraTypes
) {
  const types = {
    EIP712Domain: [
      { name: 'name', type: 'string' },
      { name: 'version', type: 'string' },
      { name: 'chainId', type: 'uint256' },
    ],
    NearTx: [
      { name: 'evmId', type: 'string' },
      { name: 'nonce', type: 'uint256' },
      { name: 'feeAmount', type: 'uint256' },
      { name: 'feeAddress', type: 'address' },
      { name: 'contractAddress', type: 'address' },
      { name: 'value', type: 'uint256' },
      { name: 'contractMethod', type: 'string' },
      { name: 'arguments', type: 'Arguments' },
    ],
  };
  Object.assign(types, extraTypes);
  return {
    types,
    domain: {
      name: 'NEAR',
      version: '1',
      chainId: 1313161555,
    },
    primaryType: 'NearTx' as const,
    message: {
      evmId,
      nonce,
      feeAmount,
      feeAddress,
      contractAddress,
      value,
      contractMethod,
      arguments: args,
    },
  };
}


text:
/* This is free and unencumbered software released into the public domain. */

import { createApp } from '../src/app';
import { Engine } from '@aurora-is-near/engine';
import externalConfig from 'config';
import { Config } from '../src/config';
import os from 'os';

import pino from 'pino';
import request from 'supertest';

let app: Promise<any>;

describe('AppServer', () => {
  beforeAll(async () => {
    const logger = pino();
    const engine = await Engine.connect((externalConfig as unknown) as Config, {
      HOME: os.homedir(),
    })
    app = await createApp(
      (externalConfig as unknown) as Config,
      logger,
      engine
    )
  })

  describe('Aurora-Process-Result headers', () => {
    test('array of eth_sendRawTransaction and eth_getCode, result and header should present', async () => {
      const response = await request(app)
        .post('/')
        .send([
          {
            jsonrpc: '2.0',
            method: 'eth_sendRawTransaction',
            params: [
              '0xf866820b2d80837a12009423a824dd17d6571e1badd25a6247c685d68029858080849c8a82caa0492c0061415907bbbe3f474e0ceb3b7a190042a5553666e3208c251a7d79a02ba035de2b41f11f877c8f938ea6b6be682e8276bcfa347e2c0923400a890657c883',
            ],
            id: 1,
          },
          {
            jsonrpc: '2.0',
            method: 'eth_sendRawTransaction',
            params: [
              '0xf8642d80837a120094ac2d0226ade52e6b4ccc97359359f01e34d503528080849c8a82c8a025b86590e2a8236e7cb5bbbb7a6e12ee1699c803f0f18163998a30223798f5faa00975dde1d880091fb47edb0769de9377ee7b640402e1dbe8b8778d32db3b5c7f',
            ],
            id: 2,
          },
          {
            jsonrpc: '2.0',
            method: 'eth_getCode',
            params: ['0x79898510Bf1cF4804AF0277D61745AD3703Ab73b'],
            id: 3,
          },
        ])

      const firstResponseTransaction = response.body[0]
      expect(firstResponseTransaction.id).toBe(1)
      expect(firstResponseTransaction.error.code).toBe(-32000)
      expect(firstResponseTransaction.error.message).toBe(
        'ERR_INCORRECT_NONCE'
      )
      expect(firstResponseTransaction).not.toHaveProperty('result')

      const secondResponseTransaction = response.body[1]
      expect(secondResponseTransaction.id).toBe(2)
      expect(secondResponseTransaction.error.code).toBe(-32000)
      expect(secondResponseTransaction.error.message).toBe(
        'ERR_INVALID_CHAIN_ID'
      )
      expect(secondResponseTransaction).not.toHaveProperty('result')

      const thirdResponseTransaction = response.body[2]
      expect(thirdResponseTransaction.id).toBe(3)
      expect(thirdResponseTransaction).not.toHaveProperty('error')
      expect(thirdResponseTransaction.result).toContain('0x6080604')

      const responseAuroraProcessResultHeaders = JSON.parse(
        response.headers['x-aurora-process-result']
      )

      expect(responseAuroraProcessResultHeaders).toHaveLength(3)

      expect(typeof responseAuroraProcessResultHeaders[0].neargas).toBe(
        'number'
      )
      expect(responseAuroraProcessResultHeaders[0]).toHaveProperty('tx')
      expect(responseAuroraProcessResultHeaders[0].error).toBe(
        'ERR_INCORRECT_NONCE'
      )

      expect(typeof responseAuroraProcessResultHeaders[1].neargas).toBe(
        'number'
      )
      expect(responseAuroraProcessResultHeaders[1]).toHaveProperty('tx')
      expect(responseAuroraProcessResultHeaders[1].error).toBe(
        'ERR_INVALID_CHAIN_ID'
      )

      expect(responseAuroraProcessResultHeaders[2]).toMatchObject({})
    })

    test('single eth_sendRawTransaction, result and header should present', async () => {
      const response = await request(app)
        .post('/')
        .send({
          jsonrpc: '2.0',
          id: 1,
          method: 'eth_sendRawTransaction',
          params: [
            '0xf866820b2d80837a12009423a824dd17d6571e1badd25a6247c685d68029858080849c8a82caa0492c0061415907bbbe3f474e0ceb3b7a190042a5553666e3208c251a7d79a02ba035de2b41f11f877c8f938ea6b6be682e8276bcfa347e2c0923400a890657c883',
          ],
        })

      expect(response.body.id).toBe(1)
      expect(response.body.error.code).toBe(-32000)
      expect(response.body.error.message).toBe('ERR_INCORRECT_NONCE')

      const responseAuroraProcessResultHeaders = JSON.parse(
        response.headers['x-aurora-process-result']
      )

      expect(responseAuroraProcessResultHeaders).toHaveLength(1)
      expect(typeof responseAuroraProcessResultHeaders[0].neargas).toBe(
        'number'
      )
      expect(responseAuroraProcessResultHeaders[0]).toHaveProperty('tx')
      expect(responseAuroraProcessResultHeaders[0].error).toBe(
        'ERR_INCORRECT_NONCE'
      )
    })

    test('array eth_getCode, result should present, headers should be skipped', async () => {
      const response = await request(app)
        .post('/')
        .send([
          {
            jsonrpc: '2.0',
            method: 'eth_getCode',
            params: ['0x6d7a65d4e761ae5f6832735db18e2c32132d7ff9'],
            id: 1,
          },
          {
            jsonrpc: '2.0',
            method: 'eth_getCode',
            params: ['0x79898510Bf1cF4804AF0277D61745AD3703Ab73b'],
            id: 2,
          },
        ])

      expect(response.body).toHaveLength(2)

      const firstResponseTransaction = response.body[0]
      expect(firstResponseTransaction.id).toBe(1)
      expect(firstResponseTransaction).not.toHaveProperty('error')
      expect(firstResponseTransaction.result).toContain('0x6080604')

      const secondResponseTransaction = response.body[1]
      expect(secondResponseTransaction.id).toBe(2)
      expect(secondResponseTransaction).not.toHaveProperty('error')
      expect(secondResponseTransaction.result).toContain('0x6080604')

      expect(response.headers).not.toHaveProperty('x-aurora-process-result')
    })

    test('single eth_getCode, result should present, headers should be skipped', async () => {
      const response = await request(app)
        .post('/')
        .send({
          jsonrpc: '2.0',
          id: 1,
          method: 'eth_getCode',
          params: ['0x79898510Bf1cF4804AF0277D61745AD3703Ab73b'],
        })

      expect(response.body.id).toBe(1)
      expect(response.body).not.toHaveProperty('error')
      expect(response.body.result).toContain('0x6080604')

      expect(response.headers).not.toHaveProperty('x-aurora-process-result')
    })
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getTransactionCount', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return data for address with transactions`, async () => {
    const response = await web3.eth.getTransactionCount('0x23a824dD17d6571e1BAdd25A6247C685D6802985', 'latest')

    expect(response).toBeGreaterThan(0)
  })

  test(`should return 0 for address without transactions`, async () => {
    const response = await web3.eth.getTransactionCount('0x1Ca3285DA521EC7ee20e3Ca72b7cd9e890F03906', 'latest')

    expect(response).toBe(0)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getTransactionReceipt', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT']
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return null for transaction that doesn't exist`, async () => {
    const response = await web3.eth.getTransactionReceipt(
      '0x0878f605c76e154225d87638e5691940ba7a9704ff2cd35c664db005c632098c'
    )

    expect(response).toBeNull()
  })

  test(`should return transaction receipt`, async () => {
    const response = await web3.eth.getTransactionReceipt(
      '0x5C33068B145D9028087D0A69DB07C612F292DC9274323C73DAFB7D37C1354549'
    )

    expect(response).toMatchInlineSnapshot(`
      Object {
        "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
        "blockNumber": 91896833,
        "contractAddress": null,
        "cumulativeGasUsed": 0,
        "from": "0xaa2666def065cbd1f16d2c3c296c0b3287ea2827",
        "gasUsed": 53310,
        "logs": Array [
          Object {
            "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
            "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
            "blockNumber": 91896833,
            "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
            "id": "log_a2758b4f",
            "logIndex": 0,
            "removed": false,
            "topics": Array [
              "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
              "0x000000000000000000000000000000000000000000000000000000000000494b",
            ],
            "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
            "transactionIndex": 0,
          },
        ],
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "nearReceiptHash": "0x88bf609224db551b6c3bddc9cc6880c6b764e793d3b2fb46c34ca4c6216150d5",
        "nearTransactionHash": "0xdc94085d1da9890574f4e437975f8122666ca2276158af299a2ce961bce08aea",
        "status": true,
        "to": "0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82",
        "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
        "transactionIndex": 0,
      }
    `)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getUncleByBlockHashAndIndex', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return null', async () => {
    const response = await web3.eth.getUncle(
      "0xc13eee2e7dc14762364d00584100bbe86c1faa97fc4694236cb5a928b2421330",
      "0x0"
    )

    expect(response).toBeNull()
  })

  test('should return null, when block exists', async () => {
    const response = await web3.eth.getUncle(
      "0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb",
      "0x0"
    )

    expect(response).toBeNull()
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('net_peerCount', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return 0', async () => {
    const response = await web3.eth.net.getPeerCount()

    expect(response).toBe(0)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_call', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`);
  });

  test('should call method from contract', async () => {
    const contractABI = [
      {
        inputs: [],
        name: 'check',
        outputs: [
          {
            internalType: 'uint256',
            name: '',
            type: 'uint256',
          },
        ],
        stateMutability: 'pure',
        type: 'function',
      },
    ];
    const contractAddress = '0x022F4C17628A68E0a5C39D8155216ba95Fa9e08a';
    const contract = new web3.eth.Contract(contractABI, contractAddress);
    const response = await contract.methods.check().call();

    expect(response).toBe('5');
  });

  test('should call revert method from contract', async () => {
    const contractABI = [
      {
        inputs: [
          {
            internalType: 'uint256',
            name: 'x',
            type: 'uint256',
          },
        ],
        name: 'data',
        outputs: [],
        stateMutability: 'nonpayable',
        type: 'function',
      },
    ];
    const contractAddress = '0xaF8bF14eA1dB408bfF5e9bcA18A0Af9cA906de29';

    const contract = new web3.eth.Contract(contractABI, contractAddress);

    const response = await contract.methods.data(5).call();

    expect(response).toMatchInlineSnapshot(`Result {}`);
  });

  test('OutOfGas', async () => {
    const response = await web3.eth.call({
      from: '0xFb9D99A9B3EC3b07933637960A05133bDEBD430c',
      to: '0xFb9D99A9B3EC3b07933637960A05133bDEBD430c',
      value: '0x1',
      gas: '0x1',
    });

    expect(response).toBe('0x');
  });

  test('OutOfFund', async () => {
    await expect(async () => {
      return await web3.eth.call({
        from: '0xFb9D99A9B3EC3b07933637960A05133bDEBD430c',
        to: '0xFb9D99A9B3EC3b07933637960A05133bDEBD430c',
        value: '0x56bc75e2d63100000',
      });
    }).rejects.toThrow('Returned error: Out Of Fund');
  });

  test('StackOverflow', async () => {
    let result: any = null;

    const contractABI = [
      {
        inputs: [],
        name: 'callToDeep',
        outputs: [],
        stateMutability: 'nonpayable',
        type: 'function',
      },
    ];
    const contractAddress = '0xB42A5f475216E4508ba22dFe21a0669c40BE2936';
    const contract = new web3.eth.Contract(contractABI, contractAddress);

    try {
      await contract.methods.callToDeep().call();
    } catch (err) {
      result = err;
    } finally {
      expect(result.message).toContain(
        'Returned error: ERR_STACK_OVERFLOW'
      );
    }
  });

  test('OutOfOffset', async () => {
    let result: any = null;

    const contractABI = [
      {
        inputs: [
          {
            internalType: 'address',
            name: 'target',
            type: 'address',
          },
        ],
        name: 'test',
        outputs: [],
        stateMutability: 'nonpayable',
        type: 'function',
      },
    ];
    const contractAddress = '0x4d0FcE38D795155b1A72e55423d3696d4aDff53b';
    const contract = new web3.eth.Contract(contractABI, contractAddress);

    try {
      await contract.methods
        .test('0xF53cC0eF22a093436BB53478b6B3FA8922264a70')
        .call();
    } catch (err) {
      result = err;
    } finally {
      expect(result.message).toContain('Returned error: Out Of Offset');
    }
  });

  test('CallTooDeep', async () => {
    let result: any = null;

    const contractABI = [
      {
        "inputs": [],
        "name": "test",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
      }
    ]
    const contractAddress = '0x73655f6d514b05ef1BEc27CfaCA01af5DA6B4388'
    const contract = new web3.eth.Contract(contractABI, contractAddress)

    try {
      await contract.methods
        .test()
        .call();
    } catch (err) {
      result = err;
    } finally {
      expect(result.message).toContain('Returned error: FunctionCallError(WasmTrap(Unreachable))');
    }
  });
});


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';
import request from 'supertest';
import { createServer } from '../helpers';

let web3: any;
let app: Promise<any>;

describe('eth_getLogs', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT']
    web3 = new Web3(`http://localhost:${port}`)
  })

  describe('without result', () => {
    test('should return [], with [] in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0x23a824dD17d6571e1BAdd25A6247C685D6802985',
        fromBlock: '0x3ecdf57',
        toBlock: '0x3ece307',
        topics: [
          [],
          [
            '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
          ],
        ],
      })

      expect(response).toEqual([])
    })

    test('should return [], with hash in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0x23a824dD17d6571e1BAdd25A6247C685D6802985',
        fromBlock: '0x3ecdf57',
        toBlock: '0x3ece307',
        topics: [
          '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
        ],
      })

      expect(response).toEqual([])
    })

    test('should return [], with double [] in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0x23a824dD17d6571e1BAdd25A6247C685D6802985',
        fromBlock: '0x3ecdf57',
        toBlock: '0x3ece307',
        topics: [
          [],
          [],
          '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
        ],
      })

      expect(response).toEqual([])
    })

    test('should return [], with double null in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0x23a824dD17d6571e1BAdd25A6247C685D6802985',
        fromBlock: '0x3ecdf57',
        toBlock: '0x3ece307',
        topics: [
          null,
          null,
          '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
        ],
      })

      expect(response).toEqual([])
    })

    test('should return [], with null in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0x23a824dD17d6571e1BAdd25A6247C685D6802985',
        fromBlock: '0x3ecdf57',
        toBlock: '0x3ece307',
        topics: [
          null,
          [
            '0x000000000000000000000000fe28a27a95e51bb2604abd65375411a059371616',
          ],
        ],
      })

      expect(response).toEqual([])
    })

    test('should return [], without topics param', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0x23a824dD17d6571e1BAdd25A6247C685D6802985',
        fromBlock: '0x3ecdf57',
        toBlock: '0x3ece307',
      })

      expect(response).toEqual([])
    })
  })

  describe('with result', () => {
    test('should return logs, with hex as blocks, without topics in params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
        fromBlock: '0x57a3c01',
        toBlock: '0x57a3c01',
      })

      expect(response).toMatchInlineSnapshot(`
        Array [
          Object {
            "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
            "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
            "blockNumber": 91896833,
            "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
            "id": "log_a2758b4f",
            "logIndex": 0,
            "removed": false,
            "topics": Array [
              "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
              "0x000000000000000000000000000000000000000000000000000000000000494b",
            ],
            "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
            "transactionIndex": 0,
          },
        ]
      `)
    })

    test('should return logs, with number as blocks, without topics in params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
        fromBlock: 91896833,
        toBlock: 91896833,
      })

      expect(response).toMatchInlineSnapshot(`
        Array [
          Object {
            "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
            "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
            "blockNumber": 91896833,
            "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
            "id": "log_a2758b4f",
            "logIndex": 0,
            "removed": false,
            "topics": Array [
              "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
              "0x000000000000000000000000000000000000000000000000000000000000494b",
            ],
            "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
            "transactionIndex": 0,
          },
        ]
      `)
    })

    test('should return logs, with [] in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
        fromBlock: '0x57a3c01',
        toBlock: '0x57a3c01',
        topics: [
          [],
          [
            '0x000000000000000000000000000000000000000000000000000000000000494b',
            '0x0000000000000000000000000000000000000000000000000000000000004941',
          ],
        ],
      })

      expect(response).toMatchInlineSnapshot(`
        Array [
          Object {
            "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
            "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
            "blockNumber": 91896833,
            "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
            "id": "log_a2758b4f",
            "logIndex": 0,
            "removed": false,
            "topics": Array [
              "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
              "0x000000000000000000000000000000000000000000000000000000000000494b",
            ],
            "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
            "transactionIndex": 0,
          },
        ]
      `)
    })

    test('should return logs, with null in topics params', async () => {
      const response = await web3.eth.getPastLogs({
        address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
        fromBlock: '0x57a3c01',
        toBlock: '0x57a3c01',
        topics: [
          null,
          '0x000000000000000000000000000000000000000000000000000000000000494b',
        ],
      })

      expect(response).toMatchInlineSnapshot(`
        Array [
          Object {
            "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
            "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
            "blockNumber": 91896833,
            "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
            "id": "log_a2758b4f",
            "logIndex": 0,
            "removed": false,
            "topics": Array [
              "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
              "0x000000000000000000000000000000000000000000000000000000000000494b",
            ],
            "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
            "transactionIndex": 0,
          },
        ]
      `)
    })

    describe('with empty topics params', () => {
      beforeAll(async () => {
        app = await createServer({
          attachAppToPort: false,
        })
      })

      test('should return logs, just null in topics params', async () => {
        const response = await web3.eth.getPastLogs({
          address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          fromBlock: '0x57a3c01',
          toBlock: '0x57a3c01',
          topics: [null],
        })

        expect(response).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": 91896833,
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "id": "log_a2758b4f",
              "logIndex": 0,
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": 0,
            },
          ]
        `)
      })

      test('should return logs, just few null in topics params', async () => {
        const response = await web3.eth.getPastLogs({
          address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          fromBlock: '0x57a3c01',
          toBlock: '0x57a3c01',
          topics: [null, null, null, null],
        })

        expect(response).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": 91896833,
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "id": "log_a2758b4f",
              "logIndex": 0,
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": 0,
            },
          ]
        `)
      })

      test('should return logs, just few [] in topics params', async () => {
        const response = await web3.eth.getPastLogs({
          address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          fromBlock: '0x57a3c01',
          toBlock: '0x57a3c01',
          topics: [
            [],
            [],
            [],
            [],
          ],
        })

        expect(response).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": 91896833,
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "id": "log_a2758b4f",
              "logIndex": 0,
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": 0,
            },
          ]
        `)
      })

      test('should return logs, just empty array in topics params', async () => {
        const response = await web3.eth.getPastLogs({
          address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          fromBlock: '0x57a3c01',
          toBlock: '0x57a3c01',
          topics: [[]],
        })

        expect(response).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": 91896833,
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "id": "log_a2758b4f",
              "logIndex": 0,
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": 0,
            },
          ]
        `)
      })

      test('should return logs, empty array and null in topics params', async () => {
        const response = await web3.eth.getPastLogs({
          address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          fromBlock: '0x57a3c01',
          toBlock: '0x57a3c01',
          topics: [[], null],
        })

        expect(response).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": 91896833,
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "id": "log_a2758b4f",
              "logIndex": 0,
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": 0,
            },
          ]
        `)
      })

      test('should return logs, null in array in topics params', async () => {
        const response = await web3.eth.getPastLogs({
          address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          fromBlock: '0x57a3c01',
          toBlock: '0x57a3c01',
          topics: [[null], null],
        })

        expect(response).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": 91896833,
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "id": "log_a2758b4f",
              "logIndex": 0,
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": 0,
            },
          ]
        `)
      })

      test('should return logs, null and empty array in array in topics params', async () => {
        const response = await request(app)
          .post('/')
          .send({
            jsonrpc: '2.0',
            id: 1,
            method: 'eth_getLogs',
            params: [
              {
                address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
                fromBlock: '0x57a3c01',
                toBlock: '0x57a3c01',
                topics: [
                  [
                    null, []
                  ]
                ],
              },
            ],
          })

        expect(response.body.result).toMatchInlineSnapshot(`
          Array [
            Object {
              "address": "0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82",
              "blockHash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
              "blockNumber": "0x57a3c01",
              "data": "0x000000000000000000000000000000000000000000000000000000035df15940000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
              "logIndex": "0x0",
              "removed": false,
              "topics": Array [
                "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
                "0x000000000000000000000000000000000000000000000000000000000000494b",
              ],
              "transactionHash": "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
              "transactionIndex": "0x0",
            },
          ]
        `)
      })
    })
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_protocolVersion', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return correct value', async () => {
    const response = await web3.eth.getProtocolVersion()

    expect(response).toBe('0x41')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_getCompilers', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should return []', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getCompilers',
        params: [],
      })

    expect(response.body.result).toEqual([])
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getBlockByNumber', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT']
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return latest block`, async () => {
    const response = await web3.eth.getBlock('latest')

    expect(response.hash).toHaveLength(66)
    expect(response.hash.startsWith('0x')).toBe(true)

    expect(response.number).toBeGreaterThanOrEqual(0)
  })

  test(`should return block by number`, async () => {
    const latestBlock = await web3.eth.getBlock('latest')
    const response = await web3.eth.getBlock(latestBlock.number)

    expect(response.hash).toHaveLength(66)
    expect(response.hash.startsWith('0x')).toBe(true)

    expect(response.number).toBeGreaterThanOrEqual(0)
  })

  test(`should return block by number, match snapshot`, async () => {
    const response = await web3.eth.getBlock(91896833)

    expect(response).toMatchInlineSnapshot(`
      Object {
        "difficulty": "0",
        "extraData": "0x",
        "gasLimit": 0,
        "gasUsed": 0,
        "hash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "miner": "0x0000000000000000000000000000000000000000",
        "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "nonce": "0x0000000000000000",
        "number": 91896833,
        "parentHash": "0x41e21a71f302a70853cc49e0b876c56867458f38200c792904be8c418675836c",
        "receiptsRoot": "0x3abf5db79c8b0856f1c3a547db4d6fd6b797dae1a17e58f59c9af946eec7e39c",
        "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
        "size": 1339,
        "stateRoot": "0xce08b5d80470391500ed7a9d429426307ebe12e994ece0c3dcd6fb29ee9c4e12",
        "timestamp": 1654706955,
        "totalDifficulty": "0",
        "transactions": Array [
          "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
        ],
        "transactionsRoot": "0x9de199b19c7b5c1eb43bed4dd6a7e8d1101cb8593ce4cc882b75cf9ebc6c8fc5",
        "uncles": Array [],
      }
    `)
  })

  test(`should return null for block that doesn't exist`, async () => {
    const response = await web3.eth.getBlock(Number.MAX_SAFE_INTEGER)

    expect(response).toBeNull()
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_hashrate', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return 0', async () => {
    const response = await web3.eth.getHashrate()

    expect(response).toBe(0)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_newFilter', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should return correct value', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [{}],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)
  })

  test('should return correct value, with address param', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [
          {
            address: '0x0000000000000000000000000000000000000000',
          },
        ],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)
  })

  test('should return correct value, with fromBlock and toBlock params', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [
          {
            fromBlock: 'earliest',
            toBlock: 'latest',
          },
        ],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_mining', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return false', async () => {
    const response = await web3.eth.isMining()

    expect(response).toBeFalsy()
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_newBlockFilter', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should return correct value', async () => {
    const response = await request(app).post('/').send({
      jsonrpc: '2.0',
      id: 1,
      method: 'eth_newBlockFilter',
      params: [],
    })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getCode', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return code of existed contract', async () => {
    const response = await web3.eth.getCode("0x02b93db565c9e2da73e9be058c4e303bbe414d9d")

    expect(response).toContain('0x')
    expect(response.length).toBe(240)
  })

  test(`should return 0 for contract that doesn't exist`, async () => {
    const response = await web3.eth.getCode("0x02b93db565c9e2da73e9be058c4e303bbe414d9c")

    expect(response).toBe("0x")
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getUncleByBlockNumberAndIndex', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return null', async () => {
    const response = await web3.eth.getUncle(
      Number.MAX_SAFE_INTEGER,
      "0x0"
    )

    expect(response).toBeNull()
  })

  test('should return null, when block exists', async () => {
    const response = await web3.eth.getUncle(
      91897216,
      "0x0"
    )

    expect(response).toBeNull()
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getBalance', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('with 0 balance', async () => {
    const response = await web3.eth.getBalance("0x702ed64ad1ed211a3cb3c4d7e8b5ca862f7527d6")

    expect(response).toBe("0")
  })

  test('with some funds', async () => {
    const response = await web3.eth.getBalance("0x23a824dD17d6571e1BAdd25A6247C685D6802985")

    expect(response).not.toBe("0")
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_uninstallFilter', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should uninstall eth_newFilter', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [{}],
      })

    const filterHash = response.body.result
    expect(filterHash).toContain(`0x`)
    expect(filterHash).not.toBe('0x00000000000000000000000000000000')

    const responseAfterUninstall = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_uninstallFilter',
        params: [filterHash],
      })

    expect(responseAfterUninstall.body.result).toBeTruthy()

    const responseGetFilterChanges = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterChanges',
        params: [filterHash],
      })

    expect(responseGetFilterChanges.body.error.code).toBe(-32000)
    expect(responseGetFilterChanges.body.error.message).toBe('filter not found')
  })

  test('should uninstall eth_newBlockFilter', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newBlockFilter',
        params: [{}],
      })

    const filterHash = response.body.result
    expect(filterHash).toContain(`0x`)
    expect(filterHash).not.toBe('0x00000000000000000000000000000000')

    const responseAfterUninstall = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_uninstallFilter',
        params: [filterHash],
      })

    expect(responseAfterUninstall.body.result).toBeTruthy()

    const responseGetFilterChanges = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterChanges',
        params: [filterHash],
      })

    expect(responseGetFilterChanges.body.error.code).toBe(-32000)
    expect(responseGetFilterChanges.body.error.message).toBe('filter not found')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('net_version', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return network ID for testnet', async () => {
    const response = await web3.eth.net.getId()

    expect(response).toBe(1313161555)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('net_listening', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return true', async () => {
    const response = await web3.eth.net.isListening()

    expect(response).toBeTruthy()
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_blockNumber', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return latest block', async () => {
    const response = await web3.eth.getBlockNumber()

    expect(response).toBeGreaterThan(0)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_newPendingTransactionFilter', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should return correct value', async () => {
    const response = await request(app).post('/').send({
      jsonrpc: '2.0',
      id: 1,
      method: 'eth_newPendingTransactionFilter',
      params: [],
    })

    expect(response.body.result).toBe(`0x00000000000000000000000000000000`)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getBlockTransactionCountByHash', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return 0 for block that doesn't exist`, async () => {
    const response = await web3.eth.getBlockTransactionCount('0x8e1431a5acd7039dc8baee870ea75e496aa0b030b54638c91c47d2dea6522ca2')

    expect(response).toBe(0)
  })

  test(`should return transactions count for block`, async () => {
    const response = await web3.eth.getBlockTransactionCount('0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1')

    expect(response).toBe(1)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getTransactionByBlockNumberAndIndex', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT']
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return null for block that doesn't exist`, async () => {
    const response = await web3.eth.getTransactionFromBlock(
      Number.MAX_SAFE_INTEGER,
      '0x1'
    )

    expect(response).toBeNull()
  })

  test(`should return transaction for block`, async () => {
    const response = await web3.eth.getTransactionFromBlock(91897216, '0x0')

    expect(response).toMatchInlineSnapshot(`
      Object {
        "blockHash": "0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb",
        "blockNumber": 91897216,
        "from": "0xAA2666DEF065cbd1F16D2C3C296c0b3287eA2827",
        "gas": 6721975,
        "gasPrice": "0",
        "hash": "0x661adbb4d1d36c919b284ec043584b538176a2f2d316cc3165b1470ff3993cf7",
        "input": "0x82b8ebc700000000000000000000000000000000000000000000000000000003663a5200",
        "nonce": 139434,
        "r": "0xe559e53801272702c3f1105748d9ebe118dc31d4694035c69c8772fcb8b8cad0",
        "s": "0x6428ff97292d6199b60f4586b839af965fc752889ff768c9f107667d8e7ae404",
        "to": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
        "transactionIndex": 0,
        "v": "0x9c8a82ca",
        "value": "0",
      }
    `)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_getFilterLogs', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false,
    })
  })

  test("should return error for filter which doesn't exists", async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterLogs',
        params: ['0xfe704947a3cd3ca12541458a4321c869'],
      })

    const error = response.body.error

    expect(error.code).toBe(-32000)
    expect(error.message).toBe('filter not found')
  })

  test('should return log object, with null in topics', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [
          {
            address: '0x19161c50f5e2cd8be249c1031ee295546ba2756f',
            topics: [
              null,
              '0x00000000000000000000000032edfdb3947a7defa9569e3fcfdfa9a4d69b349d',
            ],
          },
        ],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)

    const filterHash = response.body.result

    const responseGetFilterLogs = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterLogs',
        params: [filterHash],
      })

    expect(responseGetFilterLogs.body.result).toMatchInlineSnapshot(`
      Array [
        Object {
          "address": "0x19161c50f5e2cd8be249c1031ee295546ba2756f",
          "blockHash": "0x7d6ba4cb1daf8bf60983eea9695e1695a205374c11a8e99ab9241a9b203d03be",
          "blockNumber": "0x57a2ee1",
          "data": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "logIndex": "0x0",
          "removed": false,
          "topics": Array [
            "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b",
            "0x00000000000000000000000032edfdb3947a7defa9569e3fcfdfa9a4d69b349d",
          ],
          "transactionHash": "0x865d5e8b34b7ed7b9596e85d992418f80a55ac6186002823ff002850cbc4aa47",
          "transactionIndex": "0x0",
        },
      ]
    `)
  })

  test('should return log object, with [] in topics', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [
          {
            address: '0x19161c50f5e2cd8be249c1031ee295546ba2756f',
            topics: [
              [],
              '0x00000000000000000000000032edfdb3947a7defa9569e3fcfdfa9a4d69b349d',
            ],
          },
        ],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)

    const filterHash = response.body.result

    const responseGetFilterLogs = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterLogs',
        params: [filterHash],
      })

    expect(responseGetFilterLogs.body.result).toMatchInlineSnapshot(`
      Array [
        Object {
          "address": "0x19161c50f5e2cd8be249c1031ee295546ba2756f",
          "blockHash": "0x7d6ba4cb1daf8bf60983eea9695e1695a205374c11a8e99ab9241a9b203d03be",
          "blockNumber": "0x57a2ee1",
          "data": "0x0000000000000000000000000000000000000000000000000000000000000000",
          "logIndex": "0x0",
          "removed": false,
          "topics": Array [
            "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b",
            "0x00000000000000000000000032edfdb3947a7defa9569e3fcfdfa9a4d69b349d",
          ],
          "transactionHash": "0x865d5e8b34b7ed7b9596e85d992418f80a55ac6186002823ff002850cbc4aa47",
          "transactionIndex": "0x0",
        },
      ]
    `)
  })

  test('should return log object, with address, fromBlock and toBlock', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [
          {
            fromBlock: 91897216,
            toBlock: 91897216,
            address: '0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82',
          },
        ],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)

    const filterHash = response.body.result

    const responseGetFilterLogs = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterLogs',
        params: [filterHash],
      })

    expect(responseGetFilterLogs.body.result).toMatchInlineSnapshot(`
      Array [
        Object {
          "address": "0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82",
          "blockHash": "0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb",
          "blockNumber": "0x57a3d80",
          "data": "0x00000000000000000000000000000000000000000000000000000003663a5200000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
          "logIndex": "0x0",
          "removed": false,
          "topics": Array [
            "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
            "0x000000000000000000000000000000000000000000000000000000000000494f",
          ],
          "transactionHash": "0x661adbb4d1d36c919b284ec043584b538176a2f2d316cc3165b1470ff3993cf7",
          "transactionIndex": "0x0",
        },
      ]
    `)
  })

  test('should return log object, without address, with fromBlock and toBlock', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [
          {
            fromBlock: 91897216,
            toBlock: 91897216,
          },
        ],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)

    const filterHash = response.body.result

    const responseGetFilterLogs = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterLogs',
        params: [filterHash],
      })

    expect(responseGetFilterLogs.body.result).toMatchInlineSnapshot(`
      Array [
        Object {
          "address": "0xddf079d2f486f1ba8d5cbc0900e6a12c6f91ff82",
          "blockHash": "0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb",
          "blockNumber": "0x57a3d80",
          "data": "0x00000000000000000000000000000000000000000000000000000003663a5200000000000000000000000000aa2666def065cbd1f16d2c3c296c0b3287ea2827",
          "logIndex": "0x0",
          "removed": false,
          "topics": Array [
            "0x17eabd0a66fa631f7537cefdd5df6aa25d5ac904cf7596e958d43a75a00d0d68",
            "0x000000000000000000000000000000000000000000000000000000000000494f",
          ],
          "transactionHash": "0x661adbb4d1d36c919b284ec043584b538176a2f2d316cc3165b1470ff3993cf7",
          "transactionIndex": "0x0",
        },
      ]
    `)
  })

  test('should return error message, without params', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_newFilter',
        params: [{}],
      })

    expect(response.body.result).toContain(`0x`)
    expect(response.body.result.length).toBe(34)

    const filterHash = response.body.result

    const responseGetFilterLogs = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterLogs',
        params: [filterHash],
      })

    expect(responseGetFilterLogs.body.error.message).toBe('query returned more than 5 results')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_pendingTransactions', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return correct value', async () => {
    const response = await web3.eth.getPendingTransactions()

    expect(response).toEqual([])
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_accounts', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should return []', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_accounts',
        params: [],
      })

    expect(response.body.result).toEqual([])
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('web3_clientVersion', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return node info', async () => {
    const response = await web3.eth.getNodeInfo()

    expect(response).toBe('Aurora-Relayer/0.0.0')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getBlockByHash', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT']
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return null for block that doesn't exist`, async () => {
    const response = await web3.eth.getBlock(
      '0x702ed64ad1ed211a3cb3c4d7e8b5ca862f7527d6'
    )

    expect(response).toBeNull()
  })

  test(`should return block by hash`, async () => {
    const latestBlock = await web3.eth.getBlock('latest')
    const response = await web3.eth.getBlock(latestBlock.hash)

    expect(response.hash).toHaveLength(66)
    expect(response.hash.startsWith('0x')).toBe(true)

    expect(response.number).toBeGreaterThanOrEqual(0)
  })

  test(`should return block by hash, match snapshot`, async () => {
    const response = await web3.eth.getBlock(
      '0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1'
    )

    expect(response).toMatchInlineSnapshot(`
      Object {
        "difficulty": "0",
        "extraData": "0x",
        "gasLimit": 0,
        "gasUsed": 0,
        "hash": "0xfafdeeba634974d9dba58ff084f621666ad2fa7c292fbd48f2ee76ecfdc62ce1",
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "miner": "0x0000000000000000000000000000000000000000",
        "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "nonce": "0x0000000000000000",
        "number": 91896833,
        "parentHash": "0x41e21a71f302a70853cc49e0b876c56867458f38200c792904be8c418675836c",
        "receiptsRoot": "0x3abf5db79c8b0856f1c3a547db4d6fd6b797dae1a17e58f59c9af946eec7e39c",
        "sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
        "size": 1339,
        "stateRoot": "0xce08b5d80470391500ed7a9d429426307ebe12e994ece0c3dcd6fb29ee9c4e12",
        "timestamp": 1654706955,
        "totalDifficulty": "0",
        "transactions": Array [
          "0x5c33068b145d9028087d0a69db07c612f292dc9274323c73dafb7d37c1354549",
        ],
        "transactionsRoot": "0x9de199b19c7b5c1eb43bed4dd6a7e8d1101cb8593ce4cc882b75cf9ebc6c8fc5",
        "uncles": Array [],
      }
    `)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_syncing', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return block', async () => {
    const response = await web3.eth.isSyncing()

    expect(response).toBeFalsy()
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getUncleCountByBlockNumber', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return 0, when block exists', async () => {

    const latestBlock = await web3.eth.getBlock("latest")
    const fewBlocksAgo = await web3.eth.getBlock(latestBlock.number - 3)
    const response = await web3.eth.getBlockUncleCount(fewBlocksAgo.number)

    expect(response).toBe(0)
  })

  test(`should return null, when block doesn't exists`, async () => {
    const response = await web3.eth.getBlockUncleCount(Number.MAX_SAFE_INTEGER)

    expect(response).toBeNull()
  })

  test(`should return 0, when block exists`, async () => {
    const response = await web3.eth.getBlockUncleCount(91897216)

    expect(response).toBe(0)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getTransactionByBlockHashAndIndex', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return null for block that doesn't exist`, async () => {
    const response = await web3.eth.getTransactionFromBlock('0x010b3538f64be7467b479f71ca96279817e33656f752b43ff256901b22596295', '0x1')

    expect(response).toBeNull()
  })

  test(`should return transaction for block`, async () => {
    const response = await web3.eth.getTransactionFromBlock('0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb', '0x0')

    expect(response).toMatchInlineSnapshot(`
      Object {
        "blockHash": "0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb",
        "blockNumber": 91897216,
        "from": "0xAA2666DEF065cbd1F16D2C3C296c0b3287eA2827",
        "gas": 6721975,
        "gasPrice": "0",
        "hash": "0x661adbb4d1d36c919b284ec043584b538176a2f2d316cc3165b1470ff3993cf7",
        "input": "0x82b8ebc700000000000000000000000000000000000000000000000000000003663a5200",
        "nonce": 139434,
        "r": "0xe559e53801272702c3f1105748d9ebe118dc31d4694035c69c8772fcb8b8cad0",
        "s": "0x6428ff97292d6199b60f4586b839af965fc752889ff768c9f107667d8e7ae404",
        "to": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
        "transactionIndex": 0,
        "v": "0x9c8a82ca",
        "value": "0",
      }
    `)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('web3_sha3', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test('should return Keccak-256', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'web3_sha3',
        params: ['0x68656c6c6f20776f726c64'],
      })

    expect(response.body.result).toBe(`0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad`)
  })

  test('should return error with params are empty', async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'web3_sha3',
        params: [],
      })

    const error = response.body.error

    expect(error.code).toBe(-32603)
    expect(error.message).toContain('Internal Error - This method only supports 0x-prefixed hex strings but input was: undefined')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_estimateGas', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should constant value', async () => {
    const response = await web3.eth.estimateGas({
      to: "0x11f4d0A3c12e86B4b5F39B213F7E19D048276DAe",
      data: "0xc6888fa10000000000000000000000000000000000000000000000000000000000000003"
    })

    expect(response).toBe(6721975)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getStorageAt', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return storage position', async () => {
    const response = await web3.eth.getStorageAt("0x18a3612bcbb6df5b3bd30dbaec5ad321d3d1b4f9", "0x0", "latest")

    expect(response).toContain('0x')
    expect(response.length).toBe(66)
    expect(response).not.toBe('0x0000000000000000000000000000000000000000000000000000000000000000')
  })

  test('should return storage position for a non-existent address', async () => {
    const response = await web3.eth.getStorageAt("0x18a3612bcbb6df5b3bd30dbaec5ad321d3d1b4f1", "0x0", "latest")

    expect(response).toBe('0x0000000000000000000000000000000000000000000000000000000000000000')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getTransactionByHash', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT']
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return null for transaction that doesn't exist`, async () => {
    const response = await web3.eth.getTransaction(
      '0x926204a90109b89049965c3f31e862f0b0d1eb84103464d4d9f36fa9f037fee7'
    )

    expect(response).toBeNull()
  })

  test(`should return data for transaction that doesn't exist`, async () => {
    const response = await web3.eth.getTransaction(
      '0x661ADBB4D1D36C919B284EC043584B538176A2F2D316CC3165B1470FF3993CF7'
    )

    expect(response).toMatchInlineSnapshot(`
      Object {
        "blockHash": "0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb",
        "blockNumber": 91897216,
        "from": "0xAA2666DEF065cbd1F16D2C3C296c0b3287eA2827",
        "gas": 6721975,
        "gasPrice": "0",
        "hash": "0x661adbb4d1d36c919b284ec043584b538176a2f2d316cc3165b1470ff3993cf7",
        "input": "0x82b8ebc700000000000000000000000000000000000000000000000000000003663a5200",
        "nonce": 139434,
        "r": "0xe559e53801272702c3f1105748d9ebe118dc31d4694035c69c8772fcb8b8cad0",
        "s": "0x6428ff97292d6199b60f4586b839af965fc752889ff768c9f107667d8e7ae404",
        "to": "0xDdF079d2f486F1bA8D5cBC0900E6a12C6F91FF82",
        "transactionIndex": 0,
        "v": "0x9c8a82ca",
        "value": "0",
      }
    `)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getBlockTransactionCountByNumber', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test(`should return 0 for block that doesn't exist`, async () => {
    const response = await web3.eth.getBlockTransactionCount(Number.MAX_SAFE_INTEGER)

    expect(response).toBe(0)
  })

  test(`should return transactions count for block`, async () => {
    const response = await web3.eth.getBlockTransactionCount(91896833)

    expect(response).toBe(1)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_getUncleCountByBlockHash', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return 0, when block exists', async () => {

    const latestBlock = await web3.eth.getBlock("latest")
    const fewBlocksAgo = await web3.eth.getBlock(latestBlock.number - 3)
    const response = await web3.eth.getBlockUncleCount(fewBlocksAgo.hash)

    expect(response).toBe(0)
  })

  test(`should return null, when block doesn't exists`, async () => {
    const response = await web3.eth.getBlockUncleCount(`0x${'0'.repeat(64)}`)

    expect(response).toBeNull()
  })

  test(`should return 0, when block exists`, async () => {
    const response = await web3.eth.getBlockUncleCount(`0x0b7a7bbef2fdf7df5e4aeafe4f290150757fef8a980d7045302dbd468ddedeeb`)

    expect(response).toBe(0)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import { createServer } from '../helpers';
import request from 'supertest';

let app: Promise<any>;

describe('eth_getFilterChanges', () => {
  beforeAll(async () => {
    app = await createServer({
      attachAppToPort: false
    })
  })

  test("should return error for filter which doesn't exists", async () => {
    const response = await request(app)
      .post('/')
      .send({
        jsonrpc: '2.0',
        id: 1,
        method: 'eth_getFilterChanges',
        params: ["0xfe704947a3cd3ca12541458a4321c869"],
      })

    const error = response.body.error

    expect(error.code).toBe(-32000)
    expect(error.message).toBe('filter not found')
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_gasPrice', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return 0 gas price', async () => {
    const response = await web3.eth.getGasPrice()

    expect(response).toBe("0")
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_chainId', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return chain id for test net', async () => {
    const response = await web3.eth.getChainId()

    expect(response).toBe(1313161555)
  })
})


text:
/* This is free and unencumbered software released into the public domain. */

import Web3 from 'web3';

let web3: any;

describe('eth_coinbase', () => {
  beforeAll(async () => {
    const port = process.env['EXPRESS_PORT'];
    web3 = new Web3(`http://localhost:${port}`)
  })

  test('should return coinbase address', async () => {
    const response = await web3.eth.getCoinbase()

    expect(response).toBe('0x0000000000000000000000000000000000000000')
  })
})


text:
#!/bin/bash -e

CI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $CI_DIR/controls/common.sh

while test $# -gt 0
do
    case "$1" in
        --start) start_relayer=true
            ;;
        --rebuild) rebuild_relayer=true
            ;;
        --reset) reset_near=true
            ;;
        --reinit) reinit_near=true
            ;;
        --reinstall-cli) reinstall_cli=true
            ;;
        *) echo "bad argument $1" && exit 1
            ;;
    esac
    shift
done

if [[ ! -d $WORKDIR ]]; then
    mkdir $WORKDIR
fi

database_img=$(docker images -q ${DATABASE_IMAGE_NAME} 2> /dev/null)
endpoint_img=$(docker images -q ${ENDPOINT_IMAGE_NAME} 2> /dev/null)
if [[ ! -z $rebuild_relayer ]] || [[ -z $database_img ]] || [[ -z $endpoint_img ]]; then
    $CI_DIR/controls/relayer/build.sh
fi

if [[ ! -z $reinit_near ]] || [[ ! -d $WORKDIR/nearDataBackup ]]; then

    if [[ ! -z $reinstall_cli ]] || [[ ! -d $WORKDIR/near-cli ]] || [[ ! -d $WORKDIR/aurora-cli ]]; then
        $CI_DIR/controls/cli/install.sh
    fi

    rm -rf $WORKDIR/nearData $WORKDIR/nearDataBackup || true
    $CI_DIR/controls/network/create.sh
    $CI_DIR/controls/nearcore/init.sh
    $CI_DIR/controls/nearcore/start.sh
    echo "Sleeping for 2 seconds..." && sleep 2
    $CI_DIR/controls/contract/install.sh
    echo "Sleeping for 2 seconds..." && sleep 2
    $CI_DIR/controls/nearcore/stop.sh
    $CI_DIR/controls/network/remove.sh
    mv $WORKDIR/nearData $WORKDIR/nearDataBackup
fi

if [[ ! -z $reset_near ]] || [[ ! -d $WORKDIR/nearData ]]; then
    rm -rf $WORKDIR/nearData || true
    cp -r $WORKDIR/nearDataBackup $WORKDIR/nearData
fi

if [[ ! -z $start_relayer ]]; then
    $CI_DIR/controls/network/create.sh
    $CI_DIR/controls/nearcore/start.sh
    echo "Sleeping for 2 seconds..." && sleep 2
    $CI_DIR/controls/relayer/configure.sh
    $CI_DIR/controls/relayer/start.sh
    echo "Sleeping for 2 seconds..." && sleep 2

    echo "Setup finished!"
    echo "Putting nearcore hostname to .ci/workdir/nearcore.txt"
    echo "Putting relayer database hostname to .ci/workdir/database.txt"
    echo "Putting relayer endpoint hostname to .ci/workdir/endpoint.txt"
    if [[ ! -z $RUNNER_NAME ]]; then
        echo $NEARCORE_CONTAINER_NAME > $WORKDIR/nearcore.txt
        echo $DATABASE_CONTAINER_NAME > $WORKDIR/database.txt
        echo $ENDPOINT_CONTAINER_NAME > $WORKDIR/endpoint.txt
    else
        echo localhost > $WORKDIR/nearcore.txt
        echo localhost > $WORKDIR/database.txt
        echo localhost > $WORKDIR/endpoint.txt
    fi
fi


text:
#!/bin/bash -e

CI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $CI_DIR/controls/common.sh

while test $# -gt 0
do
    case "$1" in
        --clean) remove_images=true
            ;;
        *) echo "bad argument $1" && exit 1
            ;;
    esac
    shift
done

$CI_DIR/controls/relayer/stop.sh
$CI_DIR/controls/relayer/remove.sh
$CI_DIR/controls/nearcore/stop.sh
$CI_DIR/controls/network/remove.sh
if [[ ! -z $remove_images ]]; then
    $CI_DIR/controls/relayer/remove_images.sh
fi


text:
#!/bin/bash -e

CI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $CI_DIR/controls/common.sh

if [[ $1 == "nearcore" ]]; then
    docker logs $NEARCORE_CONTAINER_NAME
elif [[ $1 == "database" ]]; then
    docker logs $DATABASE_CONTAINER_NAME
elif [[ $1 == "indexer" ]]; then
    docker logs $INDEXER_CONTAINER_NAME
elif [[ $1 == "endpoint" ]]; then
    docker logs $ENDPOINT_CONTAINER_NAME
else
    echo "Unknown argument: $1"
fi


text:
## About

Scripts in this directory allow to setup relayer-testing environment:
1. Build docker images for `database` and `endpoint`
2. Pull, init and run `nearcore`
3. Create account `aurora.test.near`
4. Install `aurora-engine` contract
5. Run `database`, `indexer` and `endpoint`

All containers are connected to Docker bridge-network, so Docker's dynamic service-discovery is used to allow containers access each other (`hostname` = `container name`).

Hostnames are written into `.ci/workers/nearcore.txt`, `.ci/workers/database.txt` and `.ci/workers/endpoint.txt`
accordingly. In case of local run it's always `localhost`.

Ports:
- Nearcore: `3030`
- Database: `5432`
- Endpoint: `8545`

**Important**:
Dependency versions are locked for CI consistency (nearcore, aurora-cli, near-cli, aurora-engine).
Perform manual edit on `.ci/controls/common.sh` to update versions.

## Usage

### 1. Setting up environment

Use `./setup.sh` script to setup testing environment.
Parameters:
- `--start` - start relayer after setup
- `--rebuild` - rebuild relayer docker images (if nothing was changed, it usually takes no time)
- `--reset` - reset near state to the contract initialization point
- `--reinit` - reinitialize near data from scratch
- `--reinstall-cli` - reinstall aurora-cli and near-cli, useful only in case when version-locks for them was updated

**Note:** Running `./setup.sh --start` if components are already running will cause errors.

### 2. Exploring logs

You can explore logs of each component when they are running like this:
- `./show_logs.sh nearcore`
- `./show_logs.sh database`
- `./show_logs.sh indexer`
- `./show_logs.sh endpoint`

### 3. Stopping

To teardown the testing environment, run `./stop.sh`. To also remove docker-images from your system run `./stop.sh --clean`.

### Typical usage scenario

Most usually, you will want to use this scripts like this:

- Run `./setup.sh`, adding `--rebuild` (if relayer codebase was updated), adding `--reinit`
(if nearcore version-lock was updated or you want to reset neardata) and adding `--reinstall-cli`
(if aurora-cli or near-cli version locks were updated)
- `./setup.sh --reset --start`
- Run test #1
- `./stop.sh`
- `./setup.sh --reset --start`
- Run test #2
- `./stop.sh`
- ...

**Note:** In case if some tests do not conflict and do not require clean relayer/near data, you can group
them and run at once without restart.


text:
#!/bin/bash -e

CI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $CI_DIR/controls/common.sh

while test $# -gt 0
do
    case "$1" in
        --start) start_relayer=true
            ;;
        --rebuild) rebuild_relayer=true
            ;;
        *) echo "bad argument $1" && exit 1
            ;;
    esac
    shift
done

if [[ ! -d $WORKDIR ]]; then
    mkdir $WORKDIR
fi

database_img=$(docker images -q ${DATABASE_IMAGE_NAME} 2> /dev/null)
endpoint_img=$(docker images -q ${ENDPOINT_IMAGE_NAME} 2> /dev/null)
if [[ ! -z $rebuild_relayer ]] || [[ -z $database_img ]] || [[ -z $endpoint_img ]]; then
    $CI_DIR/controls/relayer/build.sh
fi

if [[ ! -z $start_relayer ]]; then
    $CI_DIR/controls/network/create.sh
    echo "Sleeping for 2 seconds..." && sleep 2
    $CI_DIR/controls/relayer/configure.sh
    $CI_DIR/controls/relayer/start.sh
    echo "Sleeping for 2 seconds..." && sleep 2

    echo "Setup finished!"
    echo "Putting relayer database hostname to .ci/workdir/database.txt"
    echo "Putting relayer endpoint hostname to .ci/workdir/endpoint.txt"
    if [[ ! -z $RUNNER_NAME ]]; then
        echo $DATABASE_CONTAINER_NAME > $WORKDIR/database.txt
        echo $ENDPOINT_CONTAINER_NAME > $WORKDIR/endpoint.txt
    else
        echo localhost > $WORKDIR/database.txt
        echo localhost > $WORKDIR/endpoint.txt
    fi
fi


text:
#!/bin/bash -e

CI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $CI_DIR/controls/common.sh

while test $# -gt 0
do
    case "$1" in
        --clean) remove_images=true
            ;;
        *) echo "bad argument $1" && exit 1
            ;;
    esac
    shift
done

$CI_DIR/controls/relayer/stop.sh
$CI_DIR/controls/relayer/remove.sh
$CI_DIR/controls/network/remove.sh
if [[ ! -z $remove_images ]]; then
    $CI_DIR/controls/relayer/remove_images.sh
fi


text:
#!/bin/bash -e

CI_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $CI_DIR/controls/common.sh

if [[ $1 == "database" ]]; then
    docker logs $DATABASE_CONTAINER_NAME
elif [[ $1 == "indexer" ]]; then
    docker logs $INDEXER_CONTAINER_NAME
elif [[ $1 == "endpoint" ]]; then
    docker logs $ENDPOINT_CONTAINER_NAME
else
    echo "Unknown argument: $1"
fi


text:
#!/bin/bash -e

CONTROLS_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
WORKDIR=$CONTROLS_DIR/../workdir
REPO_ROOT=$CONTROLS_DIR/../../..

if [[ ! -z $RUNNER_NAME ]]; then
    # All CI-runners are docker containers, and creating new
    # Docker objects (images, containers, etc) from some runner
    # will make them appear on host-level Docker, since
    # socket-binding solution is used for Docker-in-Docker.
    #
    # To avoid collision of such objects, $RUNNER_NAME suffix
    # is added to every object's name.

    UNIQUE_KEY=$(echo $RUNNER_NAME | tr '[:upper:]' '[:lower:]')
    COMMIT_HASH=$(git rev-parse HEAD)

    NETWORK_NAME=network-for-$UNIQUE_KEY
    RAW_DATABASE_IMAGE_NAME=relayer-raw-database-img-$COMMIT_HASH
    DATABASE_IMAGE_NAME=relayer-database-img-$COMMIT_HASH
    ENDPOINT_IMAGE_NAME=relayer-endpoint-img-$COMMIT_HASH
    DATABASE_CONTAINER_NAME=relayer-database-$UNIQUE_KEY
    INDEXER_CONTAINER_NAME=relayer-indexer-$UNIQUE_KEY
    ENDPOINT_CONTAINER_NAME=relayer-endpoint-$UNIQUE_KEY
else
    NETWORK_NAME=relayer-testing-network
    RAW_DATABASE_IMAGE_NAME=relayer-testing-raw-database-img
    DATABASE_IMAGE_NAME=relayer-testing-database-img
    ENDPOINT_IMAGE_NAME=relayer-testing-endpoint-img
    DATABASE_CONTAINER_NAME=relayer-testing-database
    INDEXER_CONTAINER_NAME=relayer-testing-indexer
    ENDPOINT_CONTAINER_NAME=relayer-testing-endpoint
fi


text:
#!/bin/bash -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $SCRIPT_DIR/../common.sh

echo "Removing inner network..."
if [[ ! -z $RUNNER_NAME ]]; then
    docker network disconnect -f $NETWORK_NAME $RUNNER_NAME || true
fi
docker network rm $NETWORK_NAME || true


text:
#!/bin/bash -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $SCRIPT_DIR/../common.sh

echo "Establishing inner network..."
docker network create -d bridge $NETWORK_NAME
if [[ ! -z $RUNNER_NAME ]]; then
    docker network connect $NETWORK_NAME $RUNNER_NAME
fi


text:
#!/bin/bash -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $SCRIPT_DIR/../common.sh

echo "Removing database and endpoint images..."
docker rmi -f $DATABASE_IMAGE_NAME $RAW_DATABASE_IMAGE_NAME $ENDPOINT_IMAGE_NAME || true


text:
#!/bin/bash -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $SCRIPT_DIR/../common.sh

echo "Removing endpoint, indexer and database containers..."
docker rm -f \
    $ENDPOINT_CONTAINER_NAME \
    $INDEXER_CONTAINER_NAME \
    $DATABASE_CONTAINER_NAME \
    || true


text:
#!/bin/bash -e

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
source $SCRIPT_DIR/../common.sh

echo "Stopping endpoint, indexer and database containers..."
docker stop \
    $ENDPOINT_CONTAINER_NAME \
    $INDEXER_CONTAINER_NAME \
    $DATABASE_CONTAINER_NAME \
    || true