ethers/lib/utils#getAddress TypeScript Examples

The following examples show how to use ethers/lib/utils#getAddress. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.ts    From hubble-contracts with MIT License 7 votes vote down vote up
/**
 * Generates a random address. Usefully for testing when
 * you don't need a valid address or contract.
 *
 * @returns Randomly generated address.
 */
export function randomAddress(): string {
    return getAddress(randHex(20));
}
Example #2
Source File: generator.ts    From merkle-airdrop-starter with GNU Affero General Public License v3.0 6 votes vote down vote up
/**
   * Setup generator
   * @param {number} decimals of token
   * @param {Record<string, number>} airdrop address to token claim mapping
   */
  constructor(decimals: number, airdrop: Record<string, number>) {
    // For each airdrop entry
    for (const [address, tokens] of Object.entries(airdrop)) {
      // Push:
      this.recipients.push({
        // Checksum address
        address: getAddress(address),
        // Scaled number of tokens claimable by recipient
        value: parseUnits(tokens.toString(), decimals).toString()
      });
    }
  }
Example #3
Source File: index.ts    From pancake-nft-api with GNU General Public License v3.0 6 votes vote down vote up
getCDN = (address: string, type: "avatar" | "banner-lg" | "banner-sm"): string => {
  switch (type) {
    case "avatar":
      return `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(address)}/avatar.png`;
    case "banner-lg":
      return `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(address)}/banner-lg.png`;
    case "banner-sm":
      return `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(address)}/banner-sm.png`;
    default:
      return `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/unknown.png`;
  }
}
Example #4
Source File: types.test.ts    From hubble-contracts with MIT License 6 votes vote down vote up
describe("Type testing", function() {
    let contract: TestTypes;
    before(async function() {
        const [signer] = await ethers.getSigners();
        contract = await new TestTypes__factory(signer).deploy();
    });
    it("encode and decode meta fields", async function() {
        const expected = {
            batchType: randomNum(1),
            size: randomNum(1),
            committer: getAddress(randHex(20)),
            finaliseOn: randomNum(4)
        };

        const meta = await contract.encodeMeta(
            expected.batchType,
            expected.size,
            expected.committer,
            expected.finaliseOn
        );
        const {
            batchType,
            size,
            committer,
            finaliseOn
        } = await contract.decodeMeta(meta);
        assert.equal(batchType.toNumber(), expected.batchType);
        assert.equal(size.toNumber(), expected.size);
        assert.equal(committer, expected.committer);
        assert.equal(finaliseOn.toNumber(), expected.finaliseOn);
    });
});
Example #5
Source File: proposing.ts    From safe-tasks with GNU Lesser General Public License v3.0 5 votes vote down vote up
buildMetaTx = (description: TxDescription): MetaTransaction => {
    const to = getAddress(description.to)
    const value = parseEther(description.value).toString()
    const operation = description.operation
    const data = isHexString(description.data) ? description.data!! : (description.method ? buildData(description.method, description.params) : "0x")
    return { to, value, data, operation }
}
Example #6
Source File: index.ts    From pancake-nft-api with GNU General Public License v3.0 5 votes vote down vote up
fetchGeneric = async (collection: Collection, page: number, size: number) => {
  const tokenModel = await getModel("Token");
  const tokens = await tokenModel.paginate(
    { parent_collection: collection },
    {
      page: page,
      limit: size,
      sort: { token_id: "asc" },
      populate: ["metadata", "attributes"],
      collation: { locale: "en_US", numericOrdering: true },
    }
  );

  let data = {};
  const attributesDistribution: { [key: string]: { [key: string]: number } } = {};
  tokens.docs.forEach((token: Token) => {
    const metaName = paramCase(token.metadata.name);
    data = {
      ...data,
      [token.token_id]: {
        tokenId: token.token_id,
        name: token.metadata.name,
        description: token.metadata.description,
        image: {
          original: `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(collection.address)}/${metaName}.png`,
          thumbnail: `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(
            collection.address
          )}/${metaName}-1000.png`,
          mp4: token.metadata.mp4
            ? `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(collection.address)}/${metaName}.mp4`
            : null,
          webm: token.metadata.webm
            ? `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(collection.address)}/${metaName}.webm`
            : null,
          gif: token.metadata.gif
            ? `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(collection.address)}/${metaName}.gif`
            : null,
        },
        attributes: token.attributes
          ? token.attributes.map((attribute: Attribute) => ({
              traitType: attribute.trait_type,
              value: attribute.value,
              displayType: attribute.display_type,
            }))
          : [],
        collection: {
          name: collection.name,
        },
      },
    };

    // update the attributesDistribution distribution according to this token attributes
    token.attributes.forEach((attribute) => {
      const traitType = attribute.trait_type;
      const traitValue = attribute.value;
      // Safe checks on the object structure
      if (!get(attributesDistribution, traitType)) {
        attributesDistribution[traitType] = {};
      }
      if (!get(attributesDistribution, [traitType, traitValue])) {
        attributesDistribution[traitType][traitValue] = 0;
      }

      attributesDistribution[traitType][traitValue] += 1;
    });
  });

  return { data, attributesDistribution };
}
Example #7
Source File: index.ts    From pancake-nft-api with GNU General Public License v3.0 5 votes vote down vote up
fetchPancakeBunnies = async (collection: Collection) => {
  const attributeModel = await getModel("Attribute");
  const attributes: Attribute[] = await attributeModel
    .find({ parent_collection: collection })
    .sort({ value: "asc" })
    .collation({ locale: "en_US", numericOrdering: true })
    .exec();

  const tokenModel = await getModel("Token");
  const promisesTokens = attributes.map(async (attribute) => {
    const res: Token = await tokenModel
      .findOne({ parent_collection: collection, attributes: attribute })
      .populate(["metadata", "attributes"])
      .exec();

    if (!res) {
      return null;
    }

    const metaName = paramCase(res.metadata.name);
    return {
      name: res.metadata.name,
      description: res.metadata.description,
      image: {
        original: `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(PANCAKE_BUNNY_ADDRESS)}/${metaName}.png`,
        thumbnail: `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(
          PANCAKE_BUNNY_ADDRESS
        )}/${metaName}-1000.png`,
        mp4: res.metadata.mp4
          ? `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(PANCAKE_BUNNY_ADDRESS)}/${metaName}.mp4`
          : null,
        webm: res.metadata.webm
          ? `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(PANCAKE_BUNNY_ADDRESS)}/${metaName}.webm`
          : null,
        gif: res.metadata.gif
          ? `${CONTENT_DELIVERY_NETWORK_URI}/${NETWORK}/${getAddress(PANCAKE_BUNNY_ADDRESS)}/${metaName}.gif`
          : null,
      },
      collection: {
        name: collection.name,
      },
    };
  });
  const tokens = await Promise.all(promisesTokens);

  const data: { [key: string]: Token } = attributes.reduce((acc, attribute: Attribute) => {
    const bunnyId = parseInt(attribute.value, 10);
    const token = tokens[bunnyId];
    return {
      ...acc,
      [bunnyId]: token,
    };
  }, {});

  const promisesAttributesDistribution = attributes.map(async (attribute: Attribute) => {
    return await tokenModel
      .aggregate([
        {
          $match: {
            parent_collection: collection._id,
            attributes: attribute._id,
            burned: false,
          },
        },
      ])
      .count("token_id")
      .exec();
  });
  const attributesDistribution = await Promise.all(promisesAttributesDistribution);

  return {
    data,
    attributesDistribution: attributesDistribution.reduce(
      (acc, value, index) => ({ ...acc, [index]: value[0] ? value[0].token_id : 0 }),
      {}
    ),
  };
}
Example #8
Source File: deploymentUtils.ts    From gateway-sol with GNU General Public License v3.0 5 votes vote down vote up
randomAddress = (): string => getAddress("0x" + randomBytes(20).toString("hex"))
Example #9
Source File: deploymentUtils.ts    From gateway-sol with GNU General Public License v3.0 5 votes vote down vote up
forwardTokens =
    (hre: HardhatRuntimeEnvironment, config?: NetworkConfig, logger: ConsoleInterface = console) =>
    async (to: string) => {
        const { getNamedAccounts, ethers, network } = hre;

        logger.log(`Deploying to ${network.name}...`);

        const Ox = ethers.utils.getAddress;

        config = config || networks[network.name as "hardhat"];
        if (!config) {
            throw new Error(`No network configuration found for ${network.name}!`);
        }

        const chainId: number = (await ethers.provider.getNetwork()).chainId;
        const { deployer } = await getNamedAccounts();

        const waitForTx = setupWaitForTx(logger);

        // Test Tokens are deployed when a particular lock-asset doesn't exist on a
        // testnet.
        console.log(`Handling ${(config.lockGateways || []).length} lock assets.`);
        for (const { symbol, gateway, token, decimals } of config.lockGateways || []) {
            console.log(chalk.yellow(`Lock asset: ${symbol}`));
            // Check token symbol and decimals
            if (token && typeof token === "string") {
                const erc20 = await ethers.getContractAt<ERC20>("ERC20", token);
                const recipient = "0xFB87bCF203b78d9B67719b7EEa3b6B65A208961B";
                const deployerBalance = new BigNumber((await erc20.balanceOf(deployer)).toString());
                const recipientBalance = new BigNumber((await erc20.balanceOf(recipient)).toString());
                const decimals = await erc20.decimals();
                const amount = BigNumber.min(
                    deployerBalance.dividedBy(10),
                    new BigNumber(10000).shiftedBy(decimals)
                ).minus(recipientBalance);
                if (amount.isGreaterThan(0)) {
                    console.log(`Transferring ${amount.shiftedBy(-decimals).toFixed()} ${symbol}`);
                    await waitForTx(erc20.transfer(recipient, amount.toFixed()));
                } else {
                    console.log(`Skipping ${symbol}`);
                }
            }
        }
    }
Example #10
Source File: useEthers.ts    From useDApp with MIT License 4 votes vote down vote up
/**
 * Returns connection state and functions that allow to manipulate the state.
 * **Requires**: `<ConfigProvider>`
 * 
 * @public
 * @returns {} Object with the following:
    - `account: string` - current user account (or *undefined* if not connected)
    - `chainId: ChainId` - current chainId (or *undefined* if not connected)
    - `library: Web3Provider` - an instance of ethers [Web3Provider](https://github.com/EthWorks/useDapp/tree/master/packages/example) (or `undefined` if not connected)
    - `active: boolean` - returns if provider is connected (read or write mode)
    - `activateBrowserWallet()` - function that will initiate connection to browser web3 extension (e.g. Metamask)
    - `async activate(connector: AbstractConnector, onError?: (error: Error) => void, throwErrors?: boolean)` - function that allows to connect to a wallet
    - `async deactivate()` - function that disconnects wallet
    - `error?: Error` - an error that occurred during connecting (e.g. connection is broken, unsupported network)
 */
export function useEthers(): Web3Ethers {
  const {
    network: { provider: networkProvider, chainId, accounts, errors },
    deactivate,
    activate,
    activateBrowserWallet,
    isLoading,
  } = useNetwork()

  const { networks } = useConfig()
  const supportedChainIds = networks?.map((network) => network.chainId)
  const isUnsupportedChainId = chainId && supportedChainIds && supportedChainIds.indexOf(chainId) < 0
  const unsupportedChainIdError = new Error(
    `Unsupported chain id: ${chainId}. Supported chain ids are: ${supportedChainIds}.`
  )
  unsupportedChainIdError.name = 'UnsupportedChainIdError'
  const error = isUnsupportedChainId ? unsupportedChainIdError : errors[errors.length - 1]

  const readonlyNetwork = useReadonlyNetwork()
  const provider = networkProvider ?? (readonlyNetwork?.provider as JsonRpcProvider)

  const switchNetwork = async (chainId: number) => {
    validateArguments({ chainId }, { chainId: 'number' })

    if (!provider) {
      throw new Error('Provider not connected.')
    }

    try {
      await provider.send('wallet_switchEthereumChain', [{ chainId: `0x${chainId.toString(16)}` }])
    } catch (error: any) {
      const errChainNotAddedYet = 4902 // Metamask error code
      if (error.code === errChainNotAddedYet) {
        const chain = networks?.find((chain) => chain.chainId === chainId)
        if (chain?.rpcUrl) {
          await provider.send('wallet_addEthereumChain', [getAddNetworkParams(chain)])
        }
      }
    }
  }

  const account = accounts[0] ? getAddress(accounts[0]) : undefined

  return {
    connector: undefined,
    library: provider,
    chainId: isUnsupportedChainId ? undefined : networkProvider !== undefined ? chainId : readonlyNetwork?.chainId,
    account,
    active: !!provider,
    activate: async (providerOrConnector: SupportedProviders) => {
      if ('getProvider' in providerOrConnector) {
        console.warn('Using web3-react connectors is deprecated and may lead to unexpected behavior.')
        await providerOrConnector.activate()
        return activate(await providerOrConnector.getProvider())
      }
      return activate(providerOrConnector)
    },
    activateBrowserWallet,
    deactivate,

    setError: () => {
      throw new Error('setError is deprecated')
    },

    error,
    isLoading,

    switchNetwork,
  }
}
Example #11
Source File: useLogs.test.tsx    From useDApp with MIT License 4 votes vote down vote up
describe('useLogs', () => {
  const mockProvider = new MockProvider()
  const secondMockProvider = new MockProvider({ ganacheOptions: { _chainIdRpc: SECOND_TEST_CHAIN_ID } as any })
  const [deployer, receiver] = mockProvider.getWallets()
  const [secondDeployer] = secondMockProvider.getWallets()
  let token: Contract
  let secondToken: Contract

  beforeEach(async () => {
    token = await deployMockToken(deployer)
    secondToken = await deployMockToken(secondDeployer, SECOND_MOCK_TOKEN_INITIAL_BALANCE)
  })

  async function sendToken(signer: ethers.Wallet, to: string, amount: BigNumber) {
    const { result, waitForCurrent, waitForNextUpdate } = await renderWeb3Hook(
      () =>
        useSendTransaction({
          signer,
        }),
      { mockProvider }
    )

    await waitForNextUpdate()

    const txData = ERC20MockInterface.encodeFunctionData('transfer(address,uint)', [to, amount])

    const tx: TransactionRequest = {
      to: token.address,
      value: BigNumber.from(0),
      data: txData,
      gasPrice: 0,
    }

    await result.current.sendTransaction(tx)

    await waitForCurrent((val) => val.state !== undefined)
    expect(result.current.state.status).to.eq('Success')

    return result.current.state
  }

  it('Can get only the recent token transfer log', async () => {
    const blockNumber = await mockProvider.getBlockNumber()

    const from = deployer
    const to = receiver

    const fromAddress = from.address
    const toAddress = to.address
    const amount = BigNumber.from(1)

    await sendToken(from, toAddress, amount)

    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: token,
            event: 'Transfer',
            args: [],
          },
          {
            fromBlock: blockNumber + 1,
            toBlock: blockNumber + 2,
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(1, 'Number of logs')

    const log = result.current!.value![0]

    expect(getAddress(log.data['from'])).to.equal(getAddress(fromAddress), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(toAddress), 'To')
    expect(log.data['value']).to.equal(amount, 'Amount')
  })

  it('Can get all token transfer logs using the default log query parameters', async () => {
    const from = deployer
    const to = receiver

    const fromAddress = from.address
    const toAddress = to.address
    const amount = BigNumber.from(1)

    await sendToken(from, toAddress, amount)

    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs({
          contract: token,
          event: 'Transfer',
          args: [],
        }),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(2, 'Number of logs')

    // Mint transfer event
    const log1 = result.current!.value![0]

    expect(getAddress(log1.data['from'])).to.equal(getAddress(AddressZero), 'From')
    expect(getAddress(log1.data['to'])).to.equal(getAddress(deployer.address), 'To')
    expect(log1.data['value']).to.equal(MOCK_TOKEN_INITIAL_BALANCE, 'Amount')

    // Recent transfer transaction log
    const log = result.current!.value![1]

    expect(getAddress(log.data['from'])).to.equal(getAddress(fromAddress), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(toAddress), 'To')
    expect(log.data['value']).to.equal(amount, 'Amount')
  })

  it('Can get the mint transfer log', async () => {
    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: token,
            event: 'Transfer',
            args: [],
          },
          {
            fromBlock: 0,
            toBlock: 'latest',
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(1, 'Number of logs')

    const log = result.current!.value![0]

    expect(getAddress(log.data['from'])).to.equal(getAddress(AddressZero), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(deployer.address), 'To')
    expect(log.data['value']).to.equal(MOCK_TOKEN_INITIAL_BALANCE, 'Amount')
  })

  it('Can get the mint transfer log on the alternative chain', async () => {
    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: secondToken,
            event: 'Transfer',
            args: [],
          },
          {
            fromBlock: 0,
            toBlock: 'latest',
          }
        ),
      {
        mockProvider: secondMockProvider,
      }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(1, 'Number of logs')

    const log = result.current!.value![0]

    expect(getAddress(log.data['from'])).to.equal(getAddress(AddressZero), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(secondDeployer.address), 'To')
    expect(log.data['value']).to.equal(SECOND_MOCK_TOKEN_INITIAL_BALANCE, 'Amount')
  })

  it('Works if there are no logs', async () => {
    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: secondToken, // Token on the other chain... doesn't exist so there should be no logs
            event: 'Transfer',
            args: [],
          },
          {
            fromBlock: 0,
            toBlock: 'latest',
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined
    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(0, 'Number of logs')
  })

  it('Can query mint transfer logs by sender', async () => {
    // Send to emit another Transfer token that our filter should filter out
    await sendToken(deployer, receiver.address, BigNumber.from(1))

    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: token,
            event: 'Transfer',
            args: [AddressZero],
          },
          {
            fromBlock: 0,
            toBlock: 'latest',
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(1, 'Number of logs')

    const log = result.current!.value![0]

    expect(getAddress(log.data['from'])).to.equal(getAddress(AddressZero), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(deployer.address), 'To')
    expect(log.data['value']).to.equal(MOCK_TOKEN_INITIAL_BALANCE, 'Amount')
  })

  it('Can query mint transfer logs by receiver', async () => {
    // Send to emit another Transfer token that our filter should filter out
    await sendToken(deployer, receiver.address, BigNumber.from(1))

    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: token,
            event: 'Transfer',
            args: [null, deployer.address],
          },
          {
            fromBlock: 0,
            toBlock: 'latest',
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)
    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(1, 'Number of logs')

    const log = result.current!.value![0]

    expect(getAddress(log.data['from'])).to.equal(getAddress(AddressZero), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(deployer.address), 'To')
    expect(log.data['value']).to.equal(MOCK_TOKEN_INITIAL_BALANCE, 'Amount')
  })

  it('We get an error when we query by un-indexed values', async () => {
    // Send to emit another Transfer token that our filter should filter out
    await sendToken(deployer, receiver.address, BigNumber.from(1))

    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: token,
            event: 'Transfer',
            args: [null, null, MOCK_TOKEN_INITIAL_BALANCE],
          },
          {
            fromBlock: 0,
            toBlock: 'latest',
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)

    expect(result.error).to.be.undefined
    expect(result.current?.value).to.be.undefined
    expect(result.current?.error).to.not.be.undefined
  })

  it('Can query by block hash', async () => {
    // Send to emit another Transfer token that our filter should filter out
    const { receipt } = await sendToken(deployer, receiver.address, BigNumber.from(1))

    const { result, waitForCurrent } = await renderWeb3Hook(
      () =>
        useLogs(
          {
            contract: token,
            event: 'Transfer',
            args: [],
          },
          {
            blockHash: receipt?.blockHash,
          }
        ),
      { mockProvider }
    )

    await waitForCurrent((val) => val !== undefined)

    expect(result.error).to.be.undefined

    expect(result.current?.value).to.not.be.undefined
    expect(result.current?.error).to.be.undefined
    expect(result.current?.value?.length).to.equal(1, 'Number of logs')

    const log = result.current!.value![0]

    expect(getAddress(log.data['from'])).to.equal(getAddress(deployer.address), 'From')
    expect(getAddress(log.data['to'])).to.equal(getAddress(receiver.address), 'To')
    expect(log.data['value']).to.equal(BigNumber.from(1), 'Amount')
    expect(log.blockHash).to.equal(receipt?.blockHash, 'Block hash')
    expect(log.blockNumber).to.equal(receipt?.blockNumber, 'Block number')
    expect(log.transactionHash).to.equal(receipt?.transactionHash, 'Transaction hash')
    expect(log.transactionIndex).to.equal(receipt?.transactionIndex, 'Transaction index')
  })
})