import { Execute } from 'ox/erc7821'
import { describe, expect, test } from 'vp/test'

describe('encodeData', () => {
  test('default', () => {
    expect(
      Execute.encodeData([
        {
          data: '0xdeadbeef',
          to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
          value: 1n,
        },
        {
          data: '0xcafebabe',
          to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
          value: 2n,
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004cafebabe00000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: single call', () => {
    expect(
      Execute.encodeData([
        {
          data: '0xdeadbeef',
          to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
          value: 1000000000000000000n,
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c53010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe0000000000000000000000000000000000000000000000000de0b6b3a764000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: no data', () => {
    expect(
      Execute.encodeData([
        {
          to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
          value: 1n,
        },
        {
          to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
          value: 2n,
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c5301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: no value', () => {
    expect(
      Execute.encodeData([
        {
          data: '0xdeadbeef',
          to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        },
        {
          data: '0xcafebabe',
          to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004cafebabe00000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: empty calls array', () => {
    expect(Execute.encodeData([])).toMatchInlineSnapshot(
      `"0xe9ae5c5301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: with opData', () => {
    expect(
      Execute.encodeData(
        [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 1n,
          },
        ],
        { opData: '0x1234567890abcdef' },
      ),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000007821000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081234567890abcdef000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: with empty opData', () => {
    expect(
      Execute.encodeData(
        [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 1n,
          },
        ],
        { opData: '0x' },
      ),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000007821000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: mixed calls with and without data/value', () => {
    expect(
      Execute.encodeData([
        {
          to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
          value: 100n,
        },
        {
          data: '0xdeadbeef',
          to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
        },
        {
          data: '0xcafebabe',
          to: '0x1234567890123456789012345678901234567890',
          value: 200n,
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c5301000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000180000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000123456789012345678901234567890123456789000000000000000000000000000000000000000000000000000000000000000c800000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004cafebabe00000000000000000000000000000000000000000000000000000000"`,
    )
  })
})

describe('decodeData', () => {
  test('default', () => {
    const calls = [
      {
        data: '0xdeadbeef',
        to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        value: 1n,
      },
      {
        data: '0xcafebabe',
        to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
        value: 2n,
      },
    ] as const

    const encoded = Execute.encodeData(calls)
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({ calls })
  })

  test('behavior: single call', () => {
    const calls = [
      {
        data: '0xdeadbeef',
        to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        value: 1000000000000000000n,
      },
    ] as const

    const encoded = Execute.encodeData(calls)
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({ calls })
  })

  test('behavior: empty calls', () => {
    const calls = [] as const

    const encoded = Execute.encodeData(calls)
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({ calls })
  })

  test('behavior: with opData', () => {
    const calls = [
      {
        data: '0xdeadbeef',
        to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        value: 1n,
      },
    ] as const
    const opData = '0x1234567890abcdef' as const

    const encoded = Execute.encodeData(calls, { opData })
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({ calls, opData })
  })

  test('behavior: with empty opData', () => {
    const calls = [
      {
        data: '0xdeadbeef',
        to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        value: 1n,
      },
    ] as const
    const opData = '0x' as const

    const encoded = Execute.encodeData(calls, { opData })
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({
      calls,
      opData: undefined,
    })
  })

  test('behavior: no data or value', () => {
    const calls = [
      {
        to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        value: 0n,
        data: '0x',
      },
    ] as const

    const encoded = Execute.encodeData(calls)
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({ calls })
  })

  test('behavior: round trip with mixed calls', () => {
    const calls = [
      {
        to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
        value: 100n,
        data: '0x',
      },
      {
        data: '0xdeadbeef',
        to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
        value: 0n,
      },
      {
        data: '0xcafebabe',
        to: '0x1234567890123456789012345678901234567890',
        value: 200n,
      },
    ] as const

    const encoded = Execute.encodeData(calls)
    const result = Execute.decodeData(encoded)

    expect(result).toEqual({ calls })
  })
})

describe('encodeBatchOfBatchesData', () => {
  test('default', () => {
    expect(
      Execute.encodeBatchOfBatchesData([
        {
          calls: [
            {
              data: '0xcafebabe',
              to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
              value: 1n,
            },
          ],
        },
        {
          calls: [
            {
              data: '0xdeadbeef',
              to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
              value: 2n,
            },
          ],
          opData: '0x1234567890abcdef',
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c5301000000000078210002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004cafebabe0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000081234567890abcdef000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: single batch', () => {
    expect(
      Execute.encodeBatchOfBatchesData([
        {
          calls: [
            {
              data: '0xdeadbeef',
              to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
              value: 1n,
            },
          ],
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000007821000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: batch without opData', () => {
    expect(
      Execute.encodeBatchOfBatchesData([
        {
          calls: [
            {
              data: '0xcafebabe',
              to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
              value: 1n,
            },
          ],
        },
        {
          calls: [
            {
              data: '0xdeadbeef',
              to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
              value: 2n,
            },
          ],
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000007821000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004cafebabe000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: batch with empty opData', () => {
    expect(
      Execute.encodeBatchOfBatchesData([
        {
          calls: [
            {
              data: '0xdeadbeef',
              to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
              value: 1n,
            },
          ],
          opData: '0x',
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c530100000000007821000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: multiple calls per batch', () => {
    expect(
      Execute.encodeBatchOfBatchesData([
        {
          calls: [
            {
              data: '0xcafebabe',
              to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
              value: 1n,
            },
            {
              data: '0xdeadbeef',
              to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
              value: 2n,
            },
          ],
        },
      ]),
    ).toMatchInlineSnapshot(
      `"0xe9ae5c5301000000000078210002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000001c000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000deadbeefdeadbeefdeadbeefdeadbeefdeadbeef000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004cafebabe00000000000000000000000000000000000000000000000000000000000000000000000000000000cafebabecafebabecafebabecafebabecafebabe000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000004deadbeef00000000000000000000000000000000000000000000000000000000"`,
    )
  })

  test('behavior: empty batches array', () => {
    expect(Execute.encodeBatchOfBatchesData([])).toMatchInlineSnapshot(
      `"0xe9ae5c5301000000000078210002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000"`,
    )
  })
})

describe('decodeBatchOfBatchesData', () => {
  test('default', () => {
    const batches = [
      {
        calls: [
          {
            data: '0xcafebabe',
            to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
            value: 1n,
          },
        ],
      },
      {
        calls: [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 2n,
          },
        ],
        opData: '0x1234567890abcdef',
      },
    ] as const

    const encoded = Execute.encodeBatchOfBatchesData(batches)
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })

  test('behavior: single batch', () => {
    const batches = [
      {
        calls: [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 1n,
          },
        ],
      },
    ] as const

    const encoded = Execute.encodeBatchOfBatchesData(batches)
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })

  test('behavior: batch without opData', () => {
    const batches = [
      {
        calls: [
          {
            data: '0xcafebabe',
            to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
            value: 1n,
          },
        ],
      },
      {
        calls: [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 2n,
          },
        ],
      },
    ] as const

    const encoded = Execute.encodeBatchOfBatchesData(batches)
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })

  test('behavior: batch with empty opData', () => {
    const batches = [
      {
        calls: [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 1n,
          },
        ],
      },
    ] as const
    const opData = '0x' as const

    const encoded = Execute.encodeBatchOfBatchesData([
      { calls: batches[0].calls, opData },
    ])
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })

  test('behavior: multiple calls per batch', () => {
    const batches = [
      {
        calls: [
          {
            data: '0xcafebabe',
            to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
            value: 1n,
          },
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 2n,
          },
        ],
      },
    ] as const

    const encoded = Execute.encodeBatchOfBatchesData(batches)
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })

  test('behavior: empty batches', () => {
    const batches = [] as const

    const encoded = Execute.encodeBatchOfBatchesData(batches)
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })

  test('behavior: mixed batches with and without opData', () => {
    const batches = [
      {
        calls: [
          {
            data: '0xcafebabe',
            to: '0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
            value: 100n,
          },
        ],
      },
      {
        calls: [
          {
            data: '0xdeadbeef',
            to: '0xCafEBAbECAFEbAbEcaFEbabECAfebAbEcAFEBaBe',
            value: 200n,
          },
        ],
        opData: '0xabcdef',
      },
      {
        calls: [
          {
            to: '0x1234567890123456789012345678901234567890',
            value: 300n,
            data: '0x',
          },
        ],
      },
    ] as const

    const encoded = Execute.encodeBatchOfBatchesData(batches)
    const result = Execute.decodeBatchOfBatchesData(encoded)

    expect(result).toEqual(batches)
  })
})
