[
  {
    "path": ".babelrc",
    "content": "{\n  \"env\": {\n    \"esmBundled\": {\n      \"presets\": [\n        [\"@babel/env\", {\n        \"targets\": \"> 0.25%, not dead\"\n      }], \"@babel/typescript\"]\n    },\n    \"cjs\": {\n      \"presets\": [\n        [\"@babel/env\", {\n        \"modules\":\"commonjs\"\n      }], \"@babel/typescript\"]\n    },\n   \"prod\": {\n     \"presets\": [\n       [\n         \"@babel/env\",\n         {\n           \"targets\": { \"node\": \"18\" },\n           \"useBuiltIns\": \"usage\",\n           \"corejs\": 3\n         }\n       ],\n       \"@babel/typescript\"\n     ]\n   }\n  },\n  \"plugins\": [\n    \"@babel/plugin-transform-optional-chaining\",\n    \"@babel/plugin-transform-typescript\",\n    \"transform-class-properties\"\n  ]\n}\n"
  },
  {
    "path": ".eslintignore",
    "content": "# Ignore artifacts:\nbuild\ncoverage\n_book\ndist\nnode_modules\ndist"
  },
  {
    "path": ".eslintrc",
    "content": "{\n  \"root\": true,\n  \"parser\": \"@typescript-eslint/parser\",\n  \"plugins\": [\n    \"@typescript-eslint\"\n  ],\n  \"extends\": [\n    \"eslint:recommended\",\n    \"plugin:@typescript-eslint/eslint-recommended\",\n    \"plugin:@typescript-eslint/recommended\"\n  ],\n  \"rules\": {\n    \"no-console\": 2 ,\n    // Remember, this means error!\n    \"camelcase\": [\"warn\"]\n  }\n}"
  },
  {
    "path": ".gitignore",
    "content": "yarn-error.log\n*.tgz\n*testfile*\n.idea\n_book\ndist\nnode_modules\ncoverage\n./docs\n.DS_Store\n"
  },
  {
    "path": ".gitpod.yml",
    "content": "# This configuration file was automatically generated by Gitpod.\n# Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)\n# and commit this file to your remote git repository to share the goodness with others.\n\ntasks:\n  - init: yarn install && yarn run build\n    command: yarn run start\n\n\n"
  },
  {
    "path": ".prettierignore",
    "content": "# Ignore artifacts:\nbuild\ncoverage\n_book\ndist\nnode_modules"
  },
  {
    "path": ".prettierrc.json",
    "content": "{}\n"
  },
  {
    "path": "Changelog.md",
    "content": "# CHANGELOG\n\n## JS SDK Version ChangeLog\n#### 3.6.14\n    1) Guardian approve\n#### v3.5.0\n    1）ecdsaSignature update to `eth_signTypedData_v4`  use method `sendAsync`\n#### v3.4.15\n    1）Internal browser contract signarue support\n    2）referral signature at active account\n    3）referral reword\n    4）Explorer Collection related Entry and feature optimization\n    5）insufficient quota reminder for Dual Invest\n    6）Add tutorial on Block trade\n#### v3.3.16\n    1）Change Ecrecove function\n    2）Stop limit\n    3) Red Packet \n    4) Block trade\n\n#### v3.3.0\n    1) GLOBAL information update\n\n#### v3.2.6\n    1) BlindBox Redpacket\n\n#### v3.2.1\n    1) LRC staking\n    2) signature bug fix  \n\n#### v3.1.5\n    1) hardware wallet last digital match / hard-code \n         generateKeyPair(_, publicKey: { x: string; y: string } | undefined = undefined)\n\n#### v3.1.0\n    1) dual API update (support for Partial order)\n    2) red Packet feature \n    3) amm redeem mini order\n    \n#### v3.0.1 - v3.0.8\n    1) reformate Error throw code states \n    2) new feature for collection group\n    3) method split for localStorage \n\n#### v2.0.24\n\n    1）collection feature\n    2）investment feature\n\n#### v2.0.17\n\n    1) submitForceWithdrawals\n    2) return a result hash\n    3) order/swap demo\n\n#### v2.0.12\n\n    1) ipfs cid to nftId startWith 0\n    2) server-side retturn nftId startWith 0\n\n#### v2.0.11\n    1) add deposit to\n    2) get Account by account id\n    3) add HEBAO_META_TYPE deposit_wallet\n\n#### v2.0.7\n    1) Fix isMobile\n\n####  v2.0.6\n    1) mintNFT nftData\n####  v2.0.5 (If you use v2 please move to >= v2.0.4 )\n    1) payPayeeUpdateAccount\n    2) fix generateApiKey error \n\n####  v2.0.0\n    1) update poseidon\n\n***\n####  v1.10.3\n    1) Demo update\n\n####  v1.10.1\n    1) getAllowances formatter update\n    2) getTokenBalances formatter update\n    3) unit test update\n\n####  v1.9.6\n    1) add is Mobile in personalSign\n####  v1.9.4\n    1) remove Authereum & walletLink\n    2) DEPLOYMENT_STATUS\n####  v1.8.13\n    1）Update web3_defs.ts  CREATION_CODE\n    2）submitDeployNFT transfer.maxFee tokenId: transfer.token.tokenId,\n####  v1.8.7\n    1）getAmmPoolTxs V3\n####  v1.8.5\n    1）validateNftOrder\n\n####  v1.8.1\n    1）validateNftOrder\n    2）NFTCounterFactualInfo\n#### v1.7.9\n    1) nftMint NFTCounterFactualInfo\n####v1.7.6\n    1) Doc update,UT update\n####v1.7.2\n    1) NFT ACTION        \n    2) AMM Bug\n\n####v1.6.6\n    1) NFT MINT IPFS\n\n####v1.6.5\n    1) The eddsaKey is generated by a keyseed, default format is 'Sign this message to access Loopring\n\n####v1.6.3\n    1) Error format bug fix {code:number,message:string}\n\n####v1.6.0\n    1) Error format `{code:number, msg|message: string}`\n\n####v1.5.7\n    1) 721 NFT URI function\n\n#### v1.5.6\n    1) submitDeployNFT\n\n#### v1.5.2\n    1) NFT deposit\n\n#### v1.4.9\n    1) Counter Factual check \n    2) updateAccount\n\n#### v1.4.7\n    1) NFT META \n    2) HEBAO\n#### v1.4.5 \n    1) CF wallet action sign update\n\n#### v1.4.4 (alpha)\n    1) fix unlock FC wallet\n    \n#### v1.4.3 (alpha)\n    1) bug fix for NFT get contractMeta \n    2) FC wallet connect signature\n    3) Error code \n\n#### v1.4.2\n    1) update activity\n\n#### v1.3.10\n    1) Add recognizing header for web\n\n#### v1.3.9\n    1) Update getLatestTokenPrice url\n\n#### v1.3.8\n    1) SDK update for error type\n\n#### v1.3.4 - v1.3.7 destroy\n\n#### v1.3.3\n    1) add computeNFTAddress\n    2) add eslint and prettie for the code format\n\n#### v1.3.2\n    1) Fix some bug\n    2) Update withdraw NFT unit test\n\n#### v1.3.0 && v1.3.1 -- !!! revert\n    formatter Uint8Array support\n    # !!! revert\n\n"
  },
  {
    "path": "LICENSE",
    "content": "Licensor:             Loopring Technology Limited\n\nLicensed Work:        Loopring-web/loopring-sdk\n                      The Licensed Work is (c) 2022 Loopring Technology Limited\n\n-----------------------------------------------------------------------------\n\nTerms\n\nThe Licensor hereby grants you the right to copy, modify, create derivative\nworks, redistribute, and make limited-production use of the Licensed Work, on condition that Loopring L2 protocol/technology is supported on your platform that this Licensed Work is being used. \n\nIf your use of the Licensed Work does not comply with the requirements\ncurrently in effect as described in this License, you must acquire a\nfull licensing agreement from the Licensor, or its affiliated entities, \nor you must refrain from using the Licensed Work.\n\nAll copies of the original and modified Licensed Work, and derivative works\nof the Licensed Work, are subject to this License. This License applies\nseparately for each version of the Licensed Work.\n\nYou must conspicuously display this License on each original or modified copy\nof the Licensed Work. If you receive the Licensed Work in original or\nmodified form from a third party, the terms and conditions set forth in this\nLicense apply to your use of that work.\n\nAny use of the Licensed Work in violation of this License will automatically\nterminate your rights under this License for the current and all other\nversions of the Licensed Work.\n\nThis License does not grant you any right in any trademark or logo of\nLicensor or its affiliates (provided that you may use a trademark or logo of\nLicensor as expressly required by this License).\n\nTO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON\nAN \"AS IS\" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,\nEXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND\nTITLE.\n\n-----------------------------------------------------------------------------\n\n"
  },
  {
    "path": "README.md",
    "content": "# Loopring SDK\n\n[![license](https://img.shields.io/badge/license-Loopring-blue)](https://raw.githubusercontent.com/Loopring/loopring_sdk/master/LICENSE)\n[![type-badge](https://img.shields.io/npm/types/react-data-grid)](https://www.npmjs.com/package/react-data-grid)\n[![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.com/invite/KkYccYp)\n\n## 🚀 Quick Start\n```shell\n# Using npm\nnpm i @loopring-web/loopring-sdk --save\n# Using yarn\nyarn add @loopring-web/loopring-sdk\n```\nwhen using for browser make sure set up `NODE_ENV=production|development`\n\n> Make sure you are using the original npm registry.  \n> `npm config set registry http://registry.npmjs.org`\n\n\n## 📒 Documentation\n\nPlease see the [documentation page](https://loopring.github.io/loopring_sdk/) for information about getting started and developing with the Loopring SDK.\n\n- [JS SDK](https://loopring.github.io/loopring_sdk)\n- [APIs](https://docs-protocol.loopring.io)\n\n## ✨ Changelog\n\n- [Changelog](https://loopring.github.io/loopring_sdk/ChangeLog.html)\n\n## 🫂 Community\n\n- [Loopring Website](https://loopring.org/)\n- [Loopring Exchange](https://loopring.io/#/layer2)\n- [Loopring Reddit](https://www.reddit.com/r/loopringorg/)\n- [Loopring Medium](https://medium.com/loopring-protocol)\n- [Loopring Twitter](https://twitter.com/loopringorg)\n- [Loopring Telegram](https://t.me/loopring_en)\n\n## 🎒 Getting Started\n\nPlease see our [introduction page](https://loopring.github.io/loopring_sdk/) for details on integrating the SDK into your application.\n\n## 🙋 Protocol & Architecture\n\n- [Whitepaper](https://loopring.org/resources/en_whitepaper.pdf)\n- [Design Docs](https://github.com/LoopringSecondary/docs/wiki/Loopring3_Design)\n\n## ❓[Help](https://desk.zoho.com/portal/loopring/en/home)\n\n## 👉 [What is Loopring?](https://loopring.org/#/)\n\n## 🔑 Security\n\n- [Wallet](https://security.loopring.io/)\n- [Protocol Audit](https://loopring.org/resources/loopring1.0_audit.pdf)\n"
  },
  {
    "path": "book.json",
    "content": "{\n  \"root\": \"./docs\",\n  \"description\": \"loopring sdk\",\n  \"author\": \"Loopring Dev Team\",\n  \"title\": \"Loopring SDK\",\n  \"gitbook\": \">=3.0.0\",\n  \"links\": {\n    \"sidebar\": {\n      \"Home\": \"https://loopring.io\"\n    }\n  }\n}\n"
  },
  {
    "path": "docs/.bookignore",
    "content": "docs/detail\ndocs/README.md\ndocs/Changelog.mdv\n"
  },
  {
    "path": "docs/Changelog.md",
    "content": "# CHANGELOG\n\n## JS SDK Version ChangeLog\n#### v3.6.0\n    1) dual Invest autoReinvest\n    2) guardina singature typeData\n    3) remove signature 02/03 ended\n\n#### v3.2.1\n    1) LRC staking\n    2) signature bug fix  \n\n#### v3.1.5\n    1) hardware wallet last digital match / hard-code \n         generateKeyPair(_, publicKey: { x: string; y: string } | undefined = undefined)\n\n#### v3.1.0\n    1) dual API update (support for Partial order)\n    2) red Packet feature \n    3) amm redeem mini order\n    \n#### v3.0.1 - v3.0.8\n    1) reformate Error throw code states \n    2) new feature for collection group\n    3) method split for localStorage \n\n#### v2.0.24\n\n    1）collection feature\n    2）investment feature\n\n#### v2.0.17\n\n    1) submitForceWithdrawals\n    2) return a result hash\n    3) order/swap demo\n\n#### v2.0.12\n\n    1) ipfs cid to nftId startWith 0\n    2) server-side retturn nftId startWith 0\n\n#### v2.0.11\n    1) add deposit to\n    2) get Account by account id\n    3) add HEBAO_META_TYPE deposit_wallet\n\n#### v2.0.7\n    1) Fix isMobile\n\n####  v2.0.6\n    1) mintNFT nftData\n####  v2.0.5 (If you use v2 please move to >= v2.0.4 )\n    1) payPayeeUpdateAccount\n    2) fix generateApiKey error \n\n####  v2.0.0\n    1) update poseidon\n\n***\n####  v1.10.3\n    1) Demo update\n\n####  v1.10.1\n    1) getAllowances formatter update\n    2) getTokenBalances formatter update\n    3) unit test update\n\n####  v1.9.6\n    1) add is Mobile in personalSign\n####  v1.9.4\n    1) remove Authereum & walletLink\n    2) DEPLOYMENT_STATUS\n####  v1.8.13\n    1）Update web3_defs.ts  CREATION_CODE\n    2）submitDeployNFT transfer.maxFee tokenId: transfer.token.tokenId,\n####  v1.8.7\n    1）getAmmPoolTxs V3\n####  v1.8.5\n    1）validateNftOrder\n\n####  v1.8.1\n    1）validateNftOrder\n    2）NFTCounterFactualInfo\n#### v1.7.9\n    1) nftMint NFTCounterFactualInfo\n####v1.7.6\n    1) Doc update,UT update\n####v1.7.2\n    1) NFT ACTION        \n    2) AMM Bug\n\n####v1.6.6\n    1) NFT MINT IPFS\n\n####v1.6.5\n    1) The eddsaKey is generated by a keyseed, default format is 'Sign this message to access Loopring\n\n####v1.6.3\n    1) Error format bug fix {code:number,message:string}\n\n####v1.6.0\n    1) Error format `{code:number, msg|message: string}`\n\n####v1.5.7\n    1) 721 NFT URI function\n\n#### v1.5.6\n    1) submitDeployNFT\n\n#### v1.5.2\n    1) NFT deposit\n\n#### v1.4.9\n    1) Counter Factual check \n    2) updateAccount\n\n#### v1.4.7\n    1) NFT META \n    2) HEBAO\n#### v1.4.5 \n    1) CF wallet action sign update\n\n#### v1.4.4 (alpha)\n    1) fix unlock FC wallet\n    \n#### v1.4.3 (alpha)\n    1) bug fix for NFT get contractMeta \n    2) FC wallet connect signature\n    3) Error code \n\n#### v1.4.2\n    1) update activity\n\n#### v1.3.10\n    1) Add recognizing header for web\n\n#### v1.3.9\n    1) Update getLatestTokenPrice url\n\n#### v1.3.8\n    1) SDK update for error type\n\n#### v1.3.4 - v1.3.7 destroy\n\n#### v1.3.3\n    1) add computeNFTAddress\n    2) add eslint and prettie for the code format\n\n#### v1.3.2\n    1) Fix some bug\n    2) Update withdraw NFT unit test\n\n#### v1.3.0 && v1.3.1 -- !!! revert\n    formatter Uint8Array support\n    # !!! revert\n\n"
  },
  {
    "path": "docs/README.md",
    "content": "# Loopring SDK\n\n[![license](https://img.shields.io/badge/license-Loopring-blue)](https://raw.githubusercontent.com/Loopring/loopring_sdk/master/LICENSE)\n[![type-badge](https://img.shields.io/npm/types/react-data-grid)](https://www.npmjs.com/package/react-data-grid)\n[![Discord](https://img.shields.io/discord/687207715902193673)](https://discord.com/invite/KkYccYp)\n\n## 🚀 Quick Start\n```shell\n# Using npm\nnpm i @loopring-web/loopring-sdk --save\n# Using yarn\nyarn add @loopring-web/loopring-sdk\n```\n> Make sure you are using the original npm registry.  \n> `npm config set registry http://registry.npmjs.org`\n\n\n## 📒 Documentation\n\nPlease see the [documentation page](https://loopring.github.io/loopring_sdk/) for information about getting started and developing with the Loopring SDK.\n\n- [JS SDK](https://loopring.github.io/loopring_sdk)\n- [Python](https://github.com/Loopring/hello_loopring)\n- [APIs](https://docs.loopring.io/en/)\n\n## ✨ Changelog\n\n- [Changelog](https://loopring.github.io/loopring_sdk/ChangeLog.html)\n\n## 🫂 Community\n\n- [Loopring Website](https://loopring.org/)\n- [Loopring Exchange](https://loopring.io/#/layer2)\n- [Loopring Reddit](https://www.reddit.com/r/loopringorg/)\n- [Loopring Medium](https://medium.com/loopring-protocol)\n- [Loopring Twitter](https://twitter.com/loopringorg)\n- [Loopring Telegram](https://t.me/loopring_en)\n\n## 🎒 Getting Started\n\nPlease see our [introduction page](https://loopring.github.io/loopring_sdk/) for details on integrating the SDK into your application.\n\n## 🙋 Protocol & Architecture\n\n- [Whitepaper](https://loopring.org/resources/en_whitepaper.pdf)\n- [Design Docs](https://github.com/LoopringSecondary/docs/wiki/Loopring3_Design)\n\n## ❓[Help](https://desk.zoho.com/portal/loopring/en/home)\n\n## 👉 [What is Loopring?](https://loopring.org/#/)\n\n## 🔑 Security\n\n- [Wallet](https://security.loopring.io/)\n- [Protocol Audit](https://loopring.org/resources/loopring1.0_audit.pdf)\n"
  },
  {
    "path": "docs/SUMMARY.md",
    "content": "# Summary\n\n### Overview\n\n- [Introduction](README.md)\n- [Changelog](Changelog.md)\n- [GitHub](https://github.com/Loopring/loopring_sdk)\n\n### SDKs demo\n\n- [JS SDK](./js_sdk/README.md)\n  - [Exchange](./js_sdk/exchange/exchange.md)\n    - [Web Socket](./js_sdk/exchange/webSocket.md)\n    - [Amm](./js_sdk/exchange/ammpool_api.md)\n  - [Account](./js_sdk/README.md#mock-account)\n     - [Active Account](./js_sdk/account/activeAccount.md)\n     - [Fees](./js_sdk/account/fee.md)\n     - [Signature](./js_sdk/account/signature.md)\n     - [Transaction Recorder](./js_sdk/account/historyRecord.md)\n  - [ERC20](./js_sdk/README.md#mock-erc20-token-map)\n    - [Deposit](./js_sdk/deposit/depositERC20.md)\n    - [Transfer](./js_sdk/transfer/transferERC20.md)\n    - [Withdraw](./js_sdk/withdraw/withdrawERC20.md)\n    - [Order](./js_sdk/erc20Trade/orderERC20.md)\n  - [NFT](./js_sdk/README.md#mock-account)\n    - [Deposit](./js_sdk/deposit/depositNFT.md)\n    - [Transfer](./js_sdk/transfer/transferNFT.md)\n    - [Withdraw](./js_sdk/withdraw/withdrawNFT.md)\n    - [Mint](./js_sdk/NFTAction/mintNFT.md)\n    - [MetaData](./js_sdk/NFTAction/metaNFT.md)\n    - [Collection](./js_sdk/NFTAction/collectionNFT.md)\n    - [Deploy](./js_sdk/NFTAction/deployNFT.md)\n    - [Trade](./js_sdk/NFTAction/tradeNFT.md)\n      - [Validate Order](./js_sdk/NFTAction/validateNFTOrder.md)\n\n### Links\n\n- [Python](https://github.com/Loopring/hello_loopring)\n- [APIs](https://docs.loopring.io/en/)\n- [About us](https://loopring.org/#/)\n- [Submit a Request](https://desk.zoho.com/portal/loopring/en/newticket)\n"
  },
  {
    "path": "docs/about_us.md",
    "content": "##### written by loopring dev team.\n"
  },
  {
    "path": "docs/js_sdk/Deposit.md",
    "content": "# Deposit from Ethereum L1 to Loopring, First Step for Start L2\n\n- [Step1: getUser Layer1 ETH balance](#step1️⃣-getuser-layer1-eth-balance)\n    - [ETH](#1-let-start-from-eth)\n    - [ERC20](#2-erc20-token-such-as-lrc)\n    - [NFT](#3-nft)\n- [Step2: Allow and Approve Loopring to get transaction those Token access](#step2️⃣-allow-and-approve-loopring-to-get-transaction-those-token-access)\n    - [ETH](#1-eth-skip-this-step)\n    - [ERC20](#2-erc20-token-such-as-lrc-1)\n    - [NFT](#3-nft-1)\n- [Step3: Deposit](#step3️⃣-deposit)\n    - [ETH](#1-eth-same-as-erc20-only-can-not-deposit-all-for-gas-cost)\n    - [ERC20](#2-erc20-token-such-as-lrc-2)\n    - [NFT](#3-nft-2)\n- [Additional & Reference](#additional--reference)\n    - [Approve Simple Signature Demo](#approve-simple-signature-demo)\n    - [Deposit Signature  Demo](#deposit-signature-demo-fee-is-pay-by-eth-only-current-fee-is-0)\n\n>**All Deposit Method, User should have enough `ETH` pay for the >Ethereum Gas (Loopring have no charge, no fee for Deposit).**\n\nBefore start read this Doc, make sure you understand how to create an We3 with an Ethereum provider\n\n\nLet's start step by step how to Deposit from Ethereum L1 to Loopring ( Demo as [Loopring JS SDK](https://loopring.github.io/loopring_sdk) ):\n\n     Connect Wallet processing...\n\nWhen you connect with Wallet (EOA or Loopring Wallet), you will know your `accAddress = ${Account_Address}` and have a  `web3` instance\nUser has Three chooses Deposit `ETH`; `ERC20 Token (Such as LRC )`; `NFT (ERC721 & ERC1155)`;\n\n\n***\n### Step1️⃣: getUser Layer1 ETH balance\n\n#### 1. Let start from ETH\n```ts\nconst { ethBalance } = await LoopringAPI.exchangeAPI.getEthBalances({owner: accAddress});\n```\nSDK: [getEthBalances](https://github.com/Loopring/loopring_sdk/blob/master/src/api/exchange_api.ts#L514)\nAPI: [/api/v3/eth/balances](https://uat2.loopring.io/api/v3/eth/balances?owner=0xfF7d59D9316EBA168837E3eF924BCDFd64b237D8)\n\nChoose deposit amount from UI\n>tips: user should keep some ETH pay for Ethereum Gas\n\n\n#### 2. ERC20 Token (Such as LRC)\n\n```ts\nconst { ethBalance } = await LoopringAPI.exchangeAPI.getEthBalances({owner: accAddress});\n//tokenArr is Loopring supprot ERC20 TokenId Array.jion(',')\nconst { tokenBalances } = await LoopringAPI.exchangeAPI.getTokenBalances({owner: accAddress, token: tokenArr.join()})\n```\nAPI: [/api/v3/eth/tokenBalances](https://uat2.loopring.io/api/v3/eth/tokenBalances?owner=0xfF7d59D9316EBA168837E3eF924BCDFd64b237D8&token=0xfc28028d9b1f6966fe74710653232972f50673be%2C0x0000000000000000000000000000000000000000%2C0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a%2C0xcd2c81b322a5b530b5fa3432e57da6803b0317f7%2C0x47525e6a5def04c9a56706e93f54cc70c2e8f165)\n> {tokenArr} = getMixMarkets()    \n> SDK:[getMixMarkets](https://github.com/Loopring/loopring_sdk/blob/master/src/api/exchange_api.ts#L409)\n> API:[/api/v3/mix/markets](https://api.loopring.network/api/v3/mix/markets) Market pair reduce to Unique Token Name ['ETH','LRC','USDT',...]\n\n#### 3. NFT\n- Prepare Token Address `nftTokenAddress`\n- NFT ID `nftId`\n- Know NFT Type `ERC721` or `ERC1155`\n\n```ts\nconst response = await nft.getNFTBalance({\n  web3,\n  account: accAddress,\n  tokenAddress: nftTokenAddress,\n  nftId: nftId,\n  nftType: NFTType.ERC1155,\n});\n```  \nSDK: [getNFTBalance](https://github.com/Loopring/loopring_sdk/blob/master/src/api/nft_api.ts#L100)\n\n***\n\n### Step2️⃣: Allow and Approve Loopring to get transaction those Token access\n\n#### 1. ETH Skip this step\n#### 2. ERC20 Token (Such as LRC )\n    - check Allowances\n    - getNonce web3.eth.getTransactionCount\n    - contract.approveMax\n\n```ts\nimport {getTradeArg} from \"./ws_defs\";\n\nconst {tokenAllowances} = await exchangeAPI.getAllowances({\n  owner: accAddress,\n  token: \"LRC\",\n})\nif (tokenAllowances[\"LRC\"] === undefined || tokenAllowances[\"LRC\"] < getTradeArgValue){\n  const nonce = await web3.eth.getTransactionCount(accAddress);\n  const response = await contract.approveMax(\n    web3,\n    accAddress,\n    tokenAddress, // LRC address  {tokenIdMap} = getTokens();  tokenIdMap['LRC']\n    depositAddress, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.depositAddress\n    gasPrice,\n    gasLimit,\n    ChainId.GOERLI,\n    nonce,\n    true\n  );\n}\n\n\n```\nSDK:[getAllowances](https://github.com/Loopring/loopring_sdk/blob/master/src/api/exchange_api.ts#L583)\nAPI:[/api/v3/eth/allowances](https://uat2.loopring.io/api/v3/eth/allowances?owner=0xfF7d59D9316EBA168837E3eF924BCDFd64b237D8&token=0xfc28028d9b1f6966fe74710653232972f50673be)    \nSDK:[getExchangeInfo](https://github.com/Loopring/loopring_sdk/blob/master/src/api/exchange_api.ts#L624)\nAPI:[/api/v3/exchange/info](https://uat2.loopring.io/api/v3/exchange/info)   \nSDK:[getTokens](https://github.com/Loopring/loopring_sdk/blob/master/src/api/exchange_api.ts#L416)\nAPI:[/apiv3/exchange/tokens](https://uat2.loopring.io/api/v3/exchange/tokens)   \nSDK:[approveMax](https://github.com/Loopring/loopring_sdk/blob/master/src/api/contract_api.ts#L271)\n\n[Approve Signature Demo](#approve-simple-signature-demo)\n\n#### 3. NFT\n- check nft isApprovedForAll\n- getNonce web3.eth.getTransactionCount\n- contract.approveNFT (ALL) by nftTokenAddress\n ```ts\nconst isApproved = await nft.isApprovedForAll({\n  web3,\n  from: accAddress,\n  exchangeAddress: exchangeAddr, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.exchangeAddr\n  nftType: NFTType.ERC1155,\n  tokenAddress: nftTokenAddress,\n});\nif(!isApproved){\n  const nonce = await web3.eth.getTransactionCount(accAddress);\n  const response = await nft.approveNFT({\n    web3,\n    from: accAddress,\n    depositAddress,\n    tokenAddress: nftTokenAddress,\n    tokenId: nftId,\n    nftType: NFTType.ERC1155,\n    gasPrice,\n    gasLimit,\n    chainId: ChainId.GOERLI,\n    nonce,\n    approved: true,\n    sendByMetaMask: true,\n  });\n}\n\n ```\nSDK:[isApprovedForAll](https://github.com/Loopring/loopring_sdk/blob/master/src/api/nft_api.ts#L312)    \nSDK:[approveNFT](https://github.com/Loopring/loopring_sdk/blob/master/src/api/nft_api.ts#L235)\n\n[Approve Signature Demo](#approve-simple-signature-demo)\n\n***\n### Step3️⃣: Deposit\n#### 1. ETH  (Same as ERC20, only can not deposit all for Gas cost)\n#### 2. ERC20 Token (Such as LRC )\n```ts\nconst nonce = await web3.eth.getTransactionCount(accAddress);\nconst response = await contract.deposit(\n  web3,\n  accAddress,\n  exchangeAddr, // {exchangeInfo} = getExchangeInfo()  exchangeInfo.exchangeAddr\n  tokenInfo,\n  10, // tradeValue\n  0, // fee 0\n  gasPrice,\n  gasLimit,\n  ChainId.GOERLI,\n  nonce,\n  true\n);\n```\nSDK:[deposit](https://github.com/Loopring/loopring_sdk/blob/master/src/api/contract.ts#L300)\n\n[Deposit Signature Demo](#deposit-signature-demo-fee-is-pay-by-eth-only-current-fee-is-0)\n\n#### 3. NFT\n```ts\nconst nonce = await web3.eth.getTransactionCount(accAddress);\nconst response = await nft.depositNFT({\n  web3,\n  from:accAddress,\n  exchangeAddress::exchangeAddr, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.exchangeAddr\n  nftType: NFTType.ERC1155,\n  tokenAddress: nftTokenAddress,\n  amount: 1,\n  gasPrice,\n  gasLimit,\n  chainId: ChainId.GOERLI,\n  nonce,\n  sendByMetaMask:true}\n);\n```\nSDK:[depositNFT](https://github.com/Loopring/loopring_sdk/blob/master/src/api/nft_api.ts#L354)\n\n[Deposit Signature Demo](#deposit-signature-demo-fee-is-pay-by-eth-only-current-fee-is-0)\n\n\n***\n### Additional & Reference\n\n#### Approve Simple Signature Demo\nFor more detail about genERC{XXX}Data please read [Contract ABI Specification](//https://docs.soliditylang.org/en/develop/abi-spec.html#)\n```ts \n/* ERC20 Approve Data structure */\nconst data = genERC20Data(ERC20Method.Approve, {\n  _spender: depositAddress,\n  _value:\"0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\",\n});\n/* NFT setApprovalForAll Data structure */\n// if (nftType === NFTType.ERC1155) {\n//    data = this._genERC1155Data(NFTMethod.setApprovalForAll, {\n//       operator: depositAddress,\n//       approved,\n//    });\n// } else if (nftType === NFTType.ERC721) {\n//    //TODO list not support now\n//    data = this._genERC721Data(NFTMethod.setApprovalForAll, {\n//       operator: depositAddress,\n//       approved,\n//    });\n// }\nconst gasPrice = fm.fromGWEI(gasPrice).toNumber();\nweb3.eth.sendTransaction({\n  from:accAddress,\n  to: depositAddress, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.depositAddress    \n  value:\"0\",\n  data,\n  chainId,\n  nonce,\n  gasPrice,\n  gasLimit,\n}).then((_error,transactionHash: string) =>{\n  if (!err) {\n    resolve({ result: transactionHash });\n  } else {\n    resolve({ error: { message: err.message } });\n  }\n});\n```\n\n### Deposit Signature Demo (fee is pay by ETH only current fee is 0)\n- tokenSymbol is ETH, sendTransaction value should be `amount + fee`\n- Other tokenSymbol as LRC sendTransaction value is `fee`\n- `fee` is pay by ETH only  (current fee is  0)\n```ts\n  const tokenAddress = \"0x?????????\";\n  const tokenSymbol = \"LRC\";\n  const fee = 0;\n  /* tokenSymbol is ETH, sendTransaction value should be `amount + fee` (current fee is 0)\n   * other tokenSymbol as LRC addresss valueC is fee (current fee is 0)\n   */\n  const value = tokenSymbol === \"ETH\"? amount + fee : fee;\n  const data = genExchangeData(ERC20Method.Deposit, {\n    tokenAddress,\n    amount,\n    from,\n    to: from,\n    extraData: \"\",\n  });\n  /* NFT deposit Data structure */\n  // const data = genExchangeData(NFTMethod.depositNFT, {\n  //   from,\n  //   to: from,\n  //   nftType,\n  //   tokenAddress,\n  //   nftId,\n  //   amount,\n  //   extraData: extraData ? extraData : \"\",\n  // });\n  web3.eth.sendTransaction({\n    from:accAddress,\n    to:exchangeAddress, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.depositAddress\n    value,\n    data,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n  }).then((_error,transactionHash: string) =>{\n    if (!err) {\n      resolve({ result: transactionHash });\n    } else {\n      resolve({ error: { message: err.message } });\n     }\n  });\n\nreturn await sendRawTx(\n  web3,\n  from,\n  exchangeAddress,\n  valueC.toFixed(),\n  data,\n  chainId,\n  nonce,\n  gasPrice,\n  gasLimit,\n  sendByMetaMask\n);\n\n```\n\n\nlast but not least, waiting and check your layer 2 account Balance... start Layer2\n\n#### Reference\n\n- @Loopring-web/web3-provider Package & [DEMO](https://github.com/Loopring/web3-provider)\n- Loopring allow you directory dev with our [APIs](https://docs.loopring.io/en/)\n- For your Web-app & Dapp welcome use our [JS SDK](https://loopring.github.io/loopring_sdk)\n"
  },
  {
    "path": "docs/js_sdk/NFTAction/collectionNFT.md",
    "content": "# Collection NFT\n\nDefinition: allow user create a NFT Collection with different Contract(token) address.\n\n- allow user mint the NFTs with collection\n- when collection deployed, NFTs will have different Contract(token) address in layer1\n- Loopring own collection on L2, allow user to view/edit their Collection information.\n- will soon enable the \"Import Collection\" to manage legacy NFTs\n\n***\n\n## Step 1. get Account\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n\towner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n``` \n\n***\n\n## Step 2. get eddsaKey\n\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n\t{\n\t\taccountId: accInfo.accountId,\n\t},\n\teddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n```\n\n***\n\n## Step 4. get storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n\t{\n\t\taccountId: accInfo.accountId,\n\t\tsellTokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId, // same as maxFee tokenId\n\t},\n\tapiKey\n);\n```\n\n***\n\n## Step 5. get collection Information(tokenAddress)\n\n```ts\nconst collectionRes = await LoopringAPI.userAPI\n\t.getUserOwenCollection({\n\t\t\towner: accInfo.owner,\n\t\t\ttokenAddress: mockData.nftTokenAddress,\n\t\t\tisMintable: true\n\t\t},\n\t\tapiKey\n\t)\nif ((collectionRes &&\n\t((collectionRes as sdk.RESULT_INFO).code ||\n\t\t(collectionRes as sdk.RESULT_INFO).message)) || !collectionRes.collections.length\n) {\n\tconsole.log(\"Collection is disable to mint \");\n\tthrow \"Collection is disable to mint \";\n}\n\nconst collectionMeta = (collectionRes as any).collections[ 0 ] as CollectionMeta;\n\nconst counterFactualNftInfo: NFTCounterFactualInfo = {\n\tnftOwner: accInfo.owner,\n\tnftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[ sdk.ChainId.GOERLI ],\n\tnftBaseUri: collectionMeta.baseUri,\n};\n\n```\n\n***\n\n## Step 6. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n\t{\n\t\taccountId: accInfo.accountId,\n\t\ttokenAddress: collectionMeta.contractAddress,\n\t\trequestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n\t},\n\tapiKey\n);\n```\n\n***\n\n## Step7. Mint\n\n```ts\nconst response = await LoopringAPI.userAPI.submitNFTMint({\n\trequest: {\n\t\texchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n\t\tminterId: accInfo.accountId,\n\t\tminterAddress: accInfo.owner,\n\t\ttoAccountId: accInfo.accountId,\n\t\ttoAddress: accInfo.owner,\n\t\tnftType: 0,\n\t\ttokenAddress: collectionMeta.contractAddress,\n\t\tnftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n\t\tamount: \"1\",\n\t\tvalidUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n\t\tstorageId: storageId.offchainId ?? 9,\n\t\tmaxFee: {\n\t\t\ttokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId,\n\t\t\tamount: fee.fees[ \"LRC\" ].fee ?? \"9400000000000000000\",\n\t\t},\n\t\tcounterFactualNftInfo,\n\t\troyaltyPercentage: 5,\n\t\tforceToMint: true, // suggest use as false, for here is just for run test\n\t},\n\tweb3,\n\tchainId: sdk.ChainId.GOERLI,\n\twalletType: sdk.ConnectorNames.Unknown,\n\teddsaKey: eddsaKey.sk,\n\tapiKey: apiKey,\n});\n```\n\n____\n\n### ps: Mint with legacy nftFactory\n\n<font color='red'>! Mint NFT from this way has no collection information at deploy contract(tokenAdress is\nunique)</font>\n***\n\n#### Step 1,2,3,4 is same logic\n\n#### Step 5. get tokenAddress\n\n```ts\nconst counterFactualNftInfo = {\n\tnftOwner: accInfo.owner,\n\tnftFactory: sdk.NFTFactory[ sdk.ChainId.GOERLI ],\n\tnftBaseUri: \"\",\n};\nconst nftTokenAddress =\n\tLoopringAPI.nftAPI.computeNFTAddress(counterFactualNftInfo)\n\t\t.tokenAddress || \"\";\nconsole.log(\"nftTokenAddress\", nftTokenAddress);\n```\n\n***\n\n#### Step 6. get fee\n\n```ts\n const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n\t{\n\t\taccountId: accInfo.accountId,\n\t\ttokenAddress: nftTokenAddress,\n\t\trequestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n\t},\n\tapiKey\n);\n```\n\n#### Step 7. Mint\n\n```ts\n\nconst response = await LoopringAPI.userAPI.submitNFTMint({\n\trequest: {\n\t\texchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n\t\tminterId: accInfo.accountId,\n\t\tminterAddress: accInfo.owner,\n\t\ttoAccountId: accInfo.accountId,\n\t\ttoAddress: accInfo.owner,\n\t\tnftType: 0,\n\t\ttokenAddress: nftTokenAddress,\n\t\tnftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n\t\tamount: \"1\",\n\t\tvalidUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n\t\tstorageId: storageId.offchainId ?? 9,\n\t\tmaxFee: {\n\t\t\ttokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId,\n\t\t\tamount: fee.fees[ \"LRC\" ].fee ?? \"9400000000000000000\",\n\t\t},\n\t\troyaltyPercentage: 5,\n\t\tcounterFactualNftInfo,\n\t\tforceToMint: true, // suggest use as false, for here is just for run test\n\t},\n\tweb3,\n\tchainId: sdk.ChainId.GOERLI,\n\twalletType: sdk.ConnectorNames.Unknown,\n\teddsaKey: eddsaKey.sk,\n\tapiKey: apiKey,\n});\n```\n"
  },
  {
    "path": "docs/js_sdk/NFTAction/deployNFT.md",
    "content": "# Deploy NFT\n\nDefinition: Only nft minter can deploy NFT\n\n***\n\n## Step 1. get Account\n\n```ts \nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n```\n\n***\n\n## Step 2. get eddsaKey\n\n```ts\n   const eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n```\n\n***\n\n\n## Step 4. get fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_DEPLOY,\n    amount: \"0\",\n  },\n  apiKey\n);\nconsole.log(fee);\n```      \n***\n## Step 5. get storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId, // same as Step 7. transfer->token->tokenId\n  },\n  apiKey\n);\n```\n\n***\n\n## Step 6. broker\n\n```ts\nconst {broker} = await LoopringAPI.exchangeAPI.getAvailableBroker();\n```\n\n***\n## Step 7. Build transfer & Deploy\n\n```ts\n      const transfer = {\n  exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  payerAddr: LOOPRING_EXPORTED_ACCOUNT.address,\n  payerId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  payeeAddr: broker,\n  // payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n  storageId: storageId.offchainId,\n  token: {\n    tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n    volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n  },\n  validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n};\nconst response = await LoopringAPI.userAPI.submitDeployNFT({\n  request: {\n    transfer,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n\nconsole.log(response);\n```\n      \n\n"
  },
  {
    "path": "docs/js_sdk/NFTAction/metaNFT.md",
    "content": "# NFT META METHODS\n\n***\n\n## getContractNFTMeta\n\n```ts\nconst result = await LoopringAPI.nftAPI.getContractNFTMeta({\n  web3,\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n  nftType: sdk.NFTType.ERC1155,\n});\nconsole.log(result);\n```    \n\n***\n\n## getInfoForNFTTokens\n\n```ts\nconst response = await LoopringAPI.nftAPI.getInfoForNFTTokens({\n  nftDatas: [LOOPRING_EXPORTED_ACCOUNT.nftData],\n});\nconsole.log(`getInfoForNFTTokens: response: `, JSON.stringify(response));\n```\n\n***\n\n## computeNFTAddress\n\n```ts\nconst response = LoopringAPI.nftAPI.computeNFTAddress({\n  nftOwner: \"0xE20cF871f1646d8651ee9dC95AAB1d93160b3467\",\n  nftFactory: \"0x40F2C1770E11c5bbA3A26aEeF89616D209705C5D\",\n});\nconsole.log(\n  `computeNFTAddress:`,\n  response,\n  \"0xee354d81778a4c5a08fd9dbeb5cfd01a840a746d\"\n);\n```\n\n***\n\n## ipfsCid0ToNftID\n\n```ts\nconst ipfs = \"QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ\";\nconst nftID =\n  \"0x0880847b7587968f32ba6c741f9d797d9dc64971979922a80c4e590453b8dc2f\";\nconsole.log(\n  `ipfsCid0ToNftID: ipfs: `,\n  ipfs,\n  LoopringAPI.nftAPI.ipfsCid0ToNftID(ipfs)\n);\n```\n\n*** \n\n## ipfsNftIDToCid\n\n```ts\nconst ipfs = \"QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ\";\nconst nftID =\n  \"0x0880847b7587968f32ba6c741f9d797d9dc64971979922a80c4e590453b8dc2f\";\n\nconsole.log(\n  `ipfsCid0ToNftID: nftID: `,\n  nftID,\n  LoopringAPI.nftAPI.ipfsNftIDToCid(nftID)\n);\n```\n "
  },
  {
    "path": "docs/js_sdk/NFTAction/mintNFT.md",
    "content": "# Mint NFT\n\nDefinition: Mint Layer2 NFT, Loopring follow the ipfs NFT format, IPFS CID will convert to nftId, please view MetaNFT.md\n\n>    <p style={color:\"red\"}>!!! important  describe<p>\n>    <p>Follow mehod is the simple way for mint NTF, but this kind of NFT will using the same contact & with   no Contract metadata forever on L1</p> \n>    <p>New Version of NFT will has it isolate Contract/colletion with metadata inforamtion</p> \n>    <P>From Step 3. nftTokenAddress please follow create `collectionNFT` step create collection(contract), the api will return follow info for mint NFT</p>\n>\n```ts\ntokenAddress: collectionMeta.contractAddress\ncounterFactualNftInfo: {\n\tnftOwner: ccInfo.owner,\n\tnftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[chainId],\n\tnftBaseUri: collectionMeta?.baseUri ?? \"\",\n},\n```\n\n## Step 1. get Account\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n\towner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n``` \n\n***\n\n## Step 2. get eddsaKey\n\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey({\n   accountId: accInfo.accountId,\n },\n eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n```\n\n***\n\n## Step 4. get storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n{\n\taccountId: accInfo.accountId,\n\tsellTokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId, // same as maxFee tokenId\n},\napiKey\n);\n```\n\n***\n\n## Step 5. get collection Information(tokenAddress)\n\n```ts\nconst collectionRes = await LoopringAPI.userAPI\n\t.getUserOwenCollection({\n\t\t\towner: accInfo.owner,\n\t\t\ttokenAddress: mockData.nftTokenAddress,\n\t\t\tisMintable: true\n\t\t},\n\t\tapiKey\n\t)\nif ((collectionRes &&\n\t((collectionRes as sdk.RESULT_INFO).code ||\n\t\t(collectionRes as sdk.RESULT_INFO).message)) || !collectionRes.collections.length\n) {\n\tconsole.log(\"Collection is disable to mint \");\n\tthrow \"Collection is disable to mint \";\n}\n\nconst collectionMeta = (collectionRes as any).collections[ 0 ] as CollectionMeta;\n\nconst counterFactualNftInfo: NFTCounterFactualInfo = {\n\tnftOwner: accInfo.owner,\n\tnftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[ sdk.ChainId.GOERLI ],\n\tnftBaseUri: collectionMeta.baseUri,\n};\n\n```\n\n***\n\n## Step 6. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n\t{\n\t\taccountId: accInfo.accountId,\n\t\ttokenAddress: collectionMeta.contractAddress,\n\t\trequestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n\t},\n\tapiKey\n);\n```\n\n***\n\n## Step7. Mint\n\n```ts\nconst response = await LoopringAPI.userAPI.submitNFTMint({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    minterId: accInfo.accountId,\n    minterAddress: accInfo.owner,\n    toAccountId: accInfo.accountId,\n    toAddress: accInfo.owner,\n    nftType: 0,\n    tokenAddress: nftTokenAddress, // please read the description -> tokenAddress: collectionMeta.contractAddress,\n    nftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n    amount: \"1\",\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    storageId: storageId.offchainId ?? 9,\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId,\n      amount: fee.fees[ \"LRC\" ].fee ?? \"9400000000000000000\",\n    },\n    counterFactualNftInfo,\n    royaltyPercentage: 5,\n    forceToMint: true, // suggest use as false, for here is just for run test\n    // please read the description\n    // counterFactualNftInfo: {\n    //  nftOwner: ccInfo.owner,\n    //  nftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[chainId],\n    //  nftBaseUri: collectionMeta?.baseUri ?? \"\",\n    // },\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n```\n\n____\n\n### ps: Mint with legacy nftFactory\n\n<font color='red'>! Mint NFT from this way has no collection information at deploy contract(tokenAdress is\nunique)</font>\n***\n\n#### Step 1,2,3,4 is same logic\n\n#### Step 5. get tokenAddress\n\n```ts\nconst counterFactualNftInfo = {\n  nftOwner: accInfo.owner,\n  nftFactory: sdk.NFTFactory[ sdk.ChainId.GOERLI ],\n  nftBaseUri: \"\",\n};\nconst nftTokenAddress =\n  LoopringAPI.nftAPI.computeNFTAddress(counterFactualNftInfo)\n    .tokenAddress || \"\";\nconsole.log(\"nftTokenAddress\", nftTokenAddress);\n```\n\n***\n\n#### Step 6. get fee\n\n```ts\n const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    tokenAddress: nftTokenAddress,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n  },\n  apiKey\n);\n```\n\n#### Step 7. Mint\n\n```ts\n\nconst response = await LoopringAPI.userAPI.submitNFTMint({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    minterId: accInfo.accountId,\n    minterAddress: accInfo.owner,\n    toAccountId: accInfo.accountId,\n    toAddress: accInfo.owner,\n    nftType: 0,\n    tokenAddress: nftTokenAddress,\n    nftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n    amount: \"1\",\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    storageId: storageId.offchainId ?? 9,\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId,\n      amount: fee.fees[ \"LRC\" ].fee ?? \"9400000000000000000\",\n    },\n    royaltyPercentage: 5,\n    counterFactualNftInfo,\n    forceToMint: true, // suggest use as false, for here is just for run test\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n```\n"
  },
  {
    "path": "docs/js_sdk/NFTAction/tradeNFT.md",
    "content": "# Trade NFT\n\nDefinition: This method is help for understand how to match a maker with a taker order\n\n***\n\n## tradeNFT \n> Private or third account can signature and approve this order\n\n[mock order](#MockOrder)\n```ts\n// Step 1. getAccount\nconst accInfoC = (\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  })\n).accInfo;\n\n// Step 1. eddsaKeyC\nconst eddsaKeyC = await signatureKeyPairMock(accInfoC);\n\n// Step 3. apiKey\nconst apiKeyC = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfoC.accountId,\n    },\n    eddsaKeyC.sk\n  )\n).apiKey;\n//  NFT Trade\nconst response = await LoopringAPI.userAPI.submitNFTTrade({\n  request: {\n    maker: {\n      ...mockData.makerOrder,\n      eddsaSignature: mockData.makerOrderEddsaSignature,\n    },\n    makerFeeBips: 1000,\n    taker: {\n      ...mockData.takerOrder,\n      eddsaSignature: mockData.takerOrderEddsaSignature,\n    },\n    takerFeeBips: 100,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  apiKey: apiKeyC,\n  eddsaKey: eddsaKeyC.sk,\n});\n\nconsole.log(response);\n```\n\n***\n\n## MockOrder\n\n> Validate NFT Order please reader @Validate NFT Order\n\n```ts\n// Step 1. getAccount\nconst accInfo = (\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  })\n).accInfo;\nconst accInfo2 = (\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address2,\n  })\n).accInfo;\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconst eddsaKey2 = await signatureKeyPairMock(accInfo2, web3_2);\n// Step 3. apiKey\nconst apiKey = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo.accountId,\n    },\n    eddsaKey.sk\n  )\n).apiKey;\nconst apiKey2 = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo2.accountId,\n    },\n    eddsaKey2.sk\n  )\n).apiKey;\n\n// Step 4. storageId\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconst storageId2 = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo2.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  },\n  apiKey2\n);\n// Step 5. generate Order, please read validateNFTOrder\nconst makerOrder: sdk.NFTOrderRequestV3 = {\n  exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  accountId: accInfo.accountId,\n  storageId: storageId.orderId,\n  sellToken: {\n    tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n    nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n    amount: \"1\",\n  },\n  buyToken: {\n    tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n    amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  },\n  allOrNone: false,\n  fillAmountBOrS: false,\n  validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  maxFeeBips: 1000,\n};\nconst makerOrderEddsaSignature = sdk.get_EddsaSig_NFT_Order(\n  makerOrder,\n  eddsaKey.sk\n);\n\nconst takerOrder: sdk.NFTOrderRequestV3 = {\n  exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  accountId: accInfo2.accountId,\n  storageId: storageId2.orderId,\n  sellToken: {\n    tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n    amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  },\n  buyToken: {\n    tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n    nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n    amount: \"1\",\n  },\n  allOrNone: false,\n  fillAmountBOrS: true,\n  validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  maxFeeBips: 100,\n};\nconst takerOrderEddsaSignature = sdk.get_EddsaSig_NFT_Order(\n  takerOrder,\n  eddsaKey2.sk\n);\n\nmockData = {\n  takerOrder,\n  takerOrderEddsaSignature,\n  makerOrder,\n  makerOrderEddsaSignature,\n  makerFeeBips: 1000,\n  maxFeeBips: 100,\n};\n\n```\n"
  },
  {
    "path": "docs/js_sdk/NFTAction/validateNFTOrder.md",
    "content": "# Validate NFT Order\n\nDefinition: Loopring L2 support a method help for Validate NFT one side Order, validate NFT Order is not required for\nLoopring, but when make NFT Trade, it should pass this validation\n\n## SellNFTByERC20\n\n```ts\n// Step 1. getAccount\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. apiKey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n// Step 4. storageId\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n// let hash: any = new BN(nftId,'hex')\n// hash = toHex(hash);//new BigInteger(sha256(nftId.toString()).toString(), 16)\n\n// Step 5. submitNFTValidateOrder\nconst response = await LoopringAPI.userAPI.submitNFTValidateOrder({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: accInfo.accountId,\n    storageId: storageId.orderId,\n    sellToken: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    buyToken: {\n      tokenId: 1,\n      amount: \"10000000000000\",\n    },\n    allOrNone: false,\n    fillAmountBOrS: false,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    maxFeeBips: 1000,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n\nconsole.log(\"sellNFT NFTOrderRequestV3:\", response);\n```\n\n***\n\n## BuyNFTByERC20\n\n```ts\n // Step 1. getAccount\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. apiKey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n// Step 5. submitNFTValidateOrder\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n\nconst response = await LoopringAPI.userAPI.submitNFTValidateOrder({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: accInfo.accountId,\n    storageId: storageId.orderId,\n    sellToken: {\n      tokenId: 1,\n      amount: \"10000000000000\",\n    },\n    buyToken: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    fillAmountBOrS: true,\n    allOrNone: false,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    maxFeeBips: 100,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n```\n\n"
  },
  {
    "path": "docs/js_sdk/README.md",
    "content": "# Loopring SDK  \nLoopring SDK Initialize and Mock Data structure\n\n***\n## SDK Initialize \n```ts\nimport * as sdk from \"../index\";\nexport class LoopringAPIClass {\n  public static userAPI: UserAPI;\n  public static exchangeAPI: ExchangeAPI;\n  public static ammpoolAPI: AmmpoolAPI;\n  public static walletAPI: WalletAPI;\n  public static wsAPI: WsAPI;\n  public static nftAPI: NFTAPI;\n  public static delegate: DelegateAPI;\n  public static globalAPI: GlobalAPI;\n  public static contractAPI: typeof ContractAPI;\n  public static __chainId__: sdk.ChainId;\n  public static InitApi = (chainId: sdk.ChainId) => {\n    LoopringAPI.userAPI = new UserAPI({ chainId });\n    LoopringAPI.exchangeAPI = new ExchangeAPI({ chainId });\n    LoopringAPI.globalAPI = new GlobalAPI({ chainId });\n    LoopringAPI.ammpoolAPI = new AmmpoolAPI({ chainId });\n    LoopringAPI.walletAPI = new WalletAPI({ chainId });\n    LoopringAPI.wsAPI = new WsAPI({ chainId });\n    LoopringAPI.nftAPI = new NFTAPI({ chainId });\n    LoopringAPI.delegate = new DelegateAPI({ chainId });\n    LoopringAPI.__chainId__ = chainId;\n    LoopringAPI.contractAPI = ContractAPI;\n  };\n}\n/* env:\n * test:  sdk.ChainId.GOERLI \n * eth:  sdk.ChainId.MAINNET \n */\nLoopringAPIClass.InitApi({sdk.ChainId.MAINNET}); \n```\n***\n## Connect Wallet \nSuggestion web3 provider\n```shell\n# Using npm\nnpm i @loopring-web/web3-provider --save\n# Using yarn\nyarn add @loopring-web/web3-provider\n```\n- [Demo Vue](https://codesandbox.io/s/vue-8nco78)\n- [Demo React](https://codesandbox.io/s/react-4v50ft)\n \n[Mock Provider](#mock-provider)\n\n***\n## Loopring ERC20 Data Structure \n```ts\nconst {tokensMap, idIndex, addressIndex} = LoopringAPI.exchangeAPI.getTokens();\n```\n[Mock ERC20](#mock-erc20-token-map)\n\n***\n## Token Decimal\n```ts\nconst uiValue = 100;\nconst tradeValue = sdk.toBig(uiValue).times(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals);\n```\n\n***\n## Test Mock Data\n\n##### Mock Account\n```ts\nexport const LOOPRING_EXPORTED_ACCOUNT = {\n  address: \"0x727e0fa09389156fc803eaf9c7017338efd76e7f\",\n  privateKey:\n    \"491aecdb1d5f6400a6b62fd12a41a86715bbab675c37a4060ba115fecf94083c\",\n  accountId: 12454,\n  address2: \"0xb6d8c39D5528357dBCe6BEd82aC71c74e9D19079\",\n  privateKey2:\n    \"e020ed769032ba95d9a5207687a663d6198fe2f5cedf28a250f7cbd8c81a5263\",\n  accountId2: 10488,\n  addressCF: \"0x23dE4Da688c94a66E8bbE9BCc95CB03b4e209C15\",\n  accountIdCF: 11632,\n  addressContractWallet: \"0xD4BD7c71B6d4A09217ccc713f740d6ed8f4EA0cd\",\n  depositAddress: \"0xb684B265f650a77afd27Ce0D95252a7329B5bD72\",\n  exchangeAddress: \"0x2e76EBd1c7c0C8e7c2B875b6d505a260C525d25e\",\n  whitelistedAddress: \"0x35405E1349658BcA12810d0f879Bf6c5d89B512C\",\n  whitelistedEddkey:\n    \"0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\",\n  // const eddkeyWhitelisted =\n  //   \"0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\";\n  //   apiKey: \"2PYgTOZwXHkPXtJMlOMG06ZX1QKJInpoky6iYIbtMgmkbfdL4PvxyEOj0LPOfgYX\",\n  chainId: 5,\n  nftTokenAddress: \"0x8394cB7e768070217592572582228f62CdDE4FCE\",\n  nftTokenId: 32768,\n  nftId: \"0xa0ce8990402955e559799af24ea765b14ffecc32dfa1cce2dadaf20016b074e6\",\n  nftData: \"0x1a2001aac7a1fd00cef07889cdb67b1355f86e5bc9df71cfa44fa1c7b49f598f\",\n  testNotOx: \"727e0fa09389156fc803eaf9c7017338efd76e7f\",\n  tradeLRCValue: 1000000000000000000,\n  tradeETHValue: 0.0001, //same as UI\n  gasPrice: 20, // for test\n  gasLimit: 200000, // for test\n  validUntil: Math.round(Date.now() / 1000) + 30 * 86400,\n};\nexport const CUSTOMER_KEY_SEED = \"XXXXXX\" + \" with key nonce: \" + \"${nonce}\";\n```\n\n##### Mock provider\n```ts \nconst provider = new PrivateKeyProvider(\nLOOPRING_EXPORTED_ACCOUNT.privateKey,\n\"https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3\"\n);\nconst provider2 = new PrivateKeyProvider(\nLOOPRING_EXPORTED_ACCOUNT.privateKey2,\n\"https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3\"\n);\nexport const web3 = new Web3(provider);\nexport const web3_2 = new Web3(provider2);\n```\n\n##### Mock ERC20 Token Map\n```ts \nexport let TOKEN_INFO = {\n  addressIndex: {\n    \"0x0000000000000000000000000000000000000000\": \"ETH\",\n    \"0xfc28028d9b1f6966fe74710653232972f50673be\": \"LRC\",\n    \"0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a\": \"USDT\",\n    \"0xfeb069407df0e1e4b365c10992f1bc16c078e34b\": \"LP-LRC-ETH\",\n    \"0x049a02fa9bc6bd54a2937e67d174cc69a9194f8e\": \"LP-ETH-USDT\",\n    \"0xcd2c81b322a5b530b5fa3432e57da6803b0317f7\": \"DAI\",\n    \"0x47525e6a5def04c9a56706e93f54cc70c2e8f165\": \"USDC\",\n    \"0xf37cf4ced77b985708d591acc6bfd08586ab3409\": \"LP-USDC-ETH\",\n  },\n  tokenMap: {\n    ETH: {\n      type: \"ETH\",\n      tokenId: 0,\n      symbol: \"ETH\",\n      name: \"Ethereum\",\n      address: \"0x0000000000000000000000000000000000000000\",\n      decimals: 18,\n      precision: 7,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"5000000000000000\",\n        maximum: \"1000000000000000000000\",\n        dust: \"200000000000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"50000000000000\",\n        maximum: \"1000000000000000000000\",\n        dust: \"50000000000000\",\n      },\n      fastWithdrawLimit: \"100000000000000000000\",\n      gasAmounts: {\n        distribution: \"85000\",\n        deposit: \"100000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"LRC\", \"USDT\", \"USDC\"],\n    },\n    LRC: {\n      type: \"erc20Trade\",\n      tokenId: 1,\n      symbol: \"LRC\",\n      name: \"Loopring\",\n      address: \"0xfc28028d9b1f6966fe74710653232972f50673be\",\n      decimals: 18,\n      precision: 3,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"5000000000000000000\",\n        maximum: \"5000000000000000000000000\",\n        dust: \"5000000000000000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"50000000000000000\",\n        maximum: \"5000000000000000000000000\",\n        dust: \"50000000000000000\",\n      },\n      fastWithdrawLimit: \"750000000000000000000000\",\n      gasAmounts: {\n        distribution: \"101827\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"ETH\"],\n    },\n    USDT: {\n      type: \"erc20Trade\",\n      tokenId: 2,\n      symbol: \"USDT\",\n      name: \"USDT\",\n      address: \"0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a\",\n      decimals: 6,\n      precision: 2,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"5000000\",\n        maximum: \"2000000000000\",\n        dust: \"250000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"50000\",\n        maximum: \"200000000000\",\n        dust: \"50000\",\n      },\n      fastWithdrawLimit: \"250000000000\",\n      gasAmounts: {\n        distribution: \"106233\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"ETH\", \"DAI\"],\n    },\n    \"LP-LRC-ETH\": {\n      type: \"erc20Trade\",\n      tokenId: 4,\n      symbol: \"LP-LRC-ETH\",\n      name: \"AMM-LRC-ETH\",\n      address: \"0xfeb069407df0e1e4b365c10992f1bc16c078e34b\",\n      decimals: 8,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000000000\",\n        dust: \"100000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000000000\",\n        dust: \"100000000\",\n      },\n      fastWithdrawLimit: \"20000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n    \"LP-ETH-USDT\": {\n      type: \"erc20Trade\",\n      tokenId: 7,\n      symbol: \"LP-ETH-USDT\",\n      name: \"LP-ETH-USDT\",\n      address: \"0x049a02fa9bc6bd54a2937e67d174cc69a9194f8e\",\n      decimals: 8,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000\",\n        dust: \"100000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000\",\n        dust: \"100000000\",\n      },\n      fastWithdrawLimit: \"20000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n    DAI: {\n      type: \"erc20Trade\",\n      tokenId: 6,\n      symbol: \"DAI\",\n      name: \"dai\",\n      address: \"0xcd2c81b322a5b530b5fa3432e57da6803b0317f7\",\n      decimals: 18,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"10000000000000000000\",\n        maximum: \"100000000000000000000000\",\n        dust: \"10000000000000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"10000000000000000000\",\n        maximum: \"100000000000000000000000\",\n        dust: \"10000000000000000000\",\n      },\n      fastWithdrawLimit: \"10000000000000000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"USDT\"],\n    },\n    USDC: {\n      type: \"USDC\",\n      tokenId: 8,\n      symbol: \"USDC\",\n      name: \"USDC\",\n      address: \"0x47525e6a5def04c9a56706e93f54cc70c2e8f165\",\n      decimals: 6,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"1000\",\n        maximum: \"10000000000000000000\",\n        dust: \"100\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"1000000\",\n        maximum: \"10000000000\",\n        dust: \"1000000\",\n      },\n      fastWithdrawLimit: \"20000000000000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"ETH\"],\n    },\n    \"LP-USDC-ETH\": {\n      type: \"LP-USDC-ETH\",\n      tokenId: 9,\n      symbol: \"LP-USDC-ETH\",\n      name: \"LP-USDC-ETH\",\n      address: \"0xf37cf4ced77b985708d591acc6bfd08586ab3409\",\n      decimals: 8,\n      precision: 7,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"100000\",\n        maximum: \"1000000000000000000000000000000000000000\",\n        dust: \"10000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"1000000000000000\",\n        maximum: \"10000000000000000000\",\n        dust: \"1000000000000000\",\n      },\n      fastWithdrawLimit: \"20000000000000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n  },\n  idIndex: {\n    \"0\": \"ETH\",\n    \"1\": \"LRC\",\n    \"2\": \"USDT\",\n    \"4\": \"LP-LRC-ETH\",\n    \"6\": \"DAI\",\n    \"7\": \"LP-ETH-USDT\",\n    \"8\": \"USDC\",\n    \"9\": \"LP-USDC-ETH\",\n  },\n  marketMap: {\n    \"LRC-ETH\": {\n      baseTokenId: 1,\n      enabled: true,\n      market: \"LRC-ETH\",\n      orderbookAggLevels: 5,\n      precisionForPrice: 6,\n      quoteTokenId: 0,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1617967800000,\n    },\n    \"ETH-USDT\": {\n      baseTokenId: 0,\n      enabled: true,\n      market: \"ETH-USDT\",\n      orderbookAggLevels: 3,\n      precisionForPrice: 3,\n      quoteTokenId: 2,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1617972300000,\n    },\n    \"DAI-USDT\": {\n      baseTokenId: 6,\n      enabled: true,\n      market: \"DAI-USDT\",\n      orderbookAggLevels: 2,\n      precisionForPrice: 4,\n      quoteTokenId: 2,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 0,\n    },\n    \"USDC-ETH\": {\n      baseTokenId: 8,\n      enabled: true,\n      market: \"USDC-ETH\",\n      orderbookAggLevels: 3,\n      precisionForPrice: 3,\n      quoteTokenId: 0,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1636974420000,\n    },\n  },\n};\n```\n\n##### Mock AMM MAP\n```ts \nexport let AMM_MAP = {\n  \"AMM-LRC-ETH\": {\n    name: \"LRCETH-Pool\",\n    market: \"AMM-LRC-ETH\",\n    address: \"0xfEB069407df0e1e4B365C10992F1bc16c078E34b\",\n    version: \"1.0.0\",\n    tokens: { pooled: [1, 0], lp: 4 },\n    feeBips: 20,\n    precisions: { price: 6, amount: 5 },\n    createdAt: \"1617967800000\",\n    status: 31,\n  },\n  \"AMM-ETH-USDT\": {\n    name: \"AMM-ETH-USDT\",\n    market: \"AMM-ETH-USDT\",\n    address: \"0x049a02FA9bc6bd54a2937E67D174cc69a9194f8e\",\n    version: \"1.0.0\",\n    tokens: { pooled: [0, 2], lp: 7 },\n    feeBips: 20,\n    precisions: { price: 3, amount: 3 },\n    createdAt: \"1617972300000\",\n    status: 31,\n  },\n  \"AMM-USDC-ETH\": {\n    name: \"AMM-USDC-ETH\",\n    market: \"AMM-USDC-ETH\",\n    address: \"0xf37cf4CEd77b985708D591AcC6BfD08586Ab3409\",\n    version: \"1.0.0\",\n    tokens: {\n      pooled: [8, 0],\n      lp: 9,\n    },\n    feeBips: 20,\n    precisions: {\n      price: 3,\n      amount: 4,\n    },\n    createdAt: \"1636974420000\",\n    status: 0,\n  },\n};\n```\n\n##### Mock EIP712 Typed Data\n```ts\nexport const testTypedData: EIP712TypedData = {\n  types: {\n    EIP712Domain: [\n      { name: \"name\", type: \"string\" },\n      { name: \"version\", type: \"string\" },\n      { name: \"chainId\", type: \"uint256\" },\n      { name: \"verifyingContract\", type: \"address\" },\n    ],\n    TestTypedData: [\n      { name: \"from\", type: \"address\" },\n      { name: \"to\", type: \"address\" },\n      { name: \"tokenID\", type: \"uint16\" },\n    ],\n  },\n  primaryType: \"TestTypedData\",\n  domain: {\n    name: \"Loopring Protocol\",\n    version: \"3.6.0\",\n    chainId: sdk.ChainId.GOERLI,\n    verifyingContract: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  },\n  message: {\n    from: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address2,\n    tokenID: TOKEN_INFO.tokenMap.LRC.tokenId,\n  },\n};\n ```\n\n##### Mock generate eddsaKey \n```ts \nexport async function signatureKeyPairMock(\n  accInfo: sdk.AccountInfo,\n  _web3: Web3 = web3\n) {\n  const eddsaKey = await sdk.generateKeyPair({\n    web3: _web3,\n    address: accInfo.owner,\n    keySeed:\n      accInfo.keySeed ??\n      sdk.GlobalAPI.KEY_MESSAGE.replace(\n        \"${exchangeAddress}\",\n        LOOPRING_EXPORTED_ACCOUNT.exchangeAddress\n      ).replace(\"${nonce}\", (accInfo.nonce - 1).toString()),\n    walletType: sdk.ConnectorNames.MetaMask,\n    chainId: sdk.ChainId.GOERLI,\n  });\n  return eddsaKey;\n}\n```\n"
  },
  {
    "path": "docs/js_sdk/account/activeAccount.md",
    "content": "# Active Account\n\nDefinition: After user Deposit or (Third-Part Transfer), how to active Loopring L2 account.\n\n***\n\n## Step 1. get account info\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\n```\n\n***\n\n## Step 2. use keySeed or CUSTOMER_KEY_SEED generateKeyPair\n\n```ts\nconst keySeed = sdk.BaseAPI.KEY_MESSAGE.replace(\n      \"${exchangeAddress}\",\n      LOOPRING_EXPORTED_ACCOUNT.exchangeAddress\n    ).replace(\"${nonce}\", accInfo.nonce.toString());\nconst eddsaKey = await sdk.generateKeyPair({\n  web3,\n  address: accInfo.owner,\n  keySeed,\n  walletType: sdk.ConnectorNames.MetaMask,\n  chainId: sdk.ChainId.GOERLI,\n});\nconsole.log(\"eddsakey:\", eddsaKey.sk);\n```\n\nOr\n\n```ts\n// CUSTOMER_KEY_SEED = \"XXXXXX\" + \" with key nonce: \" + \"${nonce}\";\nconst keySeed = CUSTOMER_KEY_SEED.replace(\n  \"${nonce}\",\n  accInfo.nonce.toString()\nconst eddsaKey = await sdk.generateKeyPair({\n  web3,\n  address: accInfo.owner,\n  keySeed,\n  walletType: sdk.ConnectorNames.MetaMask,\n  chainId: sdk.ChainId.GOERLI,\n});\nconsole.log(\"eddsakey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get fee\n\n```ts\nconst fee = await LoopringAPI.globalAPI.getActiveFeeInfo({\n  accountId: accInfo.accountId,\n});\nconsole.log(\"fee:\", fee);\n```  \n\n***\n\n## Step 4. updateAccount (active or rest）\n\n```ts\n      const result = await LoopringAPI.userAPI.updateAccount({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    owner: accInfo.owner,\n    accountId: accInfo.accountId,\n    publicKey: {x: eddsaKey.formatedPx, y: eddsaKey.formatedPy},\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    keySeed,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    nonce: accInfo.nonce as number,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  isHWAddr: false,\n});\n\nconst {accInfo: updateAccountInfo} =\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  });\nconsole.log(\n  \"updateAccount Result: \",\n  result,\n  \"updateAccountInfo:\",\n  updateAccountInfo\n);\n```"
  },
  {
    "path": "docs/js_sdk/account/fee.md",
    "content": "# Fee\n\nLoopring have 2 get Fee api:\n\n- getOffchainFeeAmt:\n  - `ORDER`,\n  - `FFCHAIN_WITHDRAWAL`,\n  - `UPDATE_ACCOUNT`,\n  - `TRANSFER`,\n  - `FAST_OFFCHAIN_WITHDRAWAL`,\n  - `OPEN_ACCOUNT`,\n  - `AMM_EXIT`,\n  - `DEPOSIT`,\n  - `AMM_JOIN`,\n- getNFTOffchainFeeAmt:\n  - `NFT_MINT`,\n  - `NFT_WITHDRAWAL`,\n  - `NFT_TRANSFER`,\n  - `NFT_DEPLOY`,\n\n***\n\n## Fee: updateAccount\n\n```ts\n    // Step 1. get account info\nconsole.log(LoopringAPI.exchangeAPI.getAccount);\n\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\n\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.UPDATE_ACCOUNT,\n  },\n  apiKey\n);\nconsole.log(\"updateAccount:\", response);\n```\n\n***\n\n## Fee: transfer\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.TRANSFER,\n  },\n  apiKey\n);\nconsole.log(\"transfer:\", response);\n```\n\n***\n\n## Fee: withdraw\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n    requestType: sdk.OffchainFeeReqType.OFFCHAIN_WITHDRAWAL,\n  },\n  apiKey\n);\nconsole.log(\"withdraw:\", response);\n```\n\n***\n\n## Fee: fastWithdraw\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.FAST_OFFCHAIN_WITHDRAWAL,\n    tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n  },\n  apiKey\n);\nconsole.log(\"fastWithdraw:\", response);\n```\n\n***\n\n## Fee: order\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.ORDER,\n    tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n  },\n  apiKey\n);\nconsole.log(\"order:\", response);\n```\n\n***\n\n## Fee: amm_exit\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.AMM_EXIT,\n  },\n  apiKey\n);\nconsole.log(\"amm_exit:\", response);\n```\n\n***\n\n## Fee: amm_join\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.AMM_JOIN,\n  },\n  apiKey\n);\nconsole.log(\"amm_join:\", response);\n```\n\n***\n\n## Fee: NFT Transfer\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_TRANSFER,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  },\n  apiKey\n);\nconsole.log(\"NFTTransfer:\", response);\n```\n\n***\n\n## Fee: NFT Withdrawal\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_WITHDRAWAL,\n  },\n  apiKey\n);\nconsole.log(\"NFTWithdrawal:\", response);\n```\n\n## Fee: NFT Mint\n\n```ts\n// Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress\n  },\n  apiKey\n);\nconsole.log(\"NFTWithdrawal:\", response);\n\n```\n\n## Fee: NFT Deploy\n\n```ts \n// Step 1. get account info \nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount(\n  {owner: LOOPRING_EXPORTED_ACCOUNT.address,});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_DEPLOY,\n  },\n  apiKey\n);\nconsole.log(\"NFTWithdrawal:\", response);\n```\n\n***\n\n## getActiveFeeInfo without apikey & accountId\n\n```ts\nconst response = await LoopringAPI.globalAPI.getActiveFeeInfo({});\n```\n\n***\n\n## getActiveFeeInfo without apikey with accountId\n\n```ts\n const response = await\n  LoopringAPI.globalAPI.getActiveFeeInfo({accountId: LOOPRING_EXPORTED_ACCOUNT.accountId});\n```\n\n"
  },
  {
    "path": "docs/js_sdk/account/historyRecord.md",
    "content": "# User Actions History\nFor check account Actions, more detail such as filters please read SDK interface or API .\n\n***\n\n## getUserTrades\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getUserTrades(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      offset: 0,\n      limit: 20,\n      fillTypes: sdk.TradesFillTypes.dex,\n    },\n    apiKey\n  );\n  console.log(\"getUserTrades:\", result);\n  ```\n\n***\n\n## getUserTxs\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getUserTxs(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      types: [\n        sdk.UserTxTypes.DEPOSIT,\n        sdk.UserTxTypes.TRANSFER,\n        sdk.UserTxTypes.ONCHAIN_WITHDRAWAL,\n      ],\n    },\n    apiKey\n  );\n  console.log(\"getUserTxs:\", result);\n  ```\n\n***\n\n## getUserNFTTransactionHistory\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getUserNFTTransactionHistory(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      types: [\n        sdk.UserNFTTxTypes.DEPOSIT,\n        sdk.UserNFTTxTypes.TRANSFER,\n        sdk.UserNFTTxTypes.WITHDRAW,\n        sdk.UserNFTTxTypes.MINT,\n      ],\n    },\n    apiKey\n  );\n  console.log(\"getUserNFTTransactionHistory:\", result);\n  ```\n\n***\n\n## getOrders\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getOrders(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      orderTypes: sdk.OrderType.LimitOrder,\n    },\n    apiKey\n  );\n\n  console.log(\"getOrders:\", result);\n  ```\n"
  },
  {
    "path": "docs/js_sdk/account/signature.md",
    "content": "# Signature\n\nLoopring SDK support EOA (EOA hardware wallet) & Loopring Smart wallet Signature\n\n- For Browser extension, Dapp, Hardware wallet we only support for EOA\n- For Loopring Smart wallet (App), Provider gateway only can be walletConnect\n\n## Follow is the provider gateway we inject & test:\n\n- MetaMask  (Ledger, Trezor)\n- WalletConnect (Authereum, Loopring Smart wallet )\n- Coinbase\n- [Coming soon...](https://desk.zoho.com/portal/loopring/en/newticket)\n\n## For signature:\n\nFor eth_sign signing types (eth_sign, personal_sign, v1, v3, v4)\n\n### EOA:\n\n- For Browser\n  extension ([More information: signing-data](https://docs.metamask.io/guide/signing-data.html#a-brief-history))\n  + common EOA we use the `v4` signature and `web3.eth.personal.ecRecover` validate signature\n  + when `v4` signature is failed for any step, we will try `personal_sign` and `web3.eth.personal.ecRecover` validate\n    signature\n- For Dapp\n  + when loopring Dex is inside Dapp Webview & connect by `window.ethereum`, we remove the `web3.eth.personal.ecRecover`\n    validate\n\n### Loopring Smart wallet:\n\n- For Smart wallet we send `eth_signTypedData` by walletConnect & validate\n  ABI.Contracts.ContractWallet.encodeInputs `isValidSignature(bytes32,bytes)`\n\n### Loopring Counterfactual wallet:\n\n- signature is same as Smart wallet\n- But ecRecover is by\n  walletOwner, `const {walletOwner} = await LoopringAPI.exchangeAPI.getCounterFactualInfo({ accountId: LOOPRING_EXPORTED_ACCOUNT.accountIdCF, });`\n\n> ❗ when add `SigSuffix` `02|03` ( follow EIP712 + `02`, personal_sign + `03`)\n>- for `v4` ecdsaSignature the result signature should + `SigSuffix.Suffix02`;\n>- for `personal_sign` ecdsaSignature the result signature should + `SigSuffix.Suffix03`;\n\n***\n\n## generateKeyPair\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst result = await signatureKeyPairMock(accInfo);\nconsole.log(result.sk);\n```\n\n***\n\n## getEcDSASig: eth_signTypedData_v4\n\n```ts\n// test case is not allow brock by Mock provider\nconst result = await sdk.getEcDSASig(\n  web3,\n  testTypedData,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  sdk.GetEcDSASigType.HasDataStruct,\n  sdk.ChainId.GOERLI,\n  LOOPRING_EXPORTED_ACCOUNT.accountId,\n  \"\",\n  sdk.ConnectorNames.Unknown\n);\nconsole.log(\"getEcDSASig:eth_signTypedData_v4\",\n  result,\n  \"ecdsaSig+sdk.SigSuffix.Suffix02\",\n  result.ecdsaSig + sdk.SigSuffix.Suffix02\n);\n```\n\n***\n\n## getEcDSASig: personalSign(WithoutDataStruct--Hardware wallet)\n\n```ts\nconst result = await sdk.getEcDSASig(\n  web3,\n  testTypedData,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  sdk.GetEcDSASigType.WithoutDataStruct,\n  sdk.ChainId.GOERLI,\n  LOOPRING_EXPORTED_ACCOUNT.accountId,\n  \"\",\n  sdk.ConnectorNames.Unknown\n);\nconsole.log(\n  \"getEcDSASig:WithoutDataStruct(personalSign)\",\n  result,\n  \"ecdsaSig+sdk.SigSuffix.Suffix03\",\n  result.ecdsaSig + sdk.SigSuffix.Suffix03\n);\n```\n***\n## getEcDSASig: personalSign(Contract)\n\n```ts\n// test case is not allow brock by Mock provider\nconst result = await sdk.getEcDSASig(\n  web3,\n  testTypedData,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  sdk.GetEcDSASigType.Contract,\n  sdk.ChainId.GOERLI,\n  LOOPRING_EXPORTED_ACCOUNT.accountId,\n  \"\",\n  sdk.ConnectorNames.Unknown\n);\nconsole.log(\n  \"getEcDSASig:personalSign(Contract)\",\n  result\n);\n```\n\n## Validate signature\n\n[github: src/api/base_api.ts#personalSign](https://github.com/Loopring/loopring_sdk/blob/2c79c1837114f4f383e2d292de3da4b2dac02252/src/api/base_api.ts#L549)\n\n```\n export async function personalSign(\n  web3: any,\n  account: string | undefined,\n  pwd: string,\n  msg: string,\n  walletType: ConnectorNames,\n  chainId: ChainId,\n  accountId?: number,\n  counterFactualInfo?: CounterFactualInfo,\n  isMobile?: boolean\n) {\n  if (!account) {\n    return { error: \"personalSign got no account\" };\n  }\n\n  return new Promise((resolve) => {\n    try {\n      web3.eth.personal.sign(\n        msg,\n        account,\n        pwd,\n        async function (err: any, result: any) {\n          if (!err) {\n            // Valid:1. counter Factual signature Valid\n            if (counterFactualInfo && accountId) {\n              myLog(\"fcWalletValid counterFactualInfo accountId:\");\n              const fcValid = await fcWalletValid(\n                web3,\n                account,\n                msg,\n                result,\n                accountId,\n                chainId,\n                counterFactualInfo\n              );\n              if (fcValid.result) {\n                resolve({\n                  sig: result,\n                  counterFactualInfo: fcValid.counterFactualInfo,\n                });\n                return;\n              }\n            }\n\n            // Valid: 2. webview directory signature Valid\n            if (\n              (window?.ethereum?.isImToken || window?.ethereum?.isMetaMask) &&\n              isMobile &&\n              // Mobile directory connect will sign ConnectorNames as MetaMask only\n              walletType === ConnectorNames.MetaMask\n            ) {\n              const address: string[] = await window.ethereum?.request({\n                method: \"eth_requestAccounts\",\n              });\n              if (\n                address?.find(\n                  (item) => item.toLowerCase() === account.toLowerCase()\n                )\n              ) {\n                return resolve({ sig: result });\n              }\n            }\n\n            // Valid: 3. EOA signature Valid by ecRecover\n            const valid: any = await ecRecover(web3, account, msg, result);\n            if (valid.result) {\n              return resolve({ sig: result });\n            }\n\n            // Valid: 4. contractWallet signature Valid `isValidSignature(bytes32,bytes)`\n            const walletValid2: any = await contractWalletValidate32(\n              web3,\n              account,\n              msg,\n              result\n            );\n\n            if (walletValid2.result) {\n              return resolve({ sig: result });\n            }\n\n            // Valid: 5. counter Factual signature Valid when no counterFactualInfo\n            if (accountId) {\n              const fcValid = await fcWalletValid(\n                web3,\n                account,\n                msg,\n                result,\n                accountId,\n                chainId\n              );\n              if (fcValid.result) {\n                return resolve({\n                  sig: result,\n                  counterFactualInfo: fcValid.counterFactualInfo,\n                });\n              }\n            }\n\n            // Valid: 6. myKeyValid Valid again\n            const myKeyValid: any = await mykeyWalletValid(\n              web3,\n              account,\n              msg,\n              result\n            );\n\n            if (myKeyValid.result) {\n              return resolve({ sig: result });\n            }\n\n            // Valid: Error cannot pass personalSign Valid\n            // eslint-disable-next-line no-console\n            console.log(\n              \"web3.eth.personal.sign Valid, valid 5 ways, all failed!\"\n            );\n            return resolve({\n              error: \"web3.eth.personal.sign Valid, valid 5 ways, all failed!\",\n            });\n          } else {\n            return resolve({\n              error: \"personalSign err before Validate:\" + err,\n            });\n          }\n        }\n      );\n    } catch (reason) {\n      resolve({ error: reason });\n    }\n  });\n}\n```"
  },
  {
    "path": "docs/js_sdk/account/wallet_api.md",
    "content": "# Whitelisted User Part\n\n##### 1) getUserAssets\n\n```javascript\n// step 1. get account info\nconst request: GetUserAssetsRequest = {\n  wallet: \"0xeF041462825bFdF79b2f1f02A70b2753cB5b1516\",\n  offset: 10,\n  limit: 10,\n};\n\nconst response = await api.getUserAssets(request);\n```\n\n##### 2) getTokenPrices\n\n```javascript\n// step 1. get account info\nconst request: GetTokenPricesRequest = {\n  token: \"0xdac17f958d2ee523a2206206994597c13d831ec7\",\n};\n\nconst response = await api.getTokenPrices(request);\n```\n\n##### 3) getLatestTokenPrices\n\n```javascript\n// step 1. get account info\nconst response = await api.getLatestTokenPrices();\n```\n"
  },
  {
    "path": "docs/js_sdk/account/whitelisted_user_api.md",
    "content": "# Whitelisted User Part\n\n## submitInternalTransfer\n\n```javascript\n// step 1. get account info\n\nlet addressWhitlisted = \"0x35405E1349658BcA12810d0f879Bf6c5d89B512C\";\n\nlet eddkeyWhitelisted =\n  \"0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\";\n\nconst { accInfo } = await exchange.getAccount({ owner: addressWhitlisted });\n\nconsole.log(\"accInfo:\", accInfo);\n\nconst { exchangeInfo } = await exchange.getExchangeInfo();\n\n// step 2 get apikey\nconst request: GetUserApiKeyRequest = {\n  accountId: accInfo.accountId,\n};\n\nconst { apiKey } = await userApi.getUserApiKey(request, eddkeyWhitelisted);\n\nconsole.log(\"apiKey:\", apiKey);\n\n// step 3 get storageId\nconst request2: GetNextStorageIdRequest = {\n  accountId: accInfo.accountId,\n  sellTokenId: 1,\n};\nconst storageId = await userApi.getNextStorageId(request2, apiKey);\n\n// step 4 transfer\nconst request3: OriginTransferRequestV3 = {\n  exchange: exchangeInfo.exchangeAddress,\n  payerAddr: addressWhitlisted,\n  payerId: accInfo.accountId,\n  payeeAddr: \"0xb6AdaC3e924B4985Ad74646FEa3610f14cDFB79c\",\n  payeeId: 0,\n  storageId: storageId.offchainId,\n  token: {\n    tokenId: 1,\n    volume: \"100000000000000000000\",\n  },\n  maxFee: {\n    tokenId: 1,\n    volume: \"9400000000000000000\",\n  },\n  validUntil: VALID_UNTIL,\n};\n\nconsole.log(\"request3:\", request3);\n\nconst response = await whitelistedUserApi.submitInternalTransfer(\n  request3,\n  eddkeyWhitelisted,\n  apiKey\n);\n\nconsole.log(response);\n```\n\n## submitOffchainWithdraw is unavailable.\n\nTODO: submitOffchainWithdraw example\n"
  },
  {
    "path": "docs/js_sdk/deposit/depositERC20.md",
    "content": "# Deposit ERC20\n\nDefinition: Move user L1 ERC20 assets to Loopring L2\n> **All Deposit Method, User should have enough `ETH` pay for the Ethereum Gas (Loopring have no charge, no fee for Deposit).**\n\nProvider will give the Gas Price & Limit, sdk also have a method get gasPrice:\n`const gasPrice = (await LoopringAPI.exchangeAPI.getGasPrice() ).gasPrice;`\n\n# ETH\n\n***\n\n## Step 1. getNonce\n\n```ts\nconst nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\nconsole.log(\n  `deposit: ${TOKEN_INFO.tokenMap.ETH.symbol}-${LOOPRING_EXPORTED_ACCOUNT.tradeETHValue}, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n);\n```\n\n***\n\n## Step 2. deposit\n\n```ts\nconst response = await sdk.deposit(\n  web3,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  TOKEN_INFO.tokenMap.ETH,\n  LOOPRING_EXPORTED_ACCOUNT.tradeETHValue,\n  0,\n  LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n  sdk.ChainId.GOERLI,\n  nonce,\n  true\n);\n\nconsole.log(`nonce: ${nonce} deposit_ETH: `, response);\n```\n\n# ERC20\n\n***\n\n## Step 1. getAllowances\n\n```ts\nconst {tokenAllowances} = await LoopringAPI.exchangeAPI.getAllowances({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  token: [TOKEN_INFO.tokenMap.LRC.address],\n});\nif (\n  tokenAllowances.has(TOKEN_INFO.tokenMap.LRC.address) &&\n  Number(tokenAllowances.get(TOKEN_INFO.tokenMap.LRC.address)) <\n  LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue\n) {\n  const nonce = await web3.eth.getTransactionCount(\n    LOOPRING_EXPORTED_ACCOUNT.address\n  );\n  await sdk.approveMax(\n    web3,\n    LOOPRING_EXPORTED_ACCOUNT.address,\n    TOKEN_INFO.tokenMap.LRC.address, // LRC address  {tokenIdMap} = getTokens();  tokenIdMap['LRC']\n    LOOPRING_EXPORTED_ACCOUNT.depositAddress, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.depositAddress\n    LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n    LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n    sdk.ChainId.GOERLI,\n    nonce,\n    true\n  );\n}\n```\n\n***\n\n## Step 2. getNonce\n\n```ts\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\nconsole.log(\n  `deposit: ${TOKEN_INFO.tokenMap.LRC.symbol}-${LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue}, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n);\n```\n\n***\n\n## Step 3. deposit\n\n```ts\n      const response = await sdk.deposit(\n  web3,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  TOKEN_INFO.tokenMap.LRC,\n  sdk\n    .toBig(LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue)\n    .div(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)\n    .toNumber(),\n  0,\n  LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n  sdk.ChainId.GOERLI,\n  nonce,\n  true\n);\n\nconsole.log(`nonce: ${nonce}  deposit_LRC: `, response);\n```    \n\n"
  },
  {
    "path": "docs/js_sdk/deposit/depositNFT.md",
    "content": "# Deposit NFT\n\nDefinition: Move user L1 NFT assets to Loopring L2\n\n> **All Deposit Method, User should have enough `ETH` pay for the Ethereum Gas (Loopring have no charge, no fee for Deposit).**\n\n\n***\n\n## Step 1. getNFTBalance & getEthBalances\n\n```ts\nconst {ethBalance} = await LoopringAPI.exchangeAPI.getEthBalances({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst nftBalance = await LoopringAPI.nftAPI.getNFTBalance({\n  web3,\n  account: LOOPRING_EXPORTED_ACCOUNT.address,\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n  nftType: sdk.NFTType.ERC1155,\n});\n```\n\n***\n\n## Step 2. isApprovedForAll\n\n```ts\n const isApprovedForAll = await LoopringAPI.nftAPI.isApprovedForAll({\n  web3,\n  from: LOOPRING_EXPORTED_ACCOUNT.address,\n  exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  nftType: sdk.NFTType.ERC1155, // todo： sdk.NFTType.ERC721\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n});\nconsole.log(`check is approveNFT`, isApprovedForAll);\n\n```\n\n***\n\n## Step 3. approveNFT All\n\n```ts\n  if (!isApprovedForAll) {\n  const nonce = await sdk.getNonce(\n    web3,\n    LOOPRING_EXPORTED_ACCOUNT.address\n  );\n  const approveNFT = await LoopringAPI.nftAPI.approveNFT({\n    web3,\n    from: LOOPRING_EXPORTED_ACCOUNT.address,\n    depositAddress: LOOPRING_EXPORTED_ACCOUNT.depositAddress,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    nftType: sdk.NFTType.ERC1155, // todo： sdk.NFTType.ERC721\n    gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n    gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n    chainId: sdk.ChainId.GOERLI,\n    nonce,\n    sendByMetaMask: true,\n  });\n  console.log(`nonce: ${nonce} approveNFT: ${approveNFT?.result}`);\n}\n```\n\n***\n\n## Step 3. nonce\n\n```ts\n const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n\nconsole.log(\n  `deposit: NFT, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n);\n```\n\n***\n\n## Step 4. depositNFT\n\n```ts\n  const response = await LoopringAPI.nftAPI.depositNFT({\n  web3,\n  from: LOOPRING_EXPORTED_ACCOUNT.address,\n  exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  nftType: sdk.NFTType.ERC1155,   // todo： sdk.NFTType.ERC721\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n  amount: 2,   // todo：when sdk.NFTType.ERC721  amount: 1,\n  gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit + 100000,\n  chainId: sdk.ChainId.GOERLI,\n  nonce,\n  sendByMetaMask: true,\n});\nconsole.log(`nonce: ${nonce} deposit NFT ERC1155: `, response);\n\n```\n"
  },
  {
    "path": "docs/js_sdk/erc20Trade/orderERC20.md",
    "content": "# Order ERC20\n\n***\n> ### mini-order\nTo support small quantity trading, we introduce an additional concept \"tradeCost\", which is the minimum gas fee when a trade transaction is uplink to Ethereum.\n\nLet's take LRC-ETH trading as an example.\n\nBelow are the steps -\n\n**1) Query  api/v3/exchange/tokens to get the dust value of orderAmounts for both LRC and ETH.**\n\nThe dust value is the minimum value to pass Relayer check. Any amount less than \"dust\" can't be traded. In this case, we will get both minTOkenLRC and minTokenETH after getting dust value. If user wants to convert LRC to ETH, the set LRC amount can't be less than minTokenLRC and the converted ETH amount can't be less than minTokenETH.\n\n**2) Query api/v3/user/orderUserRateAmount to get the tradeCost value.**\n\nThe parameters to call this interface are \"accountId\" and \"market=LRC-ETH\". In this example, we will get two tradeCost values for LRC and ETH as tradeCostLRC and tradeCostETH.\n\n**3) Set maxAllowBips = 50% as the maxFeeBips can't exceed 50%**\n\n**4) Set slippage as the slippage value user configured in UI (for example 0.1%)**\n\n**5）Caculate minCostLRC and minCostETH as below**\n\n    minCostLRC = max(minTokenLRC, tradeCostLRC/maxAllowBips)\n    minCostETH = max(minTokenETH, tradeCostETH/maxAllowBips)\n\n**6) Caculate the cost by considering slippage**\n\n    minCostLRCSlip = minCostLRC/(1-slippage)\n    minCostETHSlip = minCostETH/(1-slippage)\n\n\n**7) Cacluate the minimum quantity user has to set**\n\n    tradeCostSellLRC = max(tradeCostSellLRC, minTokenLRC) * 1.1\n    tradeCostSellETH = max(tradeCostSellETH, minTokenETH) * 1.1\nHere we add additonally 10% tolerance.\n\n**8) Caculate the previous minimum token amount per calling api/v3/user/orderUserRateAmount (existing logic)**\n\nThis is the threshold to distinguish small quantity trading and normal trading  \nWe will get two values (configSellLRC and configSellETH) which are used for previous trading quantity limit (Per USD 100) caculation\n\n**9）Caculate the new maxFeeBips and start trading**\n\nLet's take LRC->ETH as the example\nUser inputs the amount of LRC to convert, amount = sellLRC\n\n    if sellLRC >= configSellLRC then \n    \t// Normal trading case, stay with previous logic\n    \tmaxFeeBips=63 (the default value for maxFeeBips)\n    \tTrade \n    else if sellLRC < tradeCostSellLRC then \n    \t// Really too small to support\n    \tPrompt user the amount is too small to support\n    \tExit\n    else \n    \t// This is what we call as small quantity \n    \tcostRate = Ceil(tradeCostETH/minbuyETH) \n    \tmaxFeeBips = max(costRate, takerRate)\n    \tTrade \n    End If \n\n\n> ### price impact update\n> 1. sellTokenMinAmount  =  baseOrderInfo.minAmount from  LoopringAPI.userAPI.getMinimumTokenAmt({accountId,marke}, apiKey);\n> 2. {output} from  sdk.getOutputAmount(input: sellTokenMinAmount, isAtoB: isAtoB,…}).output\n> 3. PriceBase = output / sellTokenMinAmount\n> 4. tradePrice = calcTradeParams.minReceive / userInputSell\n> 5. priceImpact = 1 - tradePrice/PriceBase - 0.005\n> 6. If priceImpact < 0 priceImpact = 0\n     >    Else priceImpact\n\n## calculateSwap function\n```ts\nconst calculateSwap = (\n  sellSymbol = \"LRC\",\n  buySymbol = \"ETH\",\n  isInputSellToBuy: boolean,\n  inputValue: number, // user Input value no decimal,\n  _slippage = 0.1,\n  // MOCK value\n  amountMap: { [key: string]: any } = userAmount,\n  market: string = deepMock.symbol,\n  // close = ticker.tickers[7],\n  depth: any = deepMock,\n  ammPoolSnapshot: sdk.AmmPoolSnapshot = ammPoolSnapshotMock,\n  tokenMap: sdk.LoopringMap<sdk.TokenInfo> = TokenMapMockSwap,\n  ammMap: { [key: string]: any } = AMM_MAP\n) => {\n  let calcFor100USDAmount, calcForMinCost, calcForPriceImpact;\n  if (depth && market && tokenMap) {\n    const sellToken = tokenMap[sellSymbol];\n    const buyToken = tokenMap[buySymbol];\n    const isInputSellOutputBuy = isInputSellToBuy;\n    let input: any = inputValue;\n\n    console.log(\n      \"sellToken: Symbol \",\n      sellSymbol,\n      \"buyToken: Symbol\",\n      buySymbol,\n      \"is Input Sell Output Buy:\",\n      isInputSellOutputBuy,\n      \"input value\",\n      input\n    );\n    input = input === undefined || isNaN(Number(input)) ? 0 : Number(input);\n    let slippage = sdk.toBig(_slippage).times(100).toString();\n    let totalFee = undefined;\n    let feeTakerRate = undefined;\n    let feeBips = undefined;\n    let takerRate = undefined;\n    let buyMinAmtInfo = undefined;\n    let sellMinAmtInfo = undefined;\n    let tradeCost = undefined;\n    let basePrice = undefined;\n    let maxFeeBips = MAPFEEBIPS;\n    let minAmt = undefined;\n\n    if (amountMap && amountMap[market] && ammMap) {\n      console.log(`amountMap[${market}]:`, amountMap[market]);\n\n      const ammMarket = `AMM-${market}`;\n\n      const amountMarket = amountMap[market]; // userAmount from  LRC-ETH(Market)\n\n      buyMinAmtInfo = amountMarket[buySymbol];\n      sellMinAmtInfo = amountMarket[sellSymbol];\n      console.log(\n        `buyMinAmtInfo: ${market}, ${buySymbol}`,\n        buyMinAmtInfo,\n        `sellMinAmtInfo: ${market}, ${sellSymbol}`,\n        sellMinAmtInfo\n      );\n\n      feeBips = ammMap[ammMarket] ? ammMap[ammMarket].feeBips : 1;\n\n      feeTakerRate =\n        amountMarket[buySymbol] &&\n        amountMarket[buySymbol].userOrderInfo.takerRate;\n      tradeCost = amountMarket[buySymbol].tradeCost;\n\n      /** @description for charge fee calc, calcFor100USDAmount\n       *  Loopring market consider buyToken value small then  max(buyMinAmtInfo.userOrderInfo.minAmount,buyToken.orderAmounts.dust) is a small order,\n       * the fee will take the Max(tradeCost,userTakeRate)\n       * use the buyMinAmount Input calc the selltoken value,\n       * please read Line:321\n       * **/\n      const minAmountInput = BigNumber.max(\n        buyMinAmtInfo.userOrderInfo.minAmount,\n        buyToken.orderAmounts.dust\n      )\n        .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n        .div(\"1e\" + buyToken.decimals)\n        .toString();\n      calcFor100USDAmount = sdk.getOutputAmount({\n        input: minAmountInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: false,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: slippage,\n      });\n\n      console.log(\n        \"buyMinAmtInfo.userOrderInfo.minAmount:\",\n        buyMinAmtInfo.userOrderInfo.minAmount,\n        `buyMinAmtInfo.userOrderInfo.minAmount, with slippage:${slippage}`,\n        sdk\n          .toBig(buyMinAmtInfo.userOrderInfo.minAmount)\n          .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n          .toString()\n      );\n\n      /*** calc for Price Impact ****/\n      const sellMinAmtInput = sdk\n        .toBig(sellMinAmtInfo.baseOrderInfo.minAmount)\n        .div(\"1e\" + sellToken.decimals)\n        .toString();\n\n      calcForPriceImpact = sdk.getOutputAmount({\n        input: sellMinAmtInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: true,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: \"10\",\n      });\n\n      basePrice = sdk.toBig(calcForPriceImpact?.output).div(sellMinAmtInput);\n\n      console.log(\n        \"calcForPriceImpact input: \",\n        sellMinAmtInput,\n        \", output: \",\n        sdk.toBig(calcForPriceImpact?.output).div(sellMinAmtInput).toNumber(),\n        \", calcForPriceImpact:\",\n        calcForPriceImpact?.amountBOutSlip?.minReceivedVal,\n        \", calcForPriceImpact basePrice: \",\n        basePrice.toNumber()\n      );\n\n      /**** calc for mini Cost ****/\n\n        //minCostBuyToken = max(dustBuyToken, tradeCostETH/maxAllowBips)\n      const dustToken = buyToken;\n      let minCostBuyTokenInput = BigNumber.max(\n        sdk.toBig(tradeCost).times(2), //maxAllowBips = 50% tradeCostETH/50%\n        dustToken.orderAmounts.dust\n      );\n\n      const tradeCostInput = sdk\n        .toBig(minCostBuyTokenInput)\n        .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n        .div(\"1e\" + dustToken.decimals)\n        .toString();\n\n      console.log(\n        `tradeCost: ${tradeCost}*2:`,\n        sdk.toBig(tradeCost).times(2).toString(),\n        \"buyToken.orderAmounts.dust\",\n        buyToken.orderAmounts.dust,\n        \"minCostBuyToken:\",\n        minCostBuyTokenInput.toString(),\n        `calcForMinCostInput, with slippage:${slippage}`,\n        sdk\n          .toBig(minCostBuyTokenInput ?? 0)\n          .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n          .toString(),\n        \"calcForMinCost, Input\",\n        tradeCostInput\n      );\n\n      calcForMinCost = sdk.getOutputAmount({\n        input: tradeCostInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: false,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: slippage,\n      });\n\n      //add additionally 10% tolerance for minimum quantity user has to set on sell Token\n      /**\n       * @output: minAmt for UI\n       * this value mini-order Sell token amount (show on the UI for available order check)\n       * setSellMinAmt(minAmt.toString());\n       */\n      minAmt = BigNumber.max(\n        sellToken.orderAmounts.dust,\n        calcForMinCost?.amountS ?? 0\n      ).times(1.1);\n\n      console.log(\n        \"UI show mini-order Sell token amount:\",\n        minAmt.toString(),\n        sdk\n          .toBig(minAmt)\n          .div(\"1e\" + sellToken.decimals)\n          .toString()\n      );\n\n      console.log(\n        `calcFor100USDAmount.amountS`,\n        sdk\n          .toBig(calcFor100USDAmount?.amountS ?? 0)\n          .div(\"1e\" + sellToken.decimals)\n          .toString(),\n        \"calcForMinCost.amountS\",\n        sdk\n          .toBig(calcForMinCost?.amountS ?? 0)\n          .div(\"1e\" + sellToken.decimals)\n          .toString()\n      );\n    }\n    const calcTradeParams = sdk.getOutputAmount({\n      input: input.toString(),\n      sell: sellSymbol,\n      buy: buySymbol,\n      isAtoB: isInputSellOutputBuy,\n      marketArr: marketArray as string[],\n      tokenMap: tokenMap as any,\n      marketMap: marketMap as any,\n      depth,\n      ammPoolSnapshot: ammPoolSnapshot,\n      feeBips: feeBips ? feeBips.toString() : 1,\n      takerRate: \"0\", // for new calc miniReceive will minus fee, so takeRate can fix as 0\n      slipBips: slippage,\n    });\n\n    const minSymbol = buySymbol;\n    const tradePrice = sdk\n      .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n      .div(isInputSellOutputBuy ? input.toString() : calcTradeParams?.output);\n    const priceImpact = sdk\n      .toBig(1)\n      .minus(sdk.toBig(tradePrice).div(basePrice ?? 1))\n      .minus(0.001);\n    if (calcTradeParams && priceImpact.gte(0)) {\n      calcTradeParams.priceImpact = priceImpact.toFixed(4, 1);\n    } else {\n      calcTradeParams && (calcTradeParams.priceImpact = \"0\");\n    }\n\n    console.log(\n      \"calcTradeParams input:\",\n      input.toString(),\n      \", calcTradeParams Price: \",\n      sdk\n        .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n        .div(input.toString())\n        .toNumber(),\n      `isAtoB mean isInputSellOutputBuy:${isInputSellOutputBuy}, ${\n        isInputSellOutputBuy ? input.toString() : calcTradeParams?.output\n      } tradePrice: `,\n      tradePrice.toString(),\n      \"basePrice: \",\n      basePrice?.toString(),\n      \"toBig(tradePrice).div(basePrice)\",\n      sdk\n        .toBig(tradePrice)\n        .div(basePrice ?? 1)\n        .toNumber(),\n      \"priceImpact (1-tradePrice/basePrice) - 0.001\",\n      priceImpact.toNumber(),\n      \"priceImpact view\",\n      calcTradeParams?.priceImpact\n    );\n\n    if (\n      tradeCost &&\n      calcTradeParams &&\n      calcTradeParams.amountBOutSlip?.minReceived &&\n      feeTakerRate\n    ) {\n      let value = sdk\n        .toBig(calcTradeParams.amountBOutSlip?.minReceived)\n        .times(feeTakerRate)\n        .div(10000);\n\n      console.log(\n        \"input Accounts\",\n        calcTradeParams?.amountS,\n        \"100 U Amount Sell:\",\n        calcFor100USDAmount?.amountS\n      );\n\n      let validAmt = !!(\n        calcTradeParams?.amountS &&\n        calcFor100USDAmount?.amountS &&\n        sdk.toBig(calcTradeParams?.amountS).gte(calcFor100USDAmount.amountS)\n      );\n      let totalFeeRaw;\n\n      console.log(\n        `${minSymbol} tradeCost:`,\n        tradeCost,\n        \"useTakeRate Fee:\",\n        value.toString(),\n        \"calcFor100USDAmount?.amountS:\",\n        calcFor100USDAmount?.amountS,\n        `is setup minTrade amount, ${calcFor100USDAmount?.amountS}:`,\n        validAmt\n      );\n\n      if (!validAmt) {\n        if (sdk.toBig(tradeCost).gte(value)) {\n          totalFeeRaw = sdk.toBig(tradeCost);\n        } else {\n          totalFeeRaw = value;\n        }\n        console.log(\n          \"maxFeeBips update for tradeCost before value:\",\n          maxFeeBips,\n          \"totalFeeRaw\",\n          totalFeeRaw.toString()\n        );\n        maxFeeBips = Math.ceil(\n          totalFeeRaw\n            .times(10000)\n            .div(calcTradeParams.amountBOutSlip?.minReceived)\n            .toNumber()\n        );\n        console.log(\"maxFeeBips update for tradeCost after value:\", maxFeeBips);\n      } else {\n        totalFeeRaw = sdk.toBig(value);\n      }\n\n      /**\n       * totalFee\n       */\n      totalFee = totalFeeRaw\n        .div(\"1e\" + tokenMap[minSymbol].decimals)\n        .toString();\n      /** @output: UI\n       *   getValuePrecisionThousand(\n       *   totalFeeRaw.div(\"1e\" + tokenMap[minSymbol].decimals).toString(),\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   false,\n       *   { floor: true }\n       * );\n       */\n\n      tradeCost = sdk\n        .toBig(tradeCost)\n        // @ts-ignore\n        .div(\"1e\" + tokenMap[minSymbol].decimals)\n        .toString();\n\n      /** @output:  UI code with precision\n       *   getValuePrecisionThousand(\n       *   sdk\n       *     .toBig(tradeCost)\n       *     .div(\"1e\" + tokenMap[minSymbol].decimals)\n       *     .toString(),\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   false,\n       *   { floor: true }\n       * );\n       */\n\n      console.log(\"totalFee view value:\", totalFee + \" \" + minSymbol);\n      console.log(\"tradeCost view value:\", tradeCost + \" \" + minSymbol);\n    }\n\n    const minimumReceived = sdk\n      .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n      .minus(totalFee ?? 0)\n      .toString();\n    console.log(\"minimumReceived:\", minimumReceived);\n\n    /** @output:   UI code with precision\n     *   getValuePrecisionThousand(\n     *   toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n     *     .minus(totalFee)\n     *     .toString(),\n     *   tokenMap[minSymbol].precision,\n     *   tokenMap[minSymbol].precision,\n     *   tokenMap[minSymbol].precision,\n     *   false,\n     *   { floor: true }\n     * );\n     */\n\n    let priceImpactView: any = calcTradeParams?.priceImpact\n      ? parseFloat(calcTradeParams?.priceImpact) * 100\n      : undefined;\n    console.log(\"priceImpact view:\", priceImpactView + \"%\");\n    //  @output:   UI code with color alert\n    // const priceImpactObj = getPriceImpactInfo(calcTradeParams);\n    // const _tradeCalcData: Partial<TradeCalcData<C>> = {\n    //   priceImpact: priceImpactObj.value.toString(),\n    //   priceImpactColor: priceImpactObj.priceImpactColor,\n    //   minimumReceived: !minimumReceived?.toString().startsWith(\"-\")\n    //     ? minimumReceived\n    //     : undefined,\n    //   fee: totalFee,\n    //   feeTakerRate,\n    //   tradeCost,\n    // };\n\n    console.log(\n      `isInputSellOutputBuy:${isInputSellOutputBuy}`,\n      `output ${isInputSellOutputBuy ? \"Buy\" : \"Sell\"}`,\n      calcTradeParams?.output\n    );\n\n    return {\n      market,\n      feeBips,\n      takerRate,\n      sellMinAmtInfo: sellMinAmtInfo as any,\n      buyMinAmtInfo: buyMinAmtInfo as any,\n      totalFee,\n      maxFeeBips,\n      feeTakerRate,\n      tradeCost,\n      minimumReceived,\n      calcTradeParams,\n      minAmt,\n    };\n  }\n};\n```\n\n### Step 1. get apikey & eddsaKey\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst eddsaKey = await signatureKeyPairMock(accInfo);\napiKey = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo.accountId,\n    },\n    eddsaKey.sk\n  )\n).apiKey;\n```\n\n### Step Step 2 : storageId\n\n```ts\n\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n  },\n  apiKey\n);\n```\n\n### Step 3. get user AmountMap, which decided user minimum order\n\n```ts\nconst amountMap = {\n  [AMM_MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: AMM_MAP[AMM_MARKET].market,\n      },\n      apiKey\n    )\n  ).amountMap,\n  [MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: MARKET,\n      },\n      apiKey\n    )\n  ).amountMap,\n};\n```\n\n### Step 4. depth, ammPoolSnapshot ,tickMap\n\n```ts\nconst [{depth}, {ammPoolSnapshot}] = await Promise.all([\n  LoopringAPI.exchangeAPI.getMixDepth({\n    market: AMM_MAP[\"AMM-LRC-ETH\"].market,\n  }),\n  LoopringAPI.ammpoolAPI.getAmmPoolSnapshot({\n    poolAddress: AMM_MAP[\"AMM-LRC-ETH\"].address,\n  }),\n]);\n```\n\n### Step 5. check MinAmt\n\n```ts\nlet buyMinAmtInfo = (amountMap[AMM_MARKET] ?? amountMap[MARKET])[buy];\nlet takerRate = buyMinAmtInfo\n  ? buyMinAmtInfo.userOrderInfo.takerRate\n  : 0;\nconst minAmountInput = buyMinAmtInfo.userOrderInfo.minAmount;\n```\n\n### Step 6. calcTradeParams\n\n```ts\nconst calcTradeParams = sdk.getOutputAmount({\n  input: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  sell,\n  buy,\n  isAtoB,\n  marketArr: [\"LRC-ETH\", \"ETH-USDT\", \"DAI-USDT\", \"USDC-ETH\"],\n  tokenMap: TOKEN_INFO.tokenMap,\n  marketMap: TOKEN_INFO.marketMap,\n  depth,\n  ammPoolSnapshot: ammPoolSnapshot,\n  feeBips: AMM_MAP[\"AMM-LRC-ETH\"].feeBips.toString(),\n  takerRate: takerRate ? takerRate.toString() : \"0\",\n  slipBips: slippage,\n});\nconsole.log(\n  \"Buy\",\n  \",LRC:\",\n  LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  \",minAmountInput LRC:\",\n  minAmountInput,\n  \",ETH:\",\n  calcTradeParams?.amountBOutSlip?.minReceivedVal\n);\n\nconst response: { hash: string } | any =\n  await LoopringAPI.userAPI.submitOrder(\n    {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      storageId: storageId.orderId,\n      sellToken: {\n        tokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n        volume: calcTradeParams?.amountS as string,\n      },\n      buyToken: {\n        tokenId: TOKEN_INFO.tokenMap[buy].tokenId,\n        volume: calcTradeParams?.amountBOutSlip.minReceived as string,\n      },\n      allOrNone: false,\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      maxFeeBips: 63,\n      fillAmountBOrS: false, // amm only false\n      tradeChannel: calcTradeParams?.exceedDepth\n        ? sdk.TradeChannel.BLANK\n        : sdk.TradeChannel.MIXED,\n      orderType: calcTradeParams?.exceedDepth\n        ? sdk.OrderType.ClassAmm\n        : sdk.OrderType.TakerOnly,\n      eddsaSignature: \"\",\n    },\n    eddsaKey.sk,\n    apiKey\n  );\nconsole.log(\"submitOrder\", response);\n```   \n\n***\n\n## ETH-LRC : for Quote to Base\n\n### MOCK Data\n\n> user should had apikey, please check get apikey\n\n```ts\nconst buy = \"ETH\",\n  sell = \"LRC\",\n  MARKET = \"LRC-ETH\",\n  AMM_MARKET = \"AMM-LRC-ETH\",\n  slippage = \"50\";\nconst isAtoB = false;\n```\n\n### Step 1. get apikey & eddsaKey\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst eddsaKey = await signatureKeyPairMock(accInfo);\napiKey = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo.accountId,\n    },\n    eddsaKey.sk\n  )\n).apiKey;\n```\n\n### Step  2. storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n  },\n  apiKey\n);\n```\n\n### Step 3. get user AmountMap, which decided user minimum order\n\n```ts\nconst amountMap = {\n  [AMM_MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: AMM_MAP[AMM_MARKET].market,\n      },\n      apiKey\n    )\n  ).amountMap,\n  [MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: MARKET,\n      },\n      apiKey\n    )\n  ).amountMap,\n};\n```\n\n### Step 4. depth, ammPoolSnapshot ,tickMap\n\n```ts\nconst [{depth}, {ammPoolSnapshot}] = await Promise.all([\n  LoopringAPI.exchangeAPI.getMixDepth({\n    market: AMM_MAP[\"AMM-LRC-ETH\"].market,\n  }),\n  LoopringAPI.ammpoolAPI.getAmmPoolSnapshot({\n    poolAddress: AMM_MAP[\"AMM-LRC-ETH\"].address,\n  }),\n]);\n```\n\n### Step  5. check MinAmt see log and calc mini receive and ouput value & maxfeeBips & priceImpact\n\n```ts\nconst { calcTradeParams, maxFeeBips, minimumReceived } = calculateSwap(\n  sell,\n  buy,\n  isAtoB,\n  10, // user Input value no decimal 10 lrc,\n  0.1,\n  //TODO MOCK value\n  amountMap,\n  \"LRC-ETH\",\n  // close = ticker.tickers[7],\n  depth,\n  ammPoolSnapshot,\n  TOKEN_INFO.tokenMap,\n  AMM_MAP\n);\nconsole.log(\n  \"Buy\",\n  \",ETH:\",\n  LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  \",minAmountInput ETH:\",\n  minAmountInput,\n  \",LRC:\",\n  calcTradeParams?.amountBOutSlip?.minReceivedVal\n);\n\nconst response: { hash: string } | any =\n  await LoopringAPI.userAPI.submitOrder(\n    {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      storageId: storageId.orderId,\n      sellToken: {\n        tokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n        volume: calcTradeParams?.amountS as string,\n      },\n      buyToken: {\n        tokenId: TOKEN_INFO.tokenMap[buy].tokenId,\n        volume: calcTradeParams?.amountBOutSlip.minReceived as string,\n      },\n      allOrNone: false,\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      maxFeeBips: 63,\n      fillAmountBOrS: false, // amm only false\n      tradeChannel: calcTradeParams?.exceedDepth\n        ? sdk.TradeChannel.BLANK\n        : sdk.TradeChannel.MIXED,\n      orderType: calcTradeParams?.exceedDepth\n        ? sdk.OrderType.ClassAmm\n        : sdk.OrderType.TakerOnly,\n      eddsaSignature: \"\",\n    },\n    eddsaKey.sk,\n    apiKey\n  );\nconsole.log(\"submitOrder\", response);\n``` \n\n\n### MockSwapData\n```ts\n//Default config value from getTokens & getMixMarkets\nimport * as sdk from \"../index\";\n\nexport const marketArray = [\"LRC-ETH\"];\nexport const marketMap = {\n  \"LRC-ETH\": {\n    baseTokenId: 1,\n    enabled: true,\n    market: \"LRC-ETH\",\n    orderbookAggLevels: 5,\n    precisionForPrice: 6,\n    quoteTokenId: 0,\n    status: 3,\n    isSwapEnabled: true,\n    createdAt: 1617967800000,\n  },\n};\n//v3/mix/depth?level=0&limit=50&market=LRC-ETH\nexport const deepMock = {\n  symbol: \"LRC-ETH\",\n  version: 23249677,\n  timestamp: 1655719492365,\n  mid_price: 0.00033248,\n  bids: [\n    {\n      price: 0.00030689,\n      amt: \"12041160324514792497908\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"618450503644320209925641\",\n      volTotal: \"198539605794234049017\",\n    },\n    {\n      price: 0.00030752,\n      amt: \"12016302126785109160251\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"606409343319805417427733\",\n      volTotal: \"194844233461662963807\",\n    },\n    {\n      price: 0.00030816,\n      amt: \"11991520826895479525387\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"594393041193020308267482\",\n      volTotal: \"191148861129091878597\",\n    },\n    {\n      price: 0.00030881,\n      amt: \"12329062048917727073625\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"582401520366124828742095\",\n      volTotal: \"187453488796520793387\",\n    },\n    {\n      price: 0.00030945,\n      amt: \"11941442525358097768419\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"570072458317207101668470\",\n      volTotal: \"183646135484174826807\",\n    },\n    {\n      price: 0.0003102,\n      amt: \"3223726000000000000000\",\n      vol: \"999999805200000000\",\n      amtTotal: \"558131015791849003900051\",\n      volTotal: \"179950763151603741597\",\n    },\n    {\n      price: 0.0003104,\n      amt: \"11904963012947201084062\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"554907289791849003900051\",\n      volTotal: \"178950763346403741597\",\n    },\n    {\n      price: 0.00031072,\n      amt: \"11892800074855146120151\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"543002326778901802815989\",\n      volTotal: \"175255391013832656387\",\n    },\n    {\n      price: 0.00031137,\n      amt: \"12227667622887455762012\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"531109526704046656695838\",\n      volTotal: \"171560018681261571177\",\n    },\n    {\n      price: 0.00031202,\n      amt: \"11843337524732768607817\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"518881859081159200933826\",\n      volTotal: \"167752665368915604597\",\n    },\n    {\n      price: 0.00031266,\n      amt: \"11819088718260537718160\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"507038521556426432326009\",\n      volTotal: \"164057293036344519387\",\n    },\n    {\n      price: 0.0003133,\n      amt: \"11794914308461194855590\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"495219432838165894607849\",\n      volTotal: \"160361920703773434177\",\n    },\n    {\n      price: 0.00031395,\n      amt: \"12127129883064173669497\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"483424518529704699752259\",\n      volTotal: \"156666548371202348967\",\n    },\n    {\n      price: 0.0003146,\n      amt: \"11746060536480763829870\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"471297388646640526082762\",\n      volTotal: \"152859195058856382387\",\n    },\n    {\n      price: 0.00031524,\n      amt: \"11722109721002274877424\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"459551328110159762252892\",\n      volTotal: \"149163822726285297177\",\n    },\n    {\n      price: 0.0003159,\n      amt: \"12052351993023897680738\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"447829218389157487375468\",\n      volTotal: \"145468450393714211967\",\n    },\n    {\n      price: 0.00031655,\n      amt: \"11673707113082743010268\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"435776866396133589694730\",\n      volTotal: \"141661097081368245387\",\n    },\n    {\n      price: 0.00031699,\n      amt: \"615000000000000000000\",\n      vol: \"194954999999999949\",\n      amtTotal: \"424103159283050846684462\",\n      volTotal: \"137965724748797160177\",\n    },\n    {\n      price: 0.00031719,\n      amt: \"11649977142974837964110\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"423488159283050846684462\",\n      volTotal: \"137770769748797160228\",\n    },\n    {\n      price: 0.00031784,\n      amt: \"11626319455782556517212\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"411838182140076008720352\",\n      volTotal: \"134075397416226075018\",\n    },\n    {\n      price: 0.0003185,\n      amt: \"11953964321007990024755\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"400211862684293452203140\",\n      volTotal: \"130380025083654989808\",\n    },\n    {\n      price: 0.00031934,\n      amt: \"11571837200722111826863\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"388257898363285462178385\",\n      volTotal: \"126572671771309023228\",\n    },\n    {\n      price: 0.00031979,\n      amt: \"11555429099390519988949\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"376686061162563350351522\",\n      volTotal: \"122877299438737938018\",\n    },\n    {\n      price: 0.00032,\n      amt: \"300000000000000000000\",\n      vol: \"96000000000000000\",\n      amtTotal: \"365130632063172830362573\",\n      volTotal: \"119181927106166852808\",\n    },\n    {\n      price: 0.00032044,\n      amt: \"11532058329906875386268\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"364830632063172830362573\",\n      volTotal: \"119085927106166852808\",\n    },\n    {\n      price: 0.0003211,\n      amt: \"11857145662584872212009\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"353298573733265954976305\",\n      volTotal: \"115390554773595767598\",\n    },\n    {\n      price: 0.00032176,\n      amt: \"11484826169666631095087\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"341441428070681082764296\",\n      volTotal: \"111583201461249801018\",\n    },\n    {\n      price: 0.00032241,\n      amt: \"11461669156035188891431\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"329956601901014451669209\",\n      volTotal: \"107887829128678715808\",\n    },\n    {\n      price: 0.00032294,\n      amt: \"22266286128259997368320\",\n      vol: \"7190674442260284416\",\n      amtTotal: \"318494932744979262777778\",\n      volTotal: \"104192456796107630598\",\n    },\n    {\n      price: 0.00032307,\n      amt: \"11784846142950476791130\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"296228646616719265409458\",\n      volTotal: \"97001782353847346182\",\n    },\n    {\n      price: 0.00032333,\n      amt: \"31042151210389998665728\",\n      vol: \"10037169172367501312\",\n      amtTotal: \"284443800473768788618328\",\n      volTotal: \"93194429041501379602\",\n    },\n    {\n      price: 0.00032354,\n      amt: \"19082720347089998446592\",\n      vol: \"6174214168300968960\",\n      amtTotal: \"253401649263378789952600\",\n      volTotal: \"83157259869133878290\",\n    },\n    {\n      price: 0.00032373,\n      amt: \"11414868337793698506576\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"234318928916288791506008\",\n      volTotal: \"76983045700832909330\",\n    },\n    {\n      price: 0.00032438,\n      amt: \"11391922481177051106050\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"222904060578495092999432\",\n      volTotal: \"73287673368261824120\",\n    },\n    {\n      price: 0.00032503,\n      amt: \"11369045742792164433715\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"211512138097318041893382\",\n      volTotal: \"69592301035690738910\",\n    },\n    {\n      price: 0.00032512,\n      amt: \"7101984539779999465472\",\n      vol: \"2308997213573273600\",\n      amtTotal: \"200143092354525877459667\",\n      volTotal: \"65896928703119653700\",\n    },\n    {\n      price: 0.0003257,\n      amt: \"11689707913498419991686\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"193041107814745877994195\",\n      volTotal: \"63587931489546380100\",\n    },\n    {\n      price: 0.00032636,\n      amt: \"11322810509578528739940\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"181351399901247458002509\",\n      volTotal: \"59780578177200413520\",\n    },\n    {\n      price: 0.00032702,\n      amt: \"11300141532643741902081\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"170028589391668929262569\",\n      volTotal: \"56085205844629328310\",\n    },\n    {\n      price: 0.00032709,\n      amt: \"1511898000000000000000\",\n      vol: \"494541835799999898\",\n      amtTotal: \"158728447859025187360488\",\n      volTotal: \"52389833512058243100\",\n    },\n    {\n      price: 0.00032767,\n      amt: \"11277540564700637960582\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"157216549859025187360488\",\n      volTotal: \"51895291676258243202\",\n    },\n    {\n      price: 0.00032838,\n      amt: \"11594014901713773553177\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"145939009294324549399906\",\n      volTotal: \"48199919343687157992\",\n    },\n    {\n      price: 0.00032899,\n      amt: \"11232203228917728004878\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"134344994392610775846729\",\n      volTotal: \"44392566031341191412\",\n    },\n    {\n      price: 0.00032959,\n      amt: \"31100749000000000753664\",\n      vol: \"10250806870400000000\",\n      amtTotal: \"123112791163693047841851\",\n      volTotal: \"40697193698770106202\",\n    },\n    {\n      price: 0.00032965,\n      amt: \"11209805337410429375102\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"92012042163693047088187\",\n      volTotal: \"30446386828370106202\",\n    },\n    {\n      price: 0.00033031,\n      amt: \"11187474373893810850495\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"80802236826282617713085\",\n      volTotal: \"26751014495799020992\",\n    },\n    {\n      price: 0.00033098,\n      amt: \"11503202913004006553102\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"69614762452388806862590\",\n      volTotal: \"23055642163227935782\",\n    },\n    {\n      price: 0.00033099,\n      amt: \"26515451000000002129920\",\n      vol: \"8776614281000000512\",\n      amtTotal: \"58111559539384800309488\",\n      volTotal: \"19248288850881969202\",\n    },\n    {\n      price: 0.0003313,\n      amt: \"20499506300000000802816\",\n      vol: \"6791486437190000640\",\n      amtTotal: \"31596108539384798179568\",\n      volTotal: \"10471674569881968690\",\n    },\n    {\n      price: 0.00033165,\n      amt: \"11096602239384797376752\",\n      vol: \"3680188132691968050\",\n      amtTotal: \"11096602239384797376752\",\n      volTotal: \"3680188132691968050\",\n    },\n  ],\n  bids_prices: [\n    0.00030689, 0.00030752, 0.00030816, 0.00030881, 0.00030945, 0.0003102,\n    0.0003104, 0.00031072, 0.00031137, 0.00031202, 0.00031266, 0.0003133,\n    0.00031395, 0.0003146, 0.00031524, 0.0003159, 0.00031655, 0.00031699,\n    0.00031719, 0.00031784, 0.0003185, 0.00031934, 0.00031979, 0.00032,\n    0.00032044, 0.0003211, 0.00032176, 0.00032241, 0.00032294, 0.00032307,\n    0.00032333, 0.00032354, 0.00032373, 0.00032438, 0.00032503, 0.00032512,\n    0.0003257, 0.00032636, 0.00032702, 0.00032709, 0.00032767, 0.00032838,\n    0.00032899, 0.00032959, 0.00032965, 0.00033031, 0.00033098, 0.00033099,\n    0.0003313, 0.00033165,\n  ],\n  bids_amtTotals: [\n    \"618450503644320209925641\",\n    \"606409343319805417427733\",\n    \"594393041193020308267482\",\n    \"582401520366124828742095\",\n    \"570072458317207101668470\",\n    \"558131015791849003900051\",\n    \"554907289791849003900051\",\n    \"543002326778901802815989\",\n    \"531109526704046656695838\",\n    \"518881859081159200933826\",\n    \"507038521556426432326009\",\n    \"495219432838165894607849\",\n    \"483424518529704699752259\",\n    \"471297388646640526082762\",\n    \"459551328110159762252892\",\n    \"447829218389157487375468\",\n    \"435776866396133589694730\",\n    \"424103159283050846684462\",\n    \"423488159283050846684462\",\n    \"411838182140076008720352\",\n    \"400211862684293452203140\",\n    \"388257898363285462178385\",\n    \"376686061162563350351522\",\n    \"365130632063172830362573\",\n    \"364830632063172830362573\",\n    \"353298573733265954976305\",\n    \"341441428070681082764296\",\n    \"329956601901014451669209\",\n    \"318494932744979262777778\",\n    \"296228646616719265409458\",\n    \"284443800473768788618328\",\n    \"253401649263378789952600\",\n    \"234318928916288791506008\",\n    \"222904060578495092999432\",\n    \"211512138097318041893382\",\n    \"200143092354525877459667\",\n    \"193041107814745877994195\",\n    \"181351399901247458002509\",\n    \"170028589391668929262569\",\n    \"158728447859025187360488\",\n    \"157216549859025187360488\",\n    \"145939009294324549399906\",\n    \"134344994392610775846729\",\n    \"123112791163693047841851\",\n    \"92012042163693047088187\",\n    \"80802236826282617713085\",\n    \"69614762452388806862590\",\n    \"58111559539384800309488\",\n    \"31596108539384798179568\",\n    \"11096602239384797376752\",\n  ],\n  bids_volTotals: [\n    \"198539605794234049017\",\n    \"194844233461662963807\",\n    \"191148861129091878597\",\n    \"187453488796520793387\",\n    \"183646135484174826807\",\n    \"179950763151603741597\",\n    \"178950763346403741597\",\n    \"175255391013832656387\",\n    \"171560018681261571177\",\n    \"167752665368915604597\",\n    \"164057293036344519387\",\n    \"160361920703773434177\",\n    \"156666548371202348967\",\n    \"152859195058856382387\",\n    \"149163822726285297177\",\n    \"145468450393714211967\",\n    \"141661097081368245387\",\n    \"137965724748797160177\",\n    \"137770769748797160228\",\n    \"134075397416226075018\",\n    \"130380025083654989808\",\n    \"126572671771309023228\",\n    \"122877299438737938018\",\n    \"119181927106166852808\",\n    \"119085927106166852808\",\n    \"115390554773595767598\",\n    \"111583201461249801018\",\n    \"107887829128678715808\",\n    \"104192456796107630598\",\n    \"97001782353847346182\",\n    \"93194429041501379602\",\n    \"83157259869133878290\",\n    \"76983045700832909330\",\n    \"73287673368261824120\",\n    \"69592301035690738910\",\n    \"65896928703119653700\",\n    \"63587931489546380100\",\n    \"59780578177200413520\",\n    \"56085205844629328310\",\n    \"52389833512058243100\",\n    \"51895291676258243202\",\n    \"48199919343687157992\",\n    \"44392566031341191412\",\n    \"40697193698770106202\",\n    \"30446386828370106202\",\n    \"26751014495799020992\",\n    \"23055642163227935782\",\n    \"19248288850881969202\",\n    \"10471674569881968690\",\n    \"3680188132691968050\",\n  ],\n  bids_amtTotal: \"618450503644320209925641\",\n  bids_volTotal: \"198539605794234049017\",\n  asks: [\n    {\n      price: 0.00033331,\n      amt: \"26466599999999999737856\",\n      vol: \"8821317780000000000\",\n      amtTotal: \"26466599999999999737856\",\n      volTotal: \"8821317780000000000\",\n    },\n    {\n      price: 0.0003336,\n      amt: \"33880800000000001048576\",\n      vol: \"11302634880000000000\",\n      amtTotal: \"60347400000000000786432\",\n      volTotal: \"20123952660000000000\",\n    },\n    {\n      price: 0.00033371,\n      amt: \"11142477800817399987988\",\n      vol: \"3718356266910774549\",\n      amtTotal: \"71489877800817400774420\",\n      volTotal: \"23842308926910774549\",\n    },\n    {\n      price: 0.00033439,\n      amt: \"11410124103475892197402\",\n      vol: \"3815340399218399705\",\n      amtTotal: \"82900001904293292971822\",\n      volTotal: \"27657649326129174254\",\n    },\n    {\n      price: 0.00033501,\n      amt: \"39334199999999992922112\",\n      vol: \"13176957000000000000\",\n      amtTotal: \"122234201904293285893934\",\n      volTotal: \"40834606326129174254\",\n    },\n    {\n      price: 0.00033506,\n      amt: \"11052295534472154230337\",\n      vol: \"3703108939445215718\",\n      amtTotal: \"133286497438765440124271\",\n      volTotal: \"44537715265574389972\",\n    },\n    {\n      price: 0.00033572,\n      amt: \"11030456322913363709718\",\n      vol: \"3703093651997124565\",\n      amtTotal: \"144316953761678803833989\",\n      volTotal: \"48240808917571514537\",\n    },\n    {\n      price: 0.00033638,\n      amt: \"11008681778518069039476\",\n      vol: \"3703078409816047858\",\n      amtTotal: \"155325635540196872873465\",\n      volTotal: \"51943887327387562395\",\n    },\n    {\n      price: 0.000337,\n      amt: \"7188173683760000139264\",\n      vol: \"2422342649690282496\",\n      amtTotal: \"162513809223956873012729\",\n      volTotal: \"54366229977077844891\",\n    },\n    {\n      price: 0.00033706,\n      amt: \"11319571950108460741855\",\n      vol: \"3815277012711042502\",\n      amtTotal: \"173833381174065333754584\",\n      volTotal: \"58181506989788887393\",\n    },\n    {\n      price: 0.00033773,\n      amt: \"10964670732513311387215\",\n      vol: \"3703047602083844528\",\n      amtTotal: \"184798051906578645141799\",\n      volTotal: \"61884554591872731921\",\n    },\n    {\n      price: 0.00033848,\n      amt: \"10943090596879450870975\",\n      vol: \"3703921209677097807\",\n      amtTotal: \"195741142503458096012774\",\n      volTotal: \"65588475801549829728\",\n    },\n    {\n      price: 0.00033893,\n      amt: \"31086310012520000126976\",\n      vol: \"10535772189443278848\",\n      amtTotal: \"226827452515978096139750\",\n      volTotal: \"76124247990993108576\",\n    },\n    {\n      price: 0.00033907,\n      amt: \"10921574108084085072499\",\n      vol: \"3703126650187824910\",\n      amtTotal: \"237749026624062181212249\",\n      volTotal: \"79827374641180933486\",\n    },\n    {\n      price: 0.00033934,\n      amt: \"22061773569720001232896\",\n      vol: \"7486221625413088256\",\n      amtTotal: \"259810800193782182445145\",\n      volTotal: \"87313596266594021742\",\n    },\n    {\n      price: 0.00033975,\n      amt: \"11230093484570461106334\",\n      vol: \"3815326678720011608\",\n      amtTotal: \"271040893678352643551479\",\n      volTotal: \"91128922945314033350\",\n    },\n    {\n      price: 0.00034042,\n      amt: \"10878083875111520592396\",\n      vol: \"3703095772122414389\",\n      amtTotal: \"281918977553464164143875\",\n      volTotal: \"94832018717436447739\",\n    },\n    {\n      price: 0.00034061,\n      amt: \"19029641944770000453632\",\n      vol: \"6481686342808109056\",\n      amtTotal: \"300948619498234164597507\",\n      volTotal: \"101313705060244556795\",\n    },\n    {\n      price: 0.00034109,\n      amt: \"10856758733704286197912\",\n      vol: \"3703080631272015254\",\n      amtTotal: \"311805378231938450795419\",\n      volTotal: \"105016785691516572049\",\n    },\n    {\n      price: 0.00034176,\n      amt: \"10835496238854895014260\",\n      vol: \"3703065534900672185\",\n      amtTotal: \"322640874470793345809679\",\n      volTotal: \"108719851226417244234\",\n    },\n    {\n      price: 0.00034244,\n      amt: \"11141671799245742102774\",\n      vol: \"3815263899323431057\",\n      amtTotal: \"333782546270039087912453\",\n      volTotal: \"112535115125740675291\",\n    },\n    {\n      price: 0.00034312,\n      amt: \"10792518633700140402041\",\n      vol: \"3703035020801012310\",\n      amtTotal: \"344575064903739228314494\",\n      volTotal: \"116238150146541687601\",\n    },\n    {\n      price: 0.00034379,\n      amt: \"10771444484888773263977\",\n      vol: \"3703020058155356239\",\n      amtTotal: \"355346509388628001578471\",\n      volTotal: \"119941170204697043840\",\n    },\n    {\n      price: 0.00034447,\n      amt: \"11075875299655656611658\",\n      vol: \"3815217183808722096\",\n      amtTotal: \"366422384688283658190129\",\n      volTotal: \"123756387388505765936\",\n    },\n    {\n      price: 0.00034515,\n      amt: \"10728847020295584791583\",\n      vol: \"3702989813955495075\",\n      amtTotal: \"377151231708579242981712\",\n      volTotal: \"127459377202461261011\",\n    },\n    {\n      price: 0.00034582,\n      amt: \"10707958999548106661900\",\n      vol: \"3702974983460764366\",\n      amtTotal: \"387859190708127349643612\",\n      volTotal: \"131162352185922025377\",\n    },\n    {\n      price: 0.00034649,\n      amt: \"10687131919892014508549\",\n      vol: \"3702960196234208540\",\n      amtTotal: \"398546322628019364152161\",\n      volTotal: \"134865312382156233917\",\n    },\n    {\n      price: 0.00034718,\n      amt: \"10989265205593964126102\",\n      vol: \"3815155690641938295\",\n      amtTotal: \"409535587833613328278263\",\n      volTotal: \"138680468072798172212\",\n    },\n    {\n      price: 0.00034809,\n      amt: \"10645033127428079147754\",\n      vol: \"3705341637309061860\",\n      amtTotal: \"420180620961041407426017\",\n      volTotal: \"142385809710107234072\",\n    },\n    {\n      price: 0.00034854,\n      amt: \"10624389276271547157517\",\n      vol: \"3703021892850000724\",\n      amtTotal: \"430805010237312954583534\",\n      volTotal: \"146088831602957234796\",\n    },\n    {\n      price: 0.00034922,\n      amt: \"10603805418694082174472\",\n      vol: \"3703007072472544949\",\n      amtTotal: \"441408815656007036758006\",\n      volTotal: \"149791838675429779745\",\n    },\n    {\n      price: 0.00034991,\n      amt: \"10903667052066234563130\",\n      vol: \"3815203952623454269\",\n      amtTotal: \"452312482708073271321136\",\n      volTotal: \"153607042628053234014\",\n    },\n    {\n      price: 0.00035059,\n      amt: \"10562197544947631702552\",\n      vol: \"3702977114803447505\",\n      amtTotal: \"462874680253020903023688\",\n      volTotal: \"157310019742856681519\",\n    },\n    {\n      price: 0.00035127,\n      amt: \"10541794072549149477757\",\n      vol: \"3702962424303320597\",\n      amtTotal: \"473416474325570052501445\",\n      volTotal: \"161012982167160002116\",\n    },\n    {\n      price: 0.00035196,\n      amt: \"10839964505283434387937\",\n      vol: \"3815158086789770653\",\n      amtTotal: \"484256438830853486889382\",\n      volTotal: \"164828140253949772769\",\n    },\n    {\n      price: 0.00035265,\n      amt: \"10500550295026604907238\",\n      vol: \"3702932728783504366\",\n      amtTotal: \"494756989125880091796620\",\n      volTotal: \"168531072982733277135\",\n    },\n    {\n      price: 0.00035333,\n      amt: \"10480325106225117837726\",\n      vol: \"3702918166647567295\",\n      amtTotal: \"505237314232105209634346\",\n      volTotal: \"172233991149380844430\",\n    },\n    {\n      price: 0.00035401,\n      amt: \"10460158295034970667917\",\n      vol: \"3702903646543510388\",\n      amtTotal: \"515697472527140180302263\",\n      volTotal: \"175936894795924354818\",\n    },\n    {\n      price: 0.0003547,\n      amt: \"10756101480844670483856\",\n      vol: \"3815097705412174743\",\n      amtTotal: \"526453574007984850786119\",\n      volTotal: \"179751992501336529561\",\n    },\n    {\n      price: 0.000355,\n      amt: \"2879934000000000000000\",\n      vol: \"1022376570000000000\",\n      amtTotal: \"529333508007984850786119\",\n      volTotal: \"180774369071336529561\",\n    },\n    {\n      price: 0.00035539,\n      amt: \"10419392212908119384882\",\n      vol: \"3702874294964379056\",\n      amtTotal: \"539752900220892970171001\",\n      volTotal: \"184477243366300908617\",\n    },\n    {\n      price: 0.00035607,\n      amt: \"10399400937404414745812\",\n      vol: \"3702859901246016389\",\n      amtTotal: \"550152301158297384916813\",\n      volTotal: \"188180103267546925006\",\n    },\n    {\n      price: 0.00035675,\n      amt: \"10379467141462596339294\",\n      vol: \"3702845548912938279\",\n      amtTotal: \"560531768299759981256107\",\n      volTotal: \"191882948816459863285\",\n    },\n    {\n      price: 0.00035781,\n      amt: \"10673207910450037674513\",\n      vol: \"3818930797471485007\",\n      amtTotal: \"571204976210210018930620\",\n      volTotal: \"195701879613931348292\",\n    },\n    {\n      price: 0.00035815,\n      amt: \"10339171406073422424770\",\n      vol: \"3702919927697518809\",\n      amtTotal: \"581544147616283441355390\",\n      volTotal: \"199404799541628867101\",\n    },\n    {\n      price: 0.00035883,\n      amt: \"10319410450646547471681\",\n      vol: \"3702905502200057190\",\n      amtTotal: \"591863558066929988827071\",\n      volTotal: \"203107705043828924291\",\n    },\n    {\n      price: 0.00035887,\n      amt: \"1253970999999999795200\",\n      vol: \"449999996860000051\",\n      amtTotal: \"593117529066929988622271\",\n      volTotal: \"203557705040688924342\",\n    },\n    {\n      price: 0.00035952,\n      amt: \"10299706093934767574874\",\n      vol: \"3702891118019657590\",\n      amtTotal: \"603417235160864756197145\",\n      volTotal: \"207260596158708581932\",\n    },\n    {\n      price: 0.00036,\n      amt: \"491031000000000000000\",\n      vol: \"176771040000000000\",\n      amtTotal: \"603908266160864756197145\",\n      volTotal: \"207437367198708581932\",\n    },\n    {\n      price: 0.00036022,\n      amt: \"10591268908994289896668\",\n      vol: \"3815084938649532411\",\n      amtTotal: \"614499535069859046093813\",\n      volTotal: \"211252452137358114343\",\n    },\n  ],\n  asks_prices: [\n    0.00033331, 0.0003336, 0.00033371, 0.00033439, 0.00033501, 0.00033506,\n    0.00033572, 0.00033638, 0.000337, 0.00033706, 0.00033773, 0.00033848,\n    0.00033893, 0.00033907, 0.00033934, 0.00033975, 0.00034042, 0.00034061,\n    0.00034109, 0.00034176, 0.00034244, 0.00034312, 0.00034379, 0.00034447,\n    0.00034515, 0.00034582, 0.00034649, 0.00034718, 0.00034809, 0.00034854,\n    0.00034922, 0.00034991, 0.00035059, 0.00035127, 0.00035196, 0.00035265,\n    0.00035333, 0.00035401, 0.0003547, 0.000355, 0.00035539, 0.00035607,\n    0.00035675, 0.00035781, 0.00035815, 0.00035883, 0.00035887, 0.00035952,\n    0.00036, 0.00036022,\n  ],\n  asks_amtTotals: [\n    \"26466599999999999737856\",\n    \"60347400000000000786432\",\n    \"71489877800817400774420\",\n    \"82900001904293292971822\",\n    \"122234201904293285893934\",\n    \"133286497438765440124271\",\n    \"144316953761678803833989\",\n    \"155325635540196872873465\",\n    \"162513809223956873012729\",\n    \"173833381174065333754584\",\n    \"184798051906578645141799\",\n    \"195741142503458096012774\",\n    \"226827452515978096139750\",\n    \"237749026624062181212249\",\n    \"259810800193782182445145\",\n    \"271040893678352643551479\",\n    \"281918977553464164143875\",\n    \"300948619498234164597507\",\n    \"311805378231938450795419\",\n    \"322640874470793345809679\",\n    \"333782546270039087912453\",\n    \"344575064903739228314494\",\n    \"355346509388628001578471\",\n    \"366422384688283658190129\",\n    \"377151231708579242981712\",\n    \"387859190708127349643612\",\n    \"398546322628019364152161\",\n    \"409535587833613328278263\",\n    \"420180620961041407426017\",\n    \"430805010237312954583534\",\n    \"441408815656007036758006\",\n    \"452312482708073271321136\",\n    \"462874680253020903023688\",\n    \"473416474325570052501445\",\n    \"484256438830853486889382\",\n    \"494756989125880091796620\",\n    \"505237314232105209634346\",\n    \"515697472527140180302263\",\n    \"526453574007984850786119\",\n    \"529333508007984850786119\",\n    \"539752900220892970171001\",\n    \"550152301158297384916813\",\n    \"560531768299759981256107\",\n    \"571204976210210018930620\",\n    \"581544147616283441355390\",\n    \"591863558066929988827071\",\n    \"593117529066929988622271\",\n    \"603417235160864756197145\",\n    \"603908266160864756197145\",\n    \"614499535069859046093813\",\n  ],\n  asks_volTotals: [\n    \"8821317780000000000\",\n    \"20123952660000000000\",\n    \"23842308926910774549\",\n    \"27657649326129174254\",\n    \"40834606326129174254\",\n    \"44537715265574389972\",\n    \"48240808917571514537\",\n    \"51943887327387562395\",\n    \"54366229977077844891\",\n    \"58181506989788887393\",\n    \"61884554591872731921\",\n    \"65588475801549829728\",\n    \"76124247990993108576\",\n    \"79827374641180933486\",\n    \"87313596266594021742\",\n    \"91128922945314033350\",\n    \"94832018717436447739\",\n    \"101313705060244556795\",\n    \"105016785691516572049\",\n    \"108719851226417244234\",\n    \"112535115125740675291\",\n    \"116238150146541687601\",\n    \"119941170204697043840\",\n    \"123756387388505765936\",\n    \"127459377202461261011\",\n    \"131162352185922025377\",\n    \"134865312382156233917\",\n    \"138680468072798172212\",\n    \"142385809710107234072\",\n    \"146088831602957234796\",\n    \"149791838675429779745\",\n    \"153607042628053234014\",\n    \"157310019742856681519\",\n    \"161012982167160002116\",\n    \"164828140253949772769\",\n    \"168531072982733277135\",\n    \"172233991149380844430\",\n    \"175936894795924354818\",\n    \"179751992501336529561\",\n    \"180774369071336529561\",\n    \"184477243366300908617\",\n    \"188180103267546925006\",\n    \"191882948816459863285\",\n    \"195701879613931348292\",\n    \"199404799541628867101\",\n    \"203107705043828924291\",\n    \"203557705040688924342\",\n    \"207260596158708581932\",\n    \"207437367198708581932\",\n    \"211252452137358114343\",\n  ],\n  asks_amtTotal: \"614499535069859046093813\",\n  asks_volTotal: \"211252452137358114343\",\n};\n//v3/amm/balance?poolAddress=0xfEB069407df0e1e4B365C10992F1bc16c078E34b\nexport const ammPoolSnapshot: sdk.AmmPoolSnapshot = {\n  poolName: \"AMM-LRC-ETH\",\n  poolAddress: \"0x18920d6e6fb7ebe057a4dd9260d6d95845c95036\",\n  pooled: [\n    {\n      tokenId: 1,\n      volume: \"11198097977488137000000000\",\n    },\n    {\n      tokenId: 0,\n      volume: \"3725368050950874300000\",\n    },\n  ],\n  lp: {\n    tokenId: 83,\n    volume: \"34138981282200\",\n  },\n  risky: false,\n};\n//v3/amm/balance?poolAddress=0xfEB069407df0e1e4B365C10992F1bc16c078E34b\nexport const ammPool = {\n  poolName: \"AMM-LRC-ETH\",\n  poolAddress: \"0x18920d6e6fb7ebe057a4dd9260d6d95845c95036\",\n  pooled: [\n    { tokenId: 1, volume: \"11215027899488137000000000\" },\n    { tokenId: 0, volume: \"3720052711450874300000\" },\n  ],\n  lp: { tokenId: 83, volume: \"34141365482200\" },\n  risky: false,\n};\n\n//v3/mix/ticker?market=LRC-ETH\nexport const ticker = {\n  tickers: [\n    [\n      \"COMBINE-LRC-ETH\",\n      \"1655625077879\",\n      \"2429371927000000000000000\",\n      \"814655525450000000000\",\n      \"0.00035052\",\n      \"0.00035222\",\n      \"0.00032201\",\n      \"0.00033367\",\n      \"772\",\n      \"\",\n      \"\",\n      \"\",\n      \"\",\n    ],\n  ],\n};\n\n//v3/user/orderUserRateAmount?accountId=10427&market=LRC-ETH\nexport const userAmount = {\n  \"LRC-ETH\": {\n    LRC: {\n      tokenSymbol: \"LRC\",\n      baseOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"231046501539337141\",\n    },\n    ETH: {\n      tokenSymbol: \"ETH\",\n      baseOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"75150737796750\",\n    },\n  },\n  \"AMM-LRC-ETH\": {\n    LRC: {\n      tokenSymbol: \"LRC\",\n      baseOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"231046501539337141\",\n    },\n    ETH: {\n      tokenSymbol: \"ETH\",\n      baseOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"75150737796750\",\n    },\n  },\n};\nexport const TokenMapMockSwap = {\n  ETH: {\n    type: \"ETH\",\n    tokenId: 0,\n    symbol: \"ETH\",\n    name: \"Ethereum\",\n    address: \"0x0000000000000000000000000000000000000000\",\n    decimals: 18,\n    precision: 7,\n    precisionForOrder: 3,\n    orderAmounts: {\n      minimum: \"1700000000000000\",\n      maximum: \"1000000000000000000000\",\n      dust: \"200000000000000\",\n    },\n    luckyTokenAmounts: {\n      minimum: \"50000000000000\",\n      maximum: \"1000000000000000000000\",\n      dust: \"50000000000000\",\n    },\n    fastWithdrawLimit: \"100000000000000000000\",\n    gasAmounts: {\n      distribution: \"85000\",\n      deposit: \"110000\",\n    },\n    enabled: true,\n    isLpToken: false,\n    tradePairs: [\"LRC\"],\n  },\n  LRC: {\n    type: \"ERC20\",\n    tokenId: 1,\n    symbol: \"LRC\",\n    name: \"Loopring\",\n    address: \"0xbbbbca6a901c926f240b89eacb641d8aec7aeafd\",\n    decimals: 18,\n    precision: 3,\n    precisionForOrder: 3,\n    orderAmounts: {\n      minimum: \"5000000000000000000\",\n      maximum: \"5000000000000000000000000\",\n      dust: \"5000000000000000000\",\n    },\n    luckyTokenAmounts: {\n      minimum: \"50000000000000000\",\n      maximum: \"5000000000000000000000000\",\n      dust: \"50000000000000000\",\n    },\n    fastWithdrawLimit: \"750000000000000000000000\",\n    gasAmounts: {\n      distribution: \"101827\",\n      deposit: \"150000\",\n    },\n    enabled: true,\n    isLpToken: false,\n    tradePairs: [\"ETH\"],\n  },\n};\n\nexport const MAPFEEBIPS = 63;\n\n\n```\n\n"
  },
  {
    "path": "docs/js_sdk/exchange/ammpool_api.md",
    "content": "# AmmPool API\n\n## getAmmPoolConf\n\n```typescript\nconst { ammpools, pairs } = await api.getAmmPoolConf();\n```\n\n## getAmmPoolUserRewards\n\n```typescript\nconst response: any = await api.getAmmPoolUserRewards({\n  owner: acc.accountId.toString(),\n});\n```\n\n## getAmmPoolActivityRules\n\n```typescript\nconst response: any = await api.getAmmPoolActivityRules();\n```\n\n## getAmmPoolStats\n\n```typescript\nconst response: any = await api.getAmmPoolStats();\n```\n\n## getAmmPoolSnapshot\n\n```typescript\nconst request: GetAmmPoolSnapshotRequest = {\n  poolAddress,\n};\nconst response = await api.getAmmPoolSnapshot(request, acc.apiKey);\n```\n\n## getAmmPoolBalances\n\n```typescript\nconst response = await api.getAmmPoolBalances();\n```\n\n## getAmmPoolTrades\n\n```typescript\nconst request: GetAmmPoolTradesRequest = {\n  ammPoolAddress: poolAddress,\n};\n\nconst response = await api.getAmmPoolTrades(request);\n```\n\n## getUserAmmPoolTxs\n\n```typescript\nconst request: GetUserAmmPoolTxsRequest = {\n  accountId: acc.accountId,\n};\n\nconst response = await api.getUserAmmPoolTxs(request, acc.apiKey);\n```\n\n## joinAmmPool\n\n```typescript\nconst request2: JoinAmmPoolRequest = {\n  owner: acc.address,\n  poolAddress,\n  joinTokens: {\n    pooled: [\n      { tokenId: \"1\", volume: \"1000000000000000000000\" },\n      { tokenId: \"0\", volume: \"1000000000000000000\" },\n    ],\n    minimumLp: { tokenId: \"4\", volume: \"100000\" },\n  },\n  storageIds: [storageId_1.offchainId, storageId.offchainId],\n  fee: \"1000000000000000000\",\n};\n\nconst patch: AmmPoolRequestPatch = {\n  chainId: ChainId.GORLI,\n  ammName: \"LRCETH-Pool\",\n  poolAddress,\n  eddsaKey: acc.eddsaKey,\n};\n\nconst response = await api.joinAmmPool(request2, patch, acc.apiKey);\n```\n\n## exitAmmPool\n\n```typescript\nconst request2: ExitAmmPoolRequest = {\n  owner: acc.address,\n  poolAddress,\n  exitTokens: {\n    unPooled: [\n      { tokenId: \"1\", volume: \"1000000000000000000000\" },\n      { tokenId: \"0\", volume: \"1000000000000000000\" },\n    ],\n    burned: { tokenId: \"4\", volume: \"100000\" },\n  },\n  storageId: storageId_1.offchainId,\n  maxFee: \"1000000000000000000\",\n};\n\nconst patch: AmmPoolRequestPatch = {\n  chainId: ChainId.GORLI,\n  ammName: \"LRCETH-Pool\",\n  poolAddress,\n  eddsaKey: acc.eddsaKey,\n};\n\nconst response = await api.exitAmmPool(request2, patch, acc.apiKey);\n```\n"
  },
  {
    "path": "docs/js_sdk/exchange/exchange.md",
    "content": "# Loopring Exchange\n\nDefinition: Loopring Dex Main API for get Exchange Information, L2 Block, ERC20 Token Information, AMM Information,\nMarket Config and so on static and dynamic information\n\n***\n\n## getExchangeInfo\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getExchangeInfo();\nconsole.log(response);\n```\n\n***\n\n## getTokens\n\n```ts\nconst {tokensMap, coinMap, totalCoinMap, idIndex, addressIndex} =\n  await LoopringAPI.exchangeAPI.getTokens<any>();\nconsole.log(\n  \"tokenMap:\",\n  tokensMap,\n  coinMap,\n  totalCoinMap,\n  idIndex,\n  addressIndex\n);\n```\n\n***\n\n## getMixMarkets\n\n```ts\nconst {markets, pairs, tokenArr, tokenArrStr, marketArr, marketArrStr} =\n  await LoopringAPI.exchangeAPI.getMixMarkets();\nconsole.log(\"markets:\", markets);\nconsole.log(\"pairs:\", pairs);\nconsole.log(\"tokenArr:\", tokenArr);\nconsole.log(\"tokenArrStr:\", tokenArrStr);\nconsole.log(\"marketArr\", marketArr);\nconsole.log(\"marketArrStr\", marketArrStr);\n```\n\n***\n\n## getAmmPoolConf\n\n```ts\nconst response = await LoopringAPI.ammpoolAPI.getAmmPoolConf();\nconsole.log(response.ammpools);\nconsole.log(response.pairs);\n```\n\n***\n\n## getAvailableBroker\n\n```ts\nconst result = await LoopringAPI.exchangeAPI.getAvailableBroker();\nconsole.log(result);\n```\n\n***\n\n## getTokenPrices\n\n```ts\nconst response = await LoopringAPI.walletAPI.getTokenPrices({\n  token: TOKEN_INFO.tokenMap.LRC.address,\n});\nconsole.log(response);\n```\n\n***\n\n## getLatestTokenPrices\n\n```ts\nconst response = await LoopringAPI.walletAPI.getLatestTokenPrices();\nconsole.log(response);\n```\n\n***\n\n## getLatestTokenPrices_cny\n\n```ts\nconst response = await LoopringAPI.walletAPI.getLatestTokenPrices({\n  currency: sdk.Currency.cny,\n});\nconsole.log(response);\n```\n\n***\n\n## getWithdrawalAgents\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getWithdrawalAgents({\n  tokenId: 1,\n  amount: \"10000000000\",\n});\nconsole.log(response);\n```\n\n***\n\n## getCandlestick\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getCandlestick({\n  market: \"LRC-ETH\",\n  interval: sdk.TradingInterval.min15,\n  limit: 96,\n});\nconsole.log(response);\n```\n\n***\n\n## getAccountServices\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getAccountServices({});\nconsole.log(response);\n```\n\n***\n\n## getExchangeFeeInfo\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getExchangeFeeInfo<any>();\nconsole.log(response);\nconsole.log(\n  response.raw_data[sdk.VipCatergory.ORDERBOOK_TRADING_FEES_STABLECOIN]\n);\n```\n\n***\n\n## getProtocolPortrait\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getProtocolPortrait();\nconsole.log(response);\n```\n\n***\n\n## getRecommendedMarkets\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getRecommendedMarkets();\nconsole.log(response);\n```\n\n***\n\n## getGasPrice\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getGasPrice();\nconsole.log(response);\n```\n\n***\n\n## getGasPriceRange\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getGasPriceRange();\nconsole.log(response);\n```\n\n***\n\n## getMarketTrades\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMarketTrades<any>({\n  market: \"ETH-USDT\",\n});\nconsole.log(response.raw_data.trades);\n```\n\n***\n\n## getRelayerCurrentTime\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getRelayerCurrentTime();\nconsole.log(response);\n```\n\n***\n\n## getFiatPriceUSD\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getFiatPrice({\n  legal: \"USD\",\n});\nconsole.log(response);\n```\n\n***\n\n## getFiatPriceCNY\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getFiatPrice({\n  legal: \"CNY\",\n});\nconsole.log(response);\n```\n\n***\n\n## getMarkets\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMarkets();\nconsole.log(response);\nconsole.log(response.pairs.LRC.tokenList);\n\nconsole.log(\n  \"hasMarket LRC-ETH:\",\n  sdk.hasMarket(response.marketArr, \"LRC-ETH\")\n);\nconsole.log(\n  \"market 1:\",\n  sdk.getExistedMarket(response.marketArr, \"LRC\", \"ETH\")\n);\nconsole.log(\n  \"market 2:\",\n  sdk.getExistedMarket(response.marketArr, \"ETH\", \"LRC\")\n);\n```\n\n***\n\n## getDepth\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getDepth({\n  market: \"LRC-ETH\",\n});\nconsole.log(response);\n```\n\n***\n\n## getTicker\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getTicker({\n  market: \"LRC-ETH\",\n});\nconsole.log(response);\n```\n\n***\n\n## getAllTickers\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getAllTickers();\nconsole.log(response);\n```\n\n***\n\n## getMixDepth\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMixDepth({\n  market: \"LRC-ETH\",\n});\nconsole.log(response);\nconsole.log(response.depth.bids);\n```\n\n***\n\n## getMixTicker\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMixTicker({\n  market: [\"LRC-ETH\", \"ETH-USDC\", \"DAI-USDT\"].join(\",\"),\n});\nconsole.log(response.tickMap[\"DAI-USDT\"]);\n```\n\n***\n\n## getAllMixTickers\n\n```ts\nconst response: any = await LoopringAPI.exchangeAPI.getAllMixTickers();\nconsole.log(response?.tickMap);\n```\n\n***\n\n## getMixCandlestickAMM\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMixCandlestick({\n  market: \"AMM-LRC-ETH\",\n  interval: sdk.TradingInterval.min15,\n  limit: 96,\n});\nconsole.log(response);\n```\n\n});\n"
  },
  {
    "path": "docs/js_sdk/exchange/webSocket.md",
    "content": "#WebSocket Command\nDefinition: Loopring L2 websocket\n\n### Loopring L2 websocket topic type:\nWsTopicType\n- `account`\n- `orderbook`\n- `mixorder`\n- `mixtrade`\n- `ticker`\n- `candlestick`\n- `ammpool`\n\n## getWsKey (required by account related socket)\n```ts \nconst response = await LoopringAPI.wsAPI.getWsKey();\nconsole.log(response);\n```\n## getOrderBookArg\n```ts\nconst arg1 = sdk.getMixOrderArg({ market: \"LRC-ETH\", level: 50 });\nconsole.log(arg1);\n\nconst arg2 = sdk.getOrderBookArg({\n  market: \"LRC-ETH\",\n  level: 50,\n  count: 40,\n  snapshot: false,\n});\nconsole.log(arg2);\n```"
  },
  {
    "path": "docs/js_sdk/transfer/transferERC20.md",
    "content": "# Transfer ERC20 \nDefinition: Send ERC20 tokens to other account on Loopring L2, \n> trade value should with decimals `sdk.toBig(value).times(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)`\n\n***\n## Step 1. get account Info\n    const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n    const LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo;\n\n```ts\nconst { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n```\n***\n## Step 2. get eddsaKey\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n***\n## Step 3. get apikey\n```ts\nconst { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst { userBalances } = await LoopringAPI.userAPI.getUserBalances(\n  { accountId: LOOPRING_EXPORTED_ACCOUNT.accountId, tokens: \"\" },\n  apiKey\n);\n```\n\n***\n## Step 4. get storageId\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n ```\n\n***\n## Step 5. get fee\n```ts\nconst fee = await LoopringAPI.userAPI.getOffchainFeeAmt({\n  accountId: accInfo.accountId,\n  requestType: sdk.OffchainFeeReqType.TRANSFER,\n}, apiKey);\nconsole.log(\"fee:\", fee);\n```\n***\n## Step 6. transfer\n```ts\nconst transferResult = await LoopringAPI.userAPI.submitInternalTransfer({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    payerAddr: accInfo.owner,\n    payerId: accInfo.accountId,\n    payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n    payeeId: LOOPRING_EXPORTED_ACCOUNT.accountId2,\n    storageId: storageId.offchainId,\n    token: {\n      tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n      volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n    },\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Trezor,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\nconsole.log(\"transferResult:\", transferResult);\n```"
  },
  {
    "path": "docs/js_sdk/transfer/transferNFT.md",
    "content": "# Transfer NFT\nDefinition: Send NFT to other account on Loopring L2\n\n***\n## Step 1. get account Info\n```ts\nconst { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\nconst LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo;\nconst { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\n```\n\n***\n## Step 2. get eddsaKey\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n## Step 3. get apiKey\n```ts\nconst { apiKey } = await LoopringAPI.userAPI.getUserApiKey({\n  accountId: accInfo.accountId}, eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst { userNFTBalances } = await LoopringAPI.userAPI.getUserNFTBalances(\n  { accountId: accInfo.accountId, limit: 20 },\n  apiKey\n);\n```\n \n***\n##Step 4. get storageId\n```ts  \nconst storageId = await LoopringAPI.userAPI.getNextStorageId({\n  accountId: accInfo.accountId,\n  sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n}, apiKey);\n```\n\n***\n## Step 5. get fee\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt({\n  accountId: accInfo.accountId,\n  requestType: sdk.OffchainNFTFeeReqType.NFT_TRANSFER,\n  amount: \"0\",\n}, apiKey);\nconsole.log(\"fee:\", fee);\n```\n\n***\n## Step 6. Transfer NFT\n```ts\nconst transferResult = await LoopringAPI.userAPI.submitNFTInTransfer({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    fromAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    fromAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n    toAccountId: 0, // toAccountId is not required, input 0 as default\n    toAddress: LOOPRING_EXPORTED_ACCOUNT.address2,\n    token: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    storageId: storageId.offchainId,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"transfer Result:\", transferResult);\n```"
  },
  {
    "path": "docs/js_sdk/withdraw/withdrawERC20.md",
    "content": "# Withdraw ERC20\n\nDefinition: Loopring L2 withdraw ERC20 to Ethereum L1,\n> trade value should with decimals `sdk.toBig(value).times(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)`\n\n***\n\n## Step 1. getAccount\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n```\n\n##Step 2.  eddsaKey\n\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey({\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n```\n\n***\n\n## Step 4. storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId({\n    accountId: accInfo.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n\n```\n\n***\n\n## Step 5. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getOffchainFeeAmt({\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.OFFCHAIN_WITHDRAWAL,\n    tokenSymbol: TOKEN_INFO.tokenMap[\"LRC\"].symbol,\n  },\n  apiKey\n);\nconsole.log(\"fee:\", fee);\n\n```\n\n***\n\n## Step 6. withdraw\n\n```ts\nconst response = await LoopringAPI.userAPI.submitOffchainWithdraw({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    counterFactualInfo: undefined,\n    fastWithdrawalMode: false,\n    hashApproved: \"\",\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    minGas: 0,\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address,\n    storageId: 0,\n    token: {\n      tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n      volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n    },\n    validUntil: 0,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.MetaMask,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"response:\", response);\n```"
  },
  {
    "path": "docs/js_sdk/withdraw/withdrawNFT.md",
    "content": "# Withdraw NFT\n\nDefinition:  Loopring L2 withdraw NFT to Ethereum L1\n\n***\n\n## Step 1. getAccount\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n```\n\n***\n\n## Step 2. eddsaKey\n\n```ts\n\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n```\n\n***\n\n## Step 3. apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n```\n\n***\n\n## Step 4. storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n\n//Step 5. getUserNFTBalances\nconst {userNFTBalances} = await LoopringAPI.userAPI.getUserNFTBalances(\n  {accountId: LOOPRING_EXPORTED_ACCOUNT.accountId},\n  apiKey\n);\nconst tokenInfo = userNFTBalances.find(\n  (item) =>\n    item.tokenAddress?.toLowerCase() ===\n    LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress.toLowerCase() &&\n    item.nftId &&\n    web3.utils.hexToNumberString(item.nftId) ===\n    LOOPRING_EXPORTED_ACCOUNT.nftTokenId.toString()\n);\n```\n\n***\n\n## Step 5. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_WITHDRAWAL,\n    tokenAddress:  LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    deployInWithdraw:\n      tokenInfo?.deploymentStatus === DEPLOYMENT_STATUS.NOT_DEPLOYED, // when token is not deploy the fee is diff\n  },\n  apiKey\n);\nconsole.log(\"fee:\", fee);\n```\n\n***\n\n## Step 6. withdraw\n\n```ts\nconst response = await LoopringAPI.userAPI.submitNFTWithdraw({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    counterFactualInfo: undefined,\n    hashApproved: \"\",\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    minGas: 0,\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address,\n    storageId: 0,\n    token: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    validUntil: 0,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.MetaMask,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"response:\", response);\n```"
  },
  {
    "path": "jest.config.cjs",
    "content": "module.exports = {\n  preset: 'ts-jest',\n  verbose: true,\n  transform: {\n    '^.+\\\\.(js|jsx|ts|tsx)$': './node_modules/babel-jest',\n  },\n  \"moduleNameMapper\": {\n    \"axios\": \"axios/dist/node/axios.cjs\"\n  },\n  \"transformIgnorePatterns\": [\"node_modules\\/(?!axios)\"]\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"@loopring-web/loopring-sdk\",\n  \"version\": \"3.9.23\",\n  \"author\": \"Loopring Dev Team\",\n  \"description\": \"Loopring SDK\",\n  \"license\": \"SEE LICENSE IN LICENSE\",\n  \"main\": \"dist/index.cjs\",\n  \"module\": \"dist/index.esm.js\",\n  \"types\": \"dist/index.d.ts\",\n  \"source\": \"src/index.ts\",\n  \"exports\": {\n    \"require\": \"./dist/index.cjs\",\n    \"import\": \"./dist/index.esm.js\"\n  },\n  \"files\": [\n    \"dist\",\n    \"!tests\",\n    \"!__snapshots__\",\n    \"!*.test.js\",\n    \"!*.test.js.map\",\n    \"!*.test.ts\",\n    \"!*.test.d.ts\"\n  ],\n  \"type\": \"module\",\n  \"prettier\": {\n    \"semi\": false,\n    \"tabWidth\": 2,\n    \"printWidth\": 100,\n    \"singleQuote\": true,\n    \"trailingComma\": \"all\",\n    \"jsxSingleQuote\": true,\n    \"bracketSpacing\": true\n  },\n  \"dependencies\": {\n    \"@ethereumjs/common\": \"^2.4.0\",\n    \"@ethereumjs/tx\": \"^3.3.0\",\n    \"@types/jsbn\": \"^1.2.30\",\n    \"axios\": \"^1.4.0\",\n    \"bignumber.js\": \"9.1.1\",\n    \"blake-hash\": \"^2.0.0\",\n    \"blake2b\": \"^2.1.3\",\n    \"bn.js\": \"^5.2.1\",\n    \"buffer\": \"^6.0.3\",\n    \"core-js\": \"3\",\n    \"crypto-js\": \"4.1.1\",\n    \"eth-sig-util\": \"2.3.0\",\n    \"ethereumjs-abi\": \"0.6.8\",\n    \"ethereumjs-util\": \"5.2.0\",\n    \"ethers\": \"^5.7.2\",\n    \"js-sha3\": \"^0.8.0\",\n    \"js-sha512\": \"^0.8.0\",\n    \"jsbn\": \"^1.1.0\",\n    \"multiformats\": \"^12.0.1\",\n    \"web-encoding\": \"^1.1.5\",\n    \"web3\": \"1.10.0\"\n  },\n  \"build\": {\n    \"files\": [\n      \"src/**/*\",\n      \"node_modules/**/*\"\n    ],\n    \"publish\": {\n      \"provider\": \"custom\",\n      \"repo\": \"https://github.com/Loopring/loopring_sdk\",\n      \"owner\": \"Loopring Dev Team\"\n    }\n  },\n  \"scripts\": {\n    \"build\": \"rimraf dist && NODE_ENV=production cross-env BABEL_ENV=prod rollup -c --bundleConfigAsCjs\",\n    \"start\": \"NODE_ENV=development rollup -c --bundleConfigAsCjs -w\",\n    \"test\": \"tsdx test\",\n    \"test_calc\": \"tsdx test\",\n    \"lint\": \"eslint . --fix --quiet --ext .ts\",\n    \"prepublishDev\": \"NODE_ENV=dev build build\",\n    \"prepublishOnly\": \"yarn build\",\n    \"doc\": \"typedoc --out docs/detail src\\\\/\",\n    \"proxy\": \"export http_proxy=http://127.0.0.1:1087;export https_proxy=http://127.0.0.1:1087;\",\n    \"build-book\": \"npx honkit build\",\n    \"cp-file-doc\": \"cp README.md ./docs/README.md;  cp Changelog.md ./docs/Changelog.md; \",\n    \"build-b\": \"npm run doc; npm run build-book\",\n    \"serve-book\": \"npx honkit serve\",\n    \"deploy-book\": \"gh-pages -d _book\"\n  },\n  \"browserslist\": {\n    \"production\": [\n      \"last 2 chrome version\",\n      \"last 2 firefox version\",\n      \"last 2 safari version\"\n    ],\n    \"development\": [\n      \"last 1 chrome version\",\n      \"last 1 firefox version\",\n      \"last 1 safari version\"\n    ]\n  },\n  \"lint-staged\": {\n    \"**/*\": \"prettier --write --ignore-unknown\"\n  },\n  \"devDependencies\": {\n    \"@babel/plugin-transform-optional-chaining\": \"^7.23.4\",\n    \"@babel/plugin-transform-typescript\": \"^7.14.6\",\n    \"@babel/preset-env\": \"^7.14.5\",\n    \"@babel/preset-typescript\": \"^7.14.5\",\n    \"@microsoft/tsdoc\": \"^0.13.2\",\n    \"@rollup/plugin-babel\": \"^6.0.3\",\n    \"@rollup/plugin-commonjs\": \"^25.0.2\",\n    \"@rollup/plugin-json\": \"^6.0.0\",\n    \"@rollup/plugin-node-resolve\": \"^15.1.0\",\n    \"@rollup/plugin-replace\": \"^5.0.2\",\n    \"@rollup/plugin-terser\": \"^0.4.4\",\n    \"@rollup/plugin-typescript\": \"^11.0.0\",\n    \"@types/bignumber.js\": \"^5.0.0\",\n    \"@types/blake2b\": \"^2.1.0\",\n    \"@types/classnames\": \"^2.2.11\",\n    \"@types/collections\": \"^5.1.2\",\n    \"@types/crypto-js\": \"^4.0.1\",\n    \"@types/eth-sig-util\": \"^2.1.0\",\n    \"@types/ethereumjs-abi\": \"^0.6.3\",\n    \"@types/ethereumjs-tx\": \"^2.0.0\",\n    \"@types/ethereumjs-util\": \"5.2.0\",\n    \"@types/jest\": \"^26.0.23\",\n    \"@types/lodash\": \"^4.14.168\",\n    \"@types/mocha\": \"^8.2.2\",\n    \"@types/ms\": \"^0.7.31\",\n    \"@types/node\": \"^12.0.0\",\n    \"@types/node-fetch\": \"^3.0.3\",\n    \"@types/request\": \"^2.48.6\",\n    \"@types/request-promise\": \"^4.1.48\",\n    \"@types/truffle-privatekey-provider\": \"^1.1.0\",\n    \"@typescript-eslint/eslint-plugin\": \"^4.6.0\",\n    \"@typescript-eslint/parser\": \"^4.6.0\",\n    \"async\": \"^3.2.0\",\n    \"babel-jest\": \"^26.6.3\",\n    \"babel-plugin-import\": \"^1.13.3\",\n    \"babel-plugin-transform-class-properties\": \"^6.24.1\",\n    \"babel-preset-env\": \"^1.7.0\",\n    \"chai\": \"^4.3.4\",\n    \"cross-env\": \"^7.0.3\",\n    \"gh-pages\": \"^3.2.3\",\n    \"honkit\": \"^3.6.20\",\n    \"jest\": \"^26.6.3\",\n    \"mocha\": \"^8.3.2\",\n    \"prettier\": \"2.8.8\",\n    \"request-promise\": \"^4.2.6\",\n    \"rimraf\": \"^5.0.1\",\n    \"rollup\": \"^3.25.3\",\n    \"rollup-plugin-typescript2\": \"^0.36.0\",\n    \"truffle-privatekey-provider\": \"1.5.0\",\n    \"ts-node\": \"^10.0.0\",\n    \"tslib\": \"^2.3.0\",\n    \"typedoc\": \"^0.22.9\",\n    \"typedoc-plugin-markdown\": \"^3.11.7\",\n    \"typescript\": \"^5.1.3\"\n  }\n}\n"
  },
  {
    "path": "rollup.config.mjs",
    "content": "import commonjs from '@rollup/plugin-commonjs';\nimport babel from '@rollup/plugin-babel'\nimport terser from '@rollup/plugin-terser'\nimport json from '@rollup/plugin-json';\nimport { nodeResolve } from '@rollup/plugin-node-resolve';\nimport typescript from 'rollup-plugin-typescript2';\nimport { builtinModules } from 'module';\nimport pkg from  './package.json'  assert { type: \"json\" };\n// console.log('pkg',pkg)\nmodule.exports = {\n  input: pkg.source,\n  output: [\n    { file:pkg.main  , format: 'cjs', sourcemap: true, plugins: [terser()], },\n    { file: pkg.module , format: 'esm', sourcemap: true, plugins: [terser()], }\n  ],\n  external: [\n    ...builtinModules,\n    ...(pkg.dependencies ? Object.keys(pkg.dependencies) : []),\n    ...(pkg.devDependencies ? Object.keys(pkg.devDependencies) : []),\n    ...(pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : [])\n  ],\n  watch: {\n    include: 'src/**',\n  },\n  plugins: [\n    json(),\n    typescript({\n          abortOnError: process.env.NODE_ENV === 'production',\n          tsconfig:'./tsconfig.json',\n          tsconfigDefaults: {\n            exclude: [\n              // all TS test files, regardless whether co-located or in test/ etc\n              '**/*.spec.ts',\n              '**/*.test.ts',\n              '**/*.spec.ts',\n              '**/*.test.ts',\n              // TS defaults below\n              'node_modules',\n              'bower_components',\n              'jspm_packages',\n            ],\n            compilerOptions: {\n              sourceMap: true,\n              declaration: true,\n              jsx: 'react',\n            },\n          },\n          tsconfigOverride: {\n            compilerOptions: Object.assign({\n              // TS -> esnext, then leave the rest to babel-preset-env\n              target: 'esnext' }, { declaration: true, declarationMap: true }),\n          },\n        }\n    ),\n    commonjs() ,\n    nodeResolve({\n      exportConditions: ['import', 'default', 'require'],\n      mainFields: ['module', 'main', 'browser'],\n      modulesOnly: true,\n      preferBuiltins: false,\n    }),\n    babel({\n      babelHelpers: 'bundled',\n      include: ['src/**/*.ts'],\n      exclude: './node_modules/**',\n    }),\n  ]\n};\n"
  },
  {
    "path": "src/api/ammpool_api.ts",
    "content": "/* eslint-disable camelcase  */\nimport { BaseAPI } from './base_api'\nimport * as loopring_defs from '../defs'\n\nimport { LOOPRING_URLs } from '../defs'\n\nimport * as sign_tools from './sign/sign_tools'\nimport { makeAmmPool } from '../utils'\n\nexport class AmmpoolAPI extends BaseAPI {\n  /*\n   * Returns the fee rate of users placing orders in specific markets\n   */\n  public async getAmmPoolConf<R>(): Promise<{\n    raw_data: R\n    ammpools: loopring_defs.LoopringMap<loopring_defs.AmmPoolInfoV3>\n    pairs: loopring_defs.LoopringMap<loopring_defs.TokenRelatedInfo>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: LOOPRING_URLs.GET_AMM_POOLS_CONF,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const { ammpools, pairs } = makeAmmPool(raw_data)\n    // if (raw_data.code) {\n    //   return {\n    //     ...raw_data,\n    //   };\n    // }\n\n    return {\n      ammpools,\n      pairs,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolUserRewards<R>(request: loopring_defs.GetAmmUserRewardsRequest): Promise<{\n    raw_data: R\n    ammUserRewardMap: loopring_defs.AmmUserRewardMap\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_AMMPOOL_REWARDS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const ammUserRewardMap: loopring_defs.AmmUserRewardMap = {}\n\n    if (raw_data?.current) {\n      raw_data?.current.forEach((item: loopring_defs.AmmUserReward) => {\n        ammUserRewardMap[item.market] = {\n          current: item,\n          lastDay: undefined,\n        }\n      })\n    }\n    if (raw_data?.lastDay) {\n      raw_data?.lastDay.forEach((item: loopring_defs.AmmUserReward) => {\n        ammUserRewardMap[item.market] = {\n          ...ammUserRewardMap[item.market],\n          lastDay: item,\n        }\n      })\n    }\n\n    return {\n      ammUserRewardMap,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolGameRank<R>(request: loopring_defs.GetAmmPoolGameRankRequest): Promise<{\n    raw_data: R\n    totalRewards: loopring_defs.TokenVolumeV3[]\n    userRankList: loopring_defs.GameRankInfo[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_AMMPOOL_GAME_RANK,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const totalRewards: loopring_defs.TokenVolumeV3[] = raw_data?.totalRewards\n      ? raw_data.totalRewards\n      : []\n\n    const userRankList: loopring_defs.GameRankInfo[] = raw_data?.userRankList\n      ? raw_data.userRankList\n      : []\n\n    return {\n      totalRewards,\n      userRankList,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolGameUserRank<R>(\n    request: loopring_defs.GetAmmPoolGameUserRankRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    userRank: loopring_defs.GameRankInfo\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      apiKey,\n      url: LOOPRING_URLs.GET_AMMPOOL_GAME_USER_RANK,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    const userRank: loopring_defs.GameRankInfo = raw_data.data\n\n    return {\n      userRank,\n      raw_data: raw_data.data,\n    }\n  }\n\n  private getOrderList(lst: loopring_defs.AmmPoolActivityRule[], order: loopring_defs.SortOrder) {\n    return lst.sort(\n      (a: loopring_defs.AmmPoolActivityRule, b: loopring_defs.AmmPoolActivityRule) => {\n        if (order === loopring_defs.SortOrder.ASC) {\n          return a.rangeFrom < b.rangeFrom ? 1 : 0\n        }\n\n        return a.rangeFrom > b.rangeFrom ? 1 : 0\n      },\n    )\n  }\n\n  /*\n   */\n  public async getAmmPoolActivityRules<R>(): Promise<{\n    raw_data: R\n    activityInProgressRules: loopring_defs.LoopringMap<loopring_defs.AmmPoolInProgressActivityRule>\n    activityDateMap: loopring_defs.LoopringMap<{\n      AMM_MINING?: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule>\n      ORDERBOOK_MINING?: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule>\n      SWAP_VOLUME_RANKING?: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule>\n    }>\n    groupByRuleType: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule[]>\n    groupByActivityStatus: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule[]>\n    groupByRuleTypeAndStatus: loopring_defs.LoopringMap<\n      loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule[]>\n    >\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: LOOPRING_URLs.GET_AMM_ACTIVITY_RULES,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    let activityInProgressRules: loopring_defs.LoopringMap<loopring_defs.AmmPoolInProgressActivityRule> =\n      {}\n    const activityDateMap: loopring_defs.LoopringMap<{\n      AMM_MINING?: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule>\n      ORDERBOOK_MINING?: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule>\n      SWAP_VOLUME_RANKING?: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule>\n    }> = {}\n    //{AMM_MINING:{},ORDERBOOK_MINING:{},SWAP_VOLUME_RANKING:{}}\n\n    const groupByRuleType: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule[]> = {}\n\n    let groupByRuleTypeAndStatus: loopring_defs.LoopringMap<\n      loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule[]>\n    > = {}\n\n    const groupByActivityStatus: loopring_defs.LoopringMap<loopring_defs.AmmPoolActivityRule[]> = {}\n\n    const currentTs = new Date().getTime()\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.AmmPoolActivityRule) => {\n        const status =\n          currentTs < item.rangeFrom\n            ? loopring_defs.AmmPoolActivityStatus.NotStarted\n            : currentTs >= item.rangeFrom && currentTs <= item.rangeTo\n            ? loopring_defs.AmmPoolActivityStatus.InProgress\n            : loopring_defs.AmmPoolActivityStatus.EndOfGame\n\n        item.status = status\n        if (status === loopring_defs.AmmPoolActivityStatus.InProgress) {\n          const ruleType = activityInProgressRules[item.market]\n            ? [...activityInProgressRules[item.market].ruleType, item.ruleType]\n            : [item.ruleType]\n          activityInProgressRules = {\n            ...activityInProgressRules,\n            [item.market]: { ...item, ruleType },\n          }\n        }\n        groupByRuleType[item.ruleType] = [\n          ...(groupByRuleType[item.ruleType] ? groupByRuleType[item.ruleType] : []),\n          item,\n        ]\n        groupByActivityStatus[status] = [\n          ...(groupByActivityStatus[status] ? groupByActivityStatus[status] : []),\n          item,\n        ]\n        activityDateMap[item.rangeFrom] = {\n          ...(activityDateMap[item.rangeFrom] ? activityDateMap[item.rangeFrom] : {}),\n          [item.ruleType]: {\n            ...(activityDateMap[item.rangeFrom]\n              ? activityDateMap[item.rangeFrom][item.ruleType]\n                ? activityDateMap[item.rangeFrom][item.ruleType]\n                : {}\n              : {}),\n            [item.market]: item,\n          },\n        }\n        groupByRuleTypeAndStatus = {\n          ...groupByRuleTypeAndStatus,\n          [item.ruleType]: {\n            ...(groupByRuleTypeAndStatus[item.ruleType]\n              ? groupByRuleTypeAndStatus[item.ruleType]\n              : {}),\n            [status]: [\n              ...(groupByRuleTypeAndStatus[item.ruleType]\n                ? groupByRuleTypeAndStatus[item.ruleType][status]\n                  ? groupByRuleTypeAndStatus[item.ruleType][status]\n                  : []\n                : []),\n              item,\n            ],\n          },\n        }\n      })\n    }\n\n    return {\n      activityInProgressRules,\n      activityDateMap,\n      groupByRuleType,\n      groupByActivityStatus,\n      groupByRuleTypeAndStatus,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmAssetHistory<R>(request: loopring_defs.GetAmmAssetRequest): Promise<{\n    raw_data: R\n    poolAddress: string\n    market: string\n    dataSeries: any\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_AMM_ASSET_HISTORY,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const poolAddress = raw_data.poolAddress\n    const market = raw_data.market\n    const dataSeries = raw_data.data\n\n    return {\n      poolAddress,\n      market,\n      dataSeries,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolStats<R>(): Promise<{\n    raw_data: R\n    ammPoolStats: loopring_defs.LoopringMap<loopring_defs.AmmPoolStat>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: LOOPRING_URLs.GET_AMM_POOL_STATS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    const ammPoolStats: loopring_defs.LoopringMap<loopring_defs.AmmPoolStat> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.AmmPoolStat) => {\n        ammPoolStats[item.market] = item\n      })\n    }\n\n    return {\n      ammPoolStats,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolSnapshot<R>(request: loopring_defs.GetAmmPoolSnapshotRequest): Promise<{\n    raw_data: R\n    ammPoolSnapshot: loopring_defs.AmmPoolSnapshot\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: LOOPRING_URLs.GET_AMM_POOLS_SNAPSHOT,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const ammPoolSnapshot: loopring_defs.AmmPoolSnapshot = raw_data\n\n    return {\n      ammPoolSnapshot,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolBalances<R>(): Promise<{\n    raw_data: R\n    ammpoolsbalances: loopring_defs.LoopringMap<loopring_defs.AmmPoolBalance>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: LOOPRING_URLs.GET_AMM_POOLS_BALANCES,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const ammpoolsbalances: loopring_defs.LoopringMap<loopring_defs.AmmPoolBalance> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: any) => {\n        const tempPooled: any = {}\n\n        if (item?.pooled instanceof Array) {\n          item.pooled.forEach((item2: any) => {\n            tempPooled[item2.tokenId] = item2\n          })\n        }\n\n        item.pooledMap = tempPooled\n\n        let poolName = item.poolName\n        if (poolName.indexOf('LRCETH') >= 0) {\n          poolName = 'AMM-LRC-ETH'\n        }\n\n        ammpoolsbalances[poolName] = item\n      })\n    }\n\n    return {\n      ammpoolsbalances,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getLiquidityMining<R>(\n    request: loopring_defs.GetLiquidityMiningRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    rewards: loopring_defs.RewardItem[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      apiKey,\n      url: LOOPRING_URLs.GET_LIQUIDITY_MINING,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      rewards: raw_data?.data ? (raw_data.data as loopring_defs.RewardItem[]) : [],\n\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getLiquidityMiningUserHistory<R>(\n    request: loopring_defs.GetLiquidityMiningUserHistoryRequest,\n  ): Promise<{\n    raw_data: R\n    userMiningInfos: loopring_defs.UserMiningInfo[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n\n      url: LOOPRING_URLs.GET_LIQUIDITY_MINING_USER_HISTORY,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      userMiningInfos: raw_data.data as loopring_defs.UserMiningInfo[],\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getUserAmmPoolTxs<R>(\n    request: loopring_defs.GetUserAmmPoolTxsRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userAmmPoolTxs: loopring_defs.UserAmmPoolTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      apiKey,\n      url: LOOPRING_URLs.GET_USER_AMM_POOL_TXS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      totalNum: raw_data.totalNum,\n      userAmmPoolTxs: raw_data.transactions as loopring_defs.UserAmmPoolTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolTxs<R>(request: loopring_defs.GetAmmPoolTxsRequest): Promise<{\n    raw_data: R\n    totalNum: number\n    transactions: loopring_defs.AmmPoolTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_AMM_POOL_TXS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    let transactions = undefined\n\n    if (raw_data?.transactions) {\n      transactions = raw_data?.transactions\n    }\n\n    return {\n      totalNum: raw_data.totalNum,\n      transactions: transactions as loopring_defs.AmmPoolTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getAmmPoolTrades<R>(request: loopring_defs.GetAmmPoolTradesRequest): Promise<{\n    raw_data: R\n    totalNum: number\n    ammPoolTrades: loopring_defs.AmmPoolTrade[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_AMM_POOL_TRADE_TXS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data.totalNum,\n      ammPoolTrades: raw_data.transactions as loopring_defs.AmmPoolTrade[],\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async joinAmmPool<R>(\n    request: loopring_defs.JoinAmmPoolRequest,\n    patch: loopring_defs.AmmPoolRequestPatch,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    joinAmmPoolResult: loopring_defs.JoinAmmPoolResult\n  }> {\n    if (!request?.validUntil) request.validUntil = Date.now()\n\n    const reqParams: loopring_defs.ReqParams = {\n      bodyParams: request,\n      apiKey,\n      url: LOOPRING_URLs.POST_JOIN_AMM_POOL,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const { eddsaSig } = sign_tools.get_EddsaSig_JoinAmmPool(request, patch)\n\n    request.eddsaSignature = eddsaSig\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      joinAmmPoolResult: raw_data as loopring_defs.JoinAmmPoolResult,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async exitAmmPool<R>(\n    request: loopring_defs.ExitAmmPoolRequest,\n    patch: loopring_defs.AmmPoolRequestPatch,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    exitAmmPoolResult: loopring_defs.ExitAmmPoolResult\n  }> {\n    if (!request?.validUntil) request.validUntil = Date.now()\n\n    const reqParams: loopring_defs.ReqParams = {\n      bodyParams: request,\n      apiKey,\n      url: LOOPRING_URLs.POST_EXIT_AMM_POOL,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const { eddsaSig } = sign_tools.get_EddsaSig_ExitAmmPool(request, patch)\n\n    request.eddsaSignature = eddsaSig\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      exitAmmPoolResult: raw_data as loopring_defs.ExitAmmPoolResult,\n      raw_data,\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/base_api.ts",
    "content": "import * as loopring_defs from '../defs'\nimport { Request } from './request'\nimport { addHexPrefix, toBuffer, toHex } from '../utils'\nimport { myLog } from '../utils/log_tools'\nimport { contracts as abi } from './ethereum/contracts'\nimport { AxiosResponse } from 'axios'\nimport * as ethUtil from 'ethereumjs-util'\nimport { isContract } from './contract_api'\nimport { getWindowSafely } from 'utils/window_utils'\n\nexport const KEY_MESSAGE =\n  'Sign this message to access Loopring Exchange: ' +\n  '${exchangeAddress}' +\n  ' with key nonce: ' +\n  '${nonce}'\nexport class BaseAPI {\n  static KEY_MESSAGE: string = KEY_MESSAGE\n  protected baseUrl = ''\n  protected chainId: loopring_defs.ChainId = loopring_defs.ChainId.MAINNET\n  public genErr(err: Error | (AxiosResponse & Error)): loopring_defs.RESULT_INFO {\n    if (err.hasOwnProperty('request')) {\n      // const axiosError = errorInfo as AxiosResponse;\n      return {\n        // @ts-ignore;\n        message: loopring_defs.ConnectorError.HTTP_ERROR,\n        ...err,\n        msg: loopring_defs.ConnectorError.HTTP_ERROR,\n        code: loopring_defs.LoopringErrorCode.HTTP_ERROR,\n      } as loopring_defs.RESULT_INFO\n      err?.message\n    } else if (!err || !err?.message) {\n      return {\n        message: 'unKnown',\n        code: loopring_defs.LoopringErrorCode.SKD_UNKNOW,\n      }\n    } else {\n      const key = Reflect.ownKeys(loopring_defs.ConnectorError).find(\n        (key) =>\n          err?.message.search(\n            loopring_defs.ConnectorError[key as keyof typeof loopring_defs.ConnectorError],\n          ) !== -1,\n      )\n      if (key) {\n        return {\n          ...err,\n          message: key as keyof typeof loopring_defs.ConnectorError,\n          code: loopring_defs.LoopringErrorCode[key as keyof typeof loopring_defs.ConnectorError],\n        } as loopring_defs.RESULT_INFO\n      }\n      return {\n        ...(err instanceof Error\n          ? Reflect.ownKeys(err).reduce((prev, item) => {\n              // @ts-ignore\n              return { ...prev, [item]: err[item.toString()] }\n            }, {})\n          : err),\n        code: loopring_defs.LoopringErrorCode.SKD_UNKNOW,\n      }\n    }\n  }\n  protected returnTxHash<T extends loopring_defs.TX_HASH_API>(\n    raw_data: T,\n  ): (Omit<T, 'resultInfo'> & { raw_data: Omit<T, 'resultInfo'> }) | loopring_defs.RESULT_INFO {\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data.resultInfo,\n        message: raw_data.resultInfo?.msg ? raw_data.resultInfo?.msg : raw_data?.resultInfo.message,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  private timeout: number\n  private baseUrlMap: { [key: number]: string } | undefined\n\n  public constructor(\n    param: InitParam,\n    timeout: number = 6000,\n    baseUrlMap = {\n      [loopring_defs.ChainId.MAINNET]: 'https://api3.loopring.io',\n      [loopring_defs.ChainId.GOERLI]: 'https://uat2.loopring.io',\n    },\n  ) {\n    if (param.baseUrl) {\n      this.baseUrl = param.baseUrl\n    } else if (param.chainId !== undefined) {\n      this.setChainId(param.chainId)\n    } else {\n      this.setChainId(loopring_defs.ChainId.GOERLI)\n    }\n    this.baseUrlMap = baseUrlMap\n    this.timeout = timeout\n  }\n\n  public async getAvailableBroker(\n    request: loopring_defs.GetAvailableBrokerRequest,\n  ): Promise<{ broker: string }> {\n    const reqParams: loopring_defs.ReqParams = {\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      queryParams: request,\n      url: loopring_defs.LOOPRING_URLs.GET_AVAILABLE_BROKER,\n      method: loopring_defs.ReqMethod.GET,\n    }\n    const result = (await this.makeReq().request(reqParams)).data\n    return result\n  }\n\n  public async getCounterFactualInfo<T extends any>(\n    request: loopring_defs.GetCounterFactualInfoRequest,\n  ): Promise<{\n    raw_data: T\n    counterFactualInfo: loopring_defs.CounterFactualInfo | undefined\n    error?: loopring_defs.RESULT_INFO\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.COUNTER_FACTUAL_INFO,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    let counterFactualInfo: loopring_defs.CounterFactualInfo | undefined\n    let error: loopring_defs.RESULT_INFO | undefined = undefined\n\n    if (raw_data && raw_data?.resultInfo) {\n      error = raw_data?.resultInfo\n    } else {\n      counterFactualInfo = {\n        ...raw_data,\n      } as loopring_defs.CounterFactualInfo\n    }\n\n    return {\n      counterFactualInfo,\n      error,\n      raw_data,\n    }\n  }\n\n  public setChainId(chainId: loopring_defs.ChainId) {\n    this.baseUrl =\n      this.baseUrlMap && this.baseUrlMap[0]\n        ? getBaseUrlByChainId(chainId, this.baseUrlMap as any)\n        : getBaseUrlByChainId(chainId)\n    this.chainId = chainId\n  }\n\n  public setBaseUrl(baseUrl: string) {\n    this.baseUrl = baseUrl\n  }\n\n  protected makeReq(): Request {\n    return new Request(this.baseUrl, this.timeout)\n  }\n}\n\nexport function ecRecover(\n  account: string,\n  msg: string,\n  sig: any,\n  // time = 3000\n) {\n  try {\n    // let timer;\n    const hash = ethUtil.hashPersonalMessage(toBuffer(msg))\n    const signature = ethUtil.fromRpcSig(sig)\n    const result = ethUtil.ecrecover(hash, signature.v, signature.r, signature.s)\n    const result2 = ethUtil.pubToAddress(result)\n    const recAddress = toHex(result2)\n    myLog('ecRecover recAddress', result, result2, recAddress)\n    return {\n      result: recAddress.toLowerCase() === account.toLowerCase(),\n    }\n  } catch (error) {\n    return { error }\n  }\n}\n\nexport async function contractWalletValidate32(web3: any, account: string, msg: string, sig: any) {\n  return new Promise((resolve) => {\n    const hash = ethUtil.hashPersonalMessage(toBuffer(msg))\n    const data = abi.Contracts.ContractWallet.encodeInputs('isValidSignature(bytes32,bytes)', {\n      _data: hash,\n      _signature: toBuffer(sig),\n    })\n\n    web3.eth.call(\n      {\n        to: account, // contract addr\n        data: data,\n      },\n      function (err: any, result: any) {\n        if (!err) {\n          const valid = abi.Contracts.ContractWallet.decodeOutputs(\n            'isValidSignature(bytes32,bytes)',\n            result,\n          )\n          resolve({\n            result: toHex(toBuffer(valid[0])) === data.slice(0, 10),\n          })\n        } else resolve({ error: err })\n      },\n    )\n  })\n}\n\nexport async function mykeyWalletValid(web3: any, account: string, msg: string, sig: any) {\n  const myKeyContract = '0xADc92d1fD878580579716d944eF3460E241604b7'\n  return new Promise((resolve) => {\n    web3.eth.call(\n      {\n        to: myKeyContract,\n        data: abi.Contracts.ContractWallet.encodeInputs('getKeyData', {\n          _account: account,\n          _index: 3,\n        }),\n      },\n      function (err: any, res: any) {\n        if (!err) {\n          const signature = ethUtil.fromRpcSig(sig)\n          const hash = ethUtil.hashPersonalMessage(ethUtil.keccak256(toBuffer(msg)))\n          const address = addHexPrefix(\n            abi.Contracts.ContractWallet.decodeOutputs('getKeyData', res)[0],\n          )\n          const recAddress = toHex(\n            ethUtil.pubToAddress(ethUtil.ecrecover(hash, signature.v, signature.r, signature.s)),\n          )\n          resolve({\n            result: recAddress.toLowerCase() === address.toLowerCase(),\n          })\n        } else {\n          resolve({ error: err })\n        }\n      },\n    )\n  })\n}\n\nexport async function ecRecover2(account: string, message: string, signature: any) {\n  const messageBuffer = Buffer.from(message, 'utf8')\n  signature = signature.split('x')[1]\n\n  const parts = [\n    Buffer.from(`\\x19Ethereum Signed Message:\\n${messageBuffer.length}`, 'utf8'),\n    messageBuffer,\n  ]\n\n  const totalHash = ethUtil.keccak(Buffer.concat(parts))\n\n  const r = Buffer.from(signature.substring(0, 64), 'hex')\n  const s = Buffer.from(signature.substring(64, 128), 'hex')\n\n  const old_v = Number(addHexPrefix(signature.substring(128, 130)))\n\n  let v = old_v\n\n  if (v <= 1) v += 27\n\n  const pub = ethUtil.ecrecover(totalHash, v, r, s)\n\n  const recoveredAddress = '0x' + ethUtil.pubToAddress(pub).toString('hex')\n\n  // if (account.toLowerCase() !== recoveredAddress.toLowerCase()) {\n  //   myLog('v:', v, 'old_v:', old_v, ' recoveredAddress:', recoveredAddress)\n  // }\n\n  return new Promise((resolve) =>\n    resolve({\n      result: account.toLowerCase() === recoveredAddress.toLowerCase(),\n    }),\n  )\n}\n\nconst getBaseUrlByChainId = (\n  id: loopring_defs.ChainId,\n  baseUrlMap = {\n    [loopring_defs.ChainId.MAINNET]: 'https://api3.loopring.io',\n    [loopring_defs.ChainId.GOERLI]: 'https://uat2.loopring.io',\n  },\n) => {\n  let baseUrl = ''\n  switch (id) {\n    case loopring_defs.ChainId.MAINNET:\n      baseUrl = baseUrlMap[loopring_defs.ChainId.MAINNET]\n      break\n    default:\n      baseUrl = baseUrlMap[loopring_defs.ChainId.GOERLI]\n      break\n  }\n  return baseUrl\n}\n/**\n * @default chainId 1\n * @default keySeed `Sign this message to access Loopring exchange: ${exchangeAddress} with key nonce: ${nonce}`\n */\nexport interface InitParam {\n  chainId?: loopring_defs.ChainId\n  baseUrl?: string\n}\n\nexport function formatSig(rpcSig: string) {\n  const sig = ethUtil.fromRpcSig(rpcSig)\n  return ethUtil.toRpcSig(sig.v, sig.r, sig.s)\n}\nexport function recoverSignType(web3: any, account: string, msg: string, sig: string) {\n  const ethRecover: any = ecRecover(account, msg, sig)\n\n  if (ethRecover.result) {\n    return '03'\n  } else {\n    return ''\n  }\n}\n\nexport async function personalSign(\n  web3: any,\n  account: string | undefined,\n  pwd: string,\n  msg: string,\n  walletType: loopring_defs.ConnectorNames,\n  chainId: loopring_defs.ChainId,\n  accountId?: number,\n  counterFactualInfo?: loopring_defs.CounterFactualInfo,\n  isMobile?: boolean,\n) {\n  if (!account) {\n    return { error: 'personalSign got no account' }\n  }\n  return new Promise((resolve) => {\n    try {\n      web3.eth.personal.sign(msg, account, pwd, async function (err: any, result: any) {\n        if (!err) {\n          // LOG: for signature\n          myLog('ecRecover before', 'msg', msg, 'result', result, counterFactualInfo)\n          // Valid:1. counter Factual signature Valid\n          if (counterFactualInfo && accountId) {\n            myLog('fcWalletValid counterFactualInfo accountId:')\n            const fcValid = await fcWalletValid(\n              web3,\n              account,\n              msg,\n              result,\n              accountId,\n              chainId,\n              counterFactualInfo,\n            )\n            if (fcValid.result) {\n              resolve({\n                sig: result,\n                counterFactualInfo: fcValid.counterFactualInfo,\n              })\n              return\n            }\n          }\n\n          // Valid: 2. webview directory signature Valid\n          myLog('ecRecover before', result)\n          const valid: any = ecRecover(account, msg, result)\n          myLog('ecRecover after', valid.result)\n          if (valid.result) {\n            return resolve({ sig: result })\n          } else {\n            myLog('ecRecover error', valid)\n          }\n\n          // Valid: 3. contractWallet no recover\n          // signature Valid `isValidSignature(bytes32,bytes)`\n          // LOG: for signature\n          myLog('Valid: 3. contractWallet before')\n          const isContractCheck = await isContract(web3, account)\n          if (isContractCheck) {\n            // LOG: for signature\n            myLog('Valid: 5 failed isContract. no ecrecover')\n            return resolve({ sig: result })\n          }\n\n          // Valid: 5. contractWallet signature Valid `isValidSignature(bytes32,bytes)`\n          // const walletValid2: any = await contractWalletValidate32(\n          //   web3,\n          //   account,\n          //   msg,\n          //   result\n          // );\n          // if (walletValid2.result) {\n          //   return resolve({ sig: result });\n          // }\n\n          // Valid: 6. counter Factual signature Valid when no counterFactualInfo\n          if (accountId) {\n            const fcValid = await fcWalletValid(web3, account, msg, result, accountId, chainId)\n            if (fcValid.result) {\n              return resolve({\n                sig: result,\n                counterFactualInfo: fcValid.counterFactualInfo,\n              })\n            }\n          }\n\n          // Valid: 7. myKeyValid Valid again\n          const myKeyValid: any = await mykeyWalletValid(web3, account, msg, result)\n\n          if (myKeyValid.result) {\n            return resolve({ sig: result })\n          }\n\n          // Valid: Error cannot pass personalSign Valid\n          // eslint-disable-next-line no-console\n          console.log('web3.eth.personal.sign Valid, valid 5 ways, all failed!')\n          return resolve({\n            error: 'web3.eth.personal.sign Valid, valid 5 ways, all failed!',\n          })\n        } else {\n          return resolve({\n            error: 'personalSign err before Validate:' + err,\n          })\n        }\n      })\n    } catch (err) {\n      // LOG: for signature\n      myLog('personalSign callback err', (err as unknown as any)?.message)\n      resolve({ error: err as any })\n    }\n  })\n}\n\nexport async function fcWalletValid(\n  web3: any,\n  account: string,\n  msg: string,\n  result: any,\n  accountId: number,\n  chainId: loopring_defs.ChainId,\n  counterFactualInfo?: loopring_defs.CounterFactualInfo,\n): Promise<{\n  counterFactualInfo?: loopring_defs.CounterFactualInfo\n  error?: any\n  result?: boolean\n}> {\n  const api = new BaseAPI({ chainId })\n  if (counterFactualInfo === undefined || !counterFactualInfo.walletOwner) {\n    // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n    // @ts-ignore\n    counterFactualInfo = (await api.getCounterFactualInfo({ accountId })).counterFactualInfo\n  }\n\n  if (counterFactualInfo && counterFactualInfo.walletOwner) {\n    let _result: string\n    if (result.startsWith('0x')) {\n      _result = result.slice(0, 132)\n    } else {\n      _result = result\n    }\n\n    const valid: any = ecRecover(counterFactualInfo.walletOwner, msg, _result)\n    if (valid.result) {\n      myLog('fcWalletValid e:', result, counterFactualInfo)\n      return { result, counterFactualInfo }\n    } else {\n      return { error: 'valid walletOwner failed' }\n    }\n  } else {\n    return { error: 'valid walletOwner failed' }\n  }\n}\n"
  },
  {
    "path": "src/api/config/abis/contractWallet.ts",
    "content": "export const contractWallet = [\n  {\n    inputs: [\n      {\n        internalType: 'bytes',\n        name: '_data',\n        type: 'bytes',\n      },\n      {\n        internalType: 'bytes',\n        name: '_signature',\n        type: 'bytes',\n      },\n    ],\n    name: 'isValidSignature',\n    outputs: [\n      {\n        internalType: 'bytes4',\n        name: 'magicValue',\n        type: 'bytes4',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'bytes',\n        name: '_data',\n        type: 'bytes32',\n      },\n      {\n        internalType: 'bytes',\n        name: '_signature',\n        type: 'bytes',\n      },\n    ],\n    name: 'isValidSignature',\n    outputs: [\n      {\n        internalType: 'bytes4',\n        name: 'magicValue',\n        type: 'bytes4',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    constant: true,\n    inputs: [\n      {\n        name: '_account',\n        type: 'address',\n      },\n      {\n        name: '_index',\n        type: 'uint256',\n      },\n    ],\n    name: 'getKeyData',\n    outputs: [\n      {\n        name: '',\n        type: 'address',\n      },\n    ],\n    payable: false,\n    stateMutability: 'view',\n    type: 'function',\n  },\n]\n"
  },
  {
    "path": "src/api/config/abis/erc1155.ts",
    "content": "export const erc1155 = [\n  {\n    inputs: [\n      {\n        internalType: 'string',\n        name: 'uri_',\n        type: 'string',\n      },\n    ],\n    stateMutability: 'nonpayable',\n    type: 'constructor',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'account',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n      {\n        indexed: false,\n        internalType: 'bool',\n        name: 'approved',\n        type: 'bool',\n      },\n    ],\n    name: 'ApprovalForAll',\n    type: 'event',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        indexed: false,\n        internalType: 'uint256[]',\n        name: 'ids',\n        type: 'uint256[]',\n      },\n      {\n        indexed: false,\n        internalType: 'uint256[]',\n        name: 'values',\n        type: 'uint256[]',\n      },\n    ],\n    name: 'TransferBatch',\n    type: 'event',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        indexed: false,\n        internalType: 'uint256',\n        name: 'id',\n        type: 'uint256',\n      },\n      {\n        indexed: false,\n        internalType: 'uint256',\n        name: 'value',\n        type: 'uint256',\n      },\n    ],\n    name: 'TransferSingle',\n    type: 'event',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: false,\n        internalType: 'string',\n        name: 'value',\n        type: 'string',\n      },\n      {\n        indexed: true,\n        internalType: 'uint256',\n        name: 'id',\n        type: 'uint256',\n      },\n    ],\n    name: 'URI',\n    type: 'event',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'bytes4',\n        name: 'interfaceId',\n        type: 'bytes4',\n      },\n    ],\n    name: 'supportsInterface',\n    outputs: [\n      {\n        internalType: 'bool',\n        name: '',\n        type: 'bool',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'uri',\n    outputs: [\n      {\n        internalType: 'string',\n        name: '',\n        type: 'string',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'account',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256',\n        name: 'id',\n        type: 'uint256',\n      },\n    ],\n    name: 'balanceOf',\n    outputs: [\n      {\n        internalType: 'uint256',\n        name: '',\n        type: 'uint256',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address[]',\n        name: 'accounts',\n        type: 'address[]',\n      },\n      {\n        internalType: 'uint256[]',\n        name: 'ids',\n        type: 'uint256[]',\n      },\n    ],\n    name: 'balanceOfBatch',\n    outputs: [\n      {\n        internalType: 'uint256[]',\n        name: '',\n        type: 'uint256[]',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n      {\n        internalType: 'bool',\n        name: 'approved',\n        type: 'bool',\n      },\n    ],\n    name: 'setApprovalForAll',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'account',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n    ],\n    name: 'isApprovedForAll',\n    outputs: [\n      {\n        internalType: 'bool',\n        name: '',\n        type: 'bool',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256',\n        name: 'id',\n        type: 'uint256',\n      },\n      {\n        internalType: 'uint256',\n        name: 'amount',\n        type: 'uint256',\n      },\n      {\n        internalType: 'bytes',\n        name: 'data',\n        type: 'bytes',\n      },\n    ],\n    name: 'safeTransferFrom',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256[]',\n        name: 'ids',\n        type: 'uint256[]',\n      },\n      {\n        internalType: 'uint256[]',\n        name: 'amounts',\n        type: 'uint256[]',\n      },\n      {\n        internalType: 'bytes',\n        name: 'data',\n        type: 'bytes',\n      },\n    ],\n    name: 'safeBatchTransferFrom',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n]\n"
  },
  {
    "path": "src/api/config/abis/erc20.ts",
    "content": "export const erc20 = [\n  {\n    constant: true,\n    inputs: [],\n    name: 'name',\n    outputs: [\n      {\n        name: '',\n        type: 'string',\n      },\n    ],\n    payable: false,\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    constant: false,\n    inputs: [\n      {\n        name: '_spender',\n        type: 'address',\n      },\n      {\n        name: '_value',\n        type: 'uint256',\n      },\n    ],\n    name: 'approve',\n    outputs: [\n      {\n        name: '',\n        type: 'bool',\n      },\n    ],\n    payable: false,\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    constant: false,\n    inputs: [\n      {\n        name: '_from',\n        type: 'address',\n      },\n      {\n        name: '_to',\n        type: 'address',\n      },\n      {\n        name: '_value',\n        type: 'uint256',\n      },\n    ],\n    name: 'transferFrom',\n    outputs: [\n      {\n        name: '',\n        type: 'bool',\n      },\n    ],\n    payable: false,\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    constant: true,\n    inputs: [],\n    name: 'decimals',\n    outputs: [\n      {\n        name: '',\n        type: 'uint8',\n      },\n    ],\n    payable: false,\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    constant: true,\n    inputs: [\n      {\n        name: '_owner',\n        type: 'address',\n      },\n    ],\n    name: 'balanceOf',\n    outputs: [\n      {\n        name: 'balance',\n        type: 'uint256',\n      },\n    ],\n    payable: false,\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    constant: true,\n    inputs: [],\n    name: 'symbol',\n    outputs: [\n      {\n        name: '',\n        type: 'string',\n      },\n    ],\n    payable: false,\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    constant: false,\n    inputs: [\n      {\n        name: '_to',\n        type: 'address',\n      },\n      {\n        name: '_value',\n        type: 'uint256',\n      },\n    ],\n    name: 'transfer',\n    outputs: [\n      {\n        name: '',\n        type: 'bool',\n      },\n    ],\n    payable: false,\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    constant: true,\n    inputs: [\n      {\n        name: '_owner',\n        type: 'address',\n      },\n      {\n        name: '_spender',\n        type: 'address',\n      },\n    ],\n    name: 'allowance',\n    outputs: [\n      {\n        name: '',\n        type: 'uint256',\n      },\n    ],\n    payable: false,\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    payable: true,\n    stateMutability: 'payable',\n    type: 'fallback',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        name: 'owner',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        name: 'spender',\n        type: 'address',\n      },\n      {\n        indexed: false,\n        name: 'value',\n        type: 'uint256',\n      },\n    ],\n    name: 'Approval',\n    type: 'event',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        name: 'from',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        name: 'to',\n        type: 'address',\n      },\n      {\n        indexed: false,\n        name: 'value',\n        type: 'uint256',\n      },\n    ],\n    name: 'Transfer',\n    type: 'event',\n  },\n]\n"
  },
  {
    "path": "src/api/config/abis/erc721.ts",
    "content": "export const erc721 = [\n  {\n    inputs: [\n      {\n        internalType: 'string',\n        name: 'name_',\n        type: 'string',\n      },\n      {\n        internalType: 'string',\n        name: 'symbol_',\n        type: 'string',\n      },\n    ],\n    stateMutability: 'nonpayable',\n    type: 'constructor',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'owner',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'approved',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'Approval',\n    type: 'event',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'owner',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n      {\n        indexed: false,\n        internalType: 'bool',\n        name: 'approved',\n        type: 'bool',\n      },\n    ],\n    name: 'ApprovalForAll',\n    type: 'event',\n  },\n  {\n    anonymous: false,\n    inputs: [\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        indexed: true,\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'Transfer',\n    type: 'event',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'approve',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'owner',\n        type: 'address',\n      },\n    ],\n    name: 'balanceOf',\n    outputs: [\n      {\n        internalType: 'uint256',\n        name: '',\n        type: 'uint256',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'getApproved',\n    outputs: [\n      {\n        internalType: 'address',\n        name: '',\n        type: 'address',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'owner',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n    ],\n    name: 'isApprovedForAll',\n    outputs: [\n      {\n        internalType: 'bool',\n        name: '',\n        type: 'bool',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [],\n    name: 'name',\n    outputs: [\n      {\n        internalType: 'string',\n        name: '',\n        type: 'string',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'ownerOf',\n    outputs: [\n      {\n        internalType: 'address',\n        name: '',\n        type: 'address',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'safeTransferFrom',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n      {\n        internalType: 'bytes',\n        name: '_data',\n        type: 'bytes',\n      },\n    ],\n    name: 'safeTransferFrom',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'operator',\n        type: 'address',\n      },\n      {\n        internalType: 'bool',\n        name: 'approved',\n        type: 'bool',\n      },\n    ],\n    name: 'setApprovalForAll',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'bytes4',\n        name: 'interfaceId',\n        type: 'bytes4',\n      },\n    ],\n    name: 'supportsInterface',\n    outputs: [\n      {\n        internalType: 'bool',\n        name: '',\n        type: 'bool',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [],\n    name: 'symbol',\n    outputs: [\n      {\n        internalType: 'string',\n        name: '',\n        type: 'string',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'tokenURI',\n    outputs: [\n      {\n        internalType: 'string',\n        name: '',\n        type: 'string',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'from',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'to',\n        type: 'address',\n      },\n      {\n        internalType: 'uint256',\n        name: 'tokenId',\n        type: 'uint256',\n      },\n    ],\n    name: 'transferFrom',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n]\n"
  },
  {
    "path": "src/api/config/abis/exchange_3_6.ts",
    "content": "export const exchange = [\n  {\n    inputs: [\n      {\n        internalType: \"address\",\n        name: \"owner\",\n        type: \"address\",\n      },\n      {\n        internalType: \"address\",\n        name: \"tokenAddress\",\n        type: \"address\",\n      },\n      {\n        internalType: \"uint32\",\n        name: \"accountID\",\n        type: \"uint32\",\n      },\n    ],\n    name: \"forceWithdraw\",\n    outputs: [],\n    stateMutability: \"payable\",\n    type: \"function\",\n  },\n  {\n    inputs: [\n      {\n        internalType: \"address\",\n        name: \"from\",\n        type: \"address\",\n      },\n      {\n        internalType: \"address\",\n        name: \"to\",\n        type: \"address\",\n      },\n      {\n        internalType: \"address\",\n        name: \"tokenAddress\",\n        type: \"address\",\n      },\n      {\n        internalType: \"uint96\",\n        name: \"amount\",\n        type: \"uint96\",\n      },\n      {\n        internalType: \"bytes\",\n        name: \"extraData\",\n        type: \"bytes\",\n      },\n    ],\n    name: \"deposit\",\n    outputs: [],\n    stateMutability: \"payable\",\n    type: \"function\",\n  },\n  {\n    inputs: [\n      {\n        internalType: \"address\",\n        name: \"from\",\n        type: \"address\",\n      },\n      {\n        internalType: \"address\",\n        name: \"to\",\n        type: \"address\",\n      },\n      {\n        internalType: \"enum ExchangeData.NftType\",\n        name: \"nftType\",\n        type: \"uint8\",\n      },\n      {\n        internalType: \"address\",\n        name: \"tokenAddress\",\n        type: \"address\",\n      },\n      {\n        internalType: \"uint256\",\n        name: \"nftId\",\n        type: \"uint256\",\n      },\n      {\n        internalType: \"uint96\",\n        name: \"amount\",\n        type: \"uint96\",\n      },\n      {\n        internalType: \"bytes\",\n        name: \"extraData\",\n        type: \"bytes\",\n      },\n    ],\n    name: \"depositNFT\",\n    outputs: [],\n    stateMutability: \"nonpayable\",\n    type: \"function\",\n  },\n  {\n    inputs: [\n      {\n        internalType: \"address\",\n        name: \"owner\",\n        type: \"address\",\n      },\n      {\n        internalType: \"address\",\n        name: \"token\",\n        type: \"address\",\n      },\n    ],\n    name: \"withdrawFromDepositRequest\",\n    outputs: [],\n    stateMutability: \"nonpayable\",\n    type: \"function\",\n  },\n  {\n    inputs: [\n      {\n        internalType: \"address[]\",\n        name: \"owners\",\n        type: \"address[]\",\n      },\n      {\n        internalType: \"address[]\",\n        name: \"tokens\",\n        type: \"address[]\",\n      },\n    ],\n    name: \"withdrawFromApprovedWithdrawals\",\n    outputs: [],\n    stateMutability: \"nonpayable\",\n    type: \"function\",\n  },\n  {\n    inputs: [\n      {\n        internalType: \"address\",\n        name: \"owner\",\n        type: \"address\",\n      },\n      {\n        internalType: \"address\",\n        name: \"token\",\n        type: \"address\",\n      },\n    ],\n    name: \"getAmountWithdrawable\",\n    outputs: [\n      {\n        internalType: \"uint256\",\n        name: \"\",\n        type: \"uint256\",\n      },\n    ],\n    stateMutability: \"view\",\n    type: \"function\",\n  },\n  {\n    inputs: [\n      {\n        internalType: \"address\",\n        name: \"owner\",\n        type: \"address\",\n      },\n      {\n        internalType: \"bytes32\",\n        name: \"txHash\",\n        type: \"bytes32\",\n      },\n    ],\n    name: \"approveTransaction\",\n    outputs: [],\n    stateMutability: \"nonpayable\",\n    type: \"function\",\n  },\n];\n"
  },
  {
    "path": "src/api/config/abis/hebao.ts",
    "content": "export const hebao = [\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'wallet',\n        type: 'address',\n      },\n    ],\n    name: 'lock',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        internalType: 'address',\n        name: 'wallet',\n        type: 'address',\n      },\n      {\n        internalType: 'address',\n        name: 'guardian',\n        type: 'address',\n      },\n    ],\n    name: 'unlock',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n]\n"
  },
  {
    "path": "src/api/config/abis/index.ts",
    "content": "export * as contractWalletAbi from './contractWallet'\nexport * as erc20Abi from './erc20'\nexport * as erc721Abi from './erc721'\nexport * as erc1155Abi from './erc1155'\nexport * as exchange36Abi from './exchange_3_6'\nexport * as hebao from './hebao'\nexport * as smartWallet from './smartWallet'\n"
  },
  {
    "path": "src/api/config/abis/smartWallet.ts",
    "content": "export default [\n  {\n    inputs: [\n      { internalType: 'contract PriceOracle', name: '_priceOracle', type: 'address' },\n      { internalType: 'address', name: '_blankOwner', type: 'address' },\n    ],\n    stateMutability: 'nonpayable',\n    type: 'constructor',\n  },\n  {\n    inputs: [],\n    name: 'DOMAIN_SEPARATOR',\n    outputs: [{ internalType: 'bytes32', name: '', type: 'bytes32' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'guardian', type: 'address' }],\n    name: 'addGuardian',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'addr', type: 'address' }],\n    name: 'addToWhitelist',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'token', type: 'address' },\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'amount', type: 'uint256' },\n      { internalType: 'uint256', name: 'value', type: 'uint256' },\n      { internalType: 'bytes', name: 'data', type: 'bytes' },\n      { internalType: 'bool', name: 'forceUseQuota', type: 'bool' },\n    ],\n    name: 'approveThenCallContract',\n    outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'token', type: 'address' },\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'amount', type: 'uint256' },\n      { internalType: 'bool', name: 'forceUseQuota', type: 'bool' },\n    ],\n    name: 'approveToken',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'address', name: 'addr', type: 'address' },\n    ],\n    name: 'addToWhitelistWA',\n    outputs: [{ internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'address', name: 'token', type: 'address' },\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'amount', type: 'uint256' },\n      { internalType: 'uint256', name: 'value', type: 'uint256' },\n      { internalType: 'bytes', name: 'data', type: 'bytes' },\n    ],\n    name: 'approveThenCallContractWA',\n    outputs: [\n      { internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' },\n      { internalType: 'bytes', name: 'returnData', type: 'bytes' },\n    ],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address[]', name: 'to', type: 'address[]' },\n      { internalType: 'bytes[]', name: 'data', type: 'bytes[]' },\n    ],\n    name: 'batchCall',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [],\n    name: 'blankOwner',\n    outputs: [{ internalType: 'address', name: '', type: 'address' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'value', type: 'uint256' },\n      { internalType: 'bytes', name: 'data', type: 'bytes' },\n      { internalType: 'bool', name: 'forceUseQuota', type: 'bool' },\n    ],\n    name: 'callContract',\n    outputs: [{ internalType: 'bytes', name: '', type: 'bytes' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'value', type: 'uint256' },\n      { internalType: 'bytes', name: 'data', type: 'bytes' },\n    ],\n    name: 'callContractWA',\n    outputs: [\n      { internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' },\n      { internalType: 'bytes', name: 'returnData', type: 'bytes' },\n    ],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'uint256', name: 'newQuota', type: 'uint256' }],\n    name: 'changeDailyQuota',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'uint256', name: 'newQuota', type: 'uint256' },\n    ],\n    name: 'changeDailyQuotaWA',\n    outputs: [{ internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'address', name: 'newMasterCopy', type: 'address' },\n    ],\n    name: 'changeMasterCopy',\n    outputs: [{ internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'nonce', type: 'uint256' },\n      { internalType: 'address', name: 'gasToken', type: 'address' },\n      { internalType: 'uint256', name: 'gasPrice', type: 'uint256' },\n      { internalType: 'uint256', name: 'gasLimit', type: 'uint256' },\n      { internalType: 'uint256', name: 'gasOverhead', type: 'uint256' },\n      { internalType: 'address', name: 'feeRecipient', type: 'address' },\n      { internalType: 'bool', name: 'requiresSuccess', type: 'bool' },\n      { internalType: 'bytes', name: 'data', type: 'bytes' },\n      { internalType: 'bytes', name: 'signature', type: 'bytes' },\n    ],\n    name: 'executeMetaTx',\n    outputs: [{ internalType: 'bool', name: '', type: 'bool' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [],\n    name: 'getCreationTimestamp',\n    outputs: [{ internalType: 'uint64', name: '', type: 'uint64' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'bool', name: 'includePendingAddition', type: 'bool' }],\n    name: 'getGuardians',\n    outputs: [\n      {\n        components: [\n          { internalType: 'address', name: 'addr', type: 'address' },\n          { internalType: 'uint8', name: 'status', type: 'uint8' },\n          { internalType: 'uint64', name: 'timestamp', type: 'uint64' },\n        ],\n        internalType: 'struct Guardian[]',\n        name: '',\n        type: 'tuple[]',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [],\n    name: 'getMasterCopy',\n    outputs: [{ internalType: 'address', name: '', type: 'address' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [],\n    name: 'getOwner',\n    outputs: [{ internalType: 'address', name: '', type: 'address' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'addr', type: 'address' }],\n    name: 'getWhitelistEffectiveTime',\n    outputs: [{ internalType: 'uint256', name: '', type: 'uint256' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'newOwner', type: 'address' }],\n    name: 'inherit',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'owner', type: 'address' },\n      { internalType: 'address[]', name: 'guardians', type: 'address[]' },\n      { internalType: 'uint256', name: 'quota', type: 'uint256' },\n      { internalType: 'address', name: 'inheritor', type: 'address' },\n      { internalType: 'address', name: 'feeRecipient', type: 'address' },\n      { internalType: 'address', name: 'feeToken', type: 'address' },\n      { internalType: 'uint256', name: 'feeAmount', type: 'uint256' },\n    ],\n    name: 'initialize',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'addr', type: 'address' },\n      { internalType: 'bool', name: 'includePendingAddition', type: 'bool' },\n    ],\n    name: 'isGuardian',\n    outputs: [{ internalType: 'bool', name: '', type: 'bool' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'bytes32', name: 'signHash', type: 'bytes32' },\n      { internalType: 'bytes', name: 'signature', type: 'bytes' },\n    ],\n    name: 'isValidSignature',\n    outputs: [{ internalType: 'bytes4', name: 'magicValue', type: 'bytes4' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'addr', type: 'address' }],\n    name: 'isWhitelisted',\n    outputs: [{ internalType: 'bool', name: '', type: 'bool' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  { inputs: [], name: 'lock', outputs: [], stateMutability: 'nonpayable', type: 'function' },\n  {\n    inputs: [],\n    name: 'priceOracle',\n    outputs: [{ internalType: 'contract PriceOracle', name: '', type: 'address' }],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'address', name: 'newOwner', type: 'address' },\n      { internalType: 'address[]', name: 'newGuardians', type: 'address[]' },\n    ],\n    name: 'recover',\n    outputs: [{ internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'addr', type: 'address' }],\n    name: 'removeFromWhitelist',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: 'guardian', type: 'address' }],\n    name: 'removeGuardian',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address[]', name: 'newGuardians', type: 'address[]' }],\n    name: 'resetGuardians',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      {\n        components: [\n          { internalType: 'address[]', name: 'signers', type: 'address[]' },\n          { internalType: 'bytes[]', name: 'signatures', type: 'bytes[]' },\n          { internalType: 'uint256', name: 'validUntil', type: 'uint256' },\n          { internalType: 'address', name: 'wallet', type: 'address' },\n        ],\n        internalType: 'struct Approval',\n        name: 'approval',\n        type: 'tuple',\n      },\n      { internalType: 'address[]', name: 'newGuardians', type: 'address[]' },\n    ],\n    name: 'resetGuardiansWA',\n    outputs: [{ internalType: 'bytes32', name: 'approvedHash', type: 'bytes32' }],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'inheritor', type: 'address' },\n      { internalType: 'uint32', name: 'waitingPeriod', type: 'uint32' },\n    ],\n    name: 'setInheritor',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [{ internalType: 'address', name: '_owner', type: 'address' }],\n    name: 'transferOwnership',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n  {\n    inputs: [\n      { internalType: 'address', name: 'token', type: 'address' },\n      { internalType: 'address', name: 'to', type: 'address' },\n      { internalType: 'uint256', name: 'amount', type: 'uint256' },\n      { internalType: 'bytes', name: 'logdata', type: 'bytes' },\n      { internalType: 'bool', name: 'forceUseQuota', type: 'bool' },\n    ],\n    name: 'transferToken',\n    outputs: [],\n    stateMutability: 'nonpayable',\n    type: 'function',\n  },\n\n  {\n    inputs: [],\n    name: 'wallet',\n    outputs: [\n      { internalType: 'address', name: 'owner', type: 'address' },\n      { internalType: 'uint64', name: 'creationTimestamp', type: 'uint64' },\n      { internalType: 'uint256', name: 'nonce', type: 'uint256' },\n      { internalType: 'bool', name: 'locked', type: 'bool' },\n      { internalType: 'address', name: 'inheritor', type: 'address' },\n      { internalType: 'uint32', name: 'inheritWaitingPeriod', type: 'uint32' },\n      { internalType: 'uint64', name: 'lastActive', type: 'uint64' },\n      {\n        components: [\n          { internalType: 'uint128', name: 'currentQuota', type: 'uint128' },\n          { internalType: 'uint128', name: 'pendingQuota', type: 'uint128' },\n          { internalType: 'uint128', name: 'spentAmount', type: 'uint128' },\n          { internalType: 'uint64', name: 'spentTimestamp', type: 'uint64' },\n          { internalType: 'uint64', name: 'pendingUntil', type: 'uint64' },\n        ],\n        internalType: 'struct Quota',\n        name: 'quota',\n        type: 'tuple',\n      },\n    ],\n    stateMutability: 'view',\n    type: 'function',\n  },\n  { stateMutability: 'payable', type: 'receive' },\n]\n\n// recovery\n// transfer\n// add_guardian\n// remove_guardian\n// unlock_wallet\n// upgrade_contract\n// deposit_wallet\n"
  },
  {
    "path": "src/api/config/guardianTypeData.ts",
    "content": "import { ChainId, ConnectorNames, HEBAO_META_TYPE, SigSuffix } from '../../defs'\nimport { myLog } from '../../utils/log_tools'\nimport { getEcDSASig, GetEcDSASigType } from '../sign/sign_tools'\nimport { personalSign } from '../base_api'\nimport { utils } from 'ethers'\n\nconst EIP712Domain = [\n  { name: 'name', type: 'string' },\n  { name: 'version', type: 'string' },\n  { name: 'chainId', type: 'uint256' },\n  { name: 'verifyingContract', type: 'address' },\n]\n\nconst domain = (chainId: ChainId, guardiaContractAddress: any, name: string, version: string) => {\n  return {\n    name,\n    version: version,\n    chainId: chainId,\n    verifyingContract: guardiaContractAddress,\n  }\n}\n\nfunction getApproveRecoverTypedData({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  message,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  // newOwner: any,\n  newGuardians?: Buffer | any\n  message?: {\n    [key: string]: any\n  }\n  walletVersion: 2 | 1\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      recover: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n        { name: 'newOwner', type: 'address' },\n        ...(walletVersion == 1 ? [] : [{ name: 'newGuardians', type: 'address[]' }]),\n      ],\n    },\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'GuardianModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'recover',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n      ...message,\n      // newOwner: newOwner,\n    },\n  }\n  const hash = utils._TypedDataEncoder.hash(typedData.domain, {recover: typedData.types.recover}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\n\nfunction getApproveTransferTypedData({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  newGuardians,\n  message,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  newGuardians?: Buffer | any\n  message?: { [key: string]: any }\n  walletVersion: 2 | 1\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      transferToken: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n        { name: 'token', type: 'address' },\n        { name: 'to', type: 'address' },\n        { name: 'amount', type: 'uint256' },\n        { name: 'logdata', type: 'bytes' },\n      ],\n    },\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'TransferModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'transferToken',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n      ...message,\n    },\n  }\n  const hash= utils._TypedDataEncoder.hash(typedData.domain, {transferToken: typedData.types.transferToken}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\n\n// function getAddGuardianTypedData({\n//   chainId,\n//   guardiaContractAddress,\n//   wallet,\n//   validUntil,\n//   message,\n// }: {\n//   chainId: ChainId\n//   guardiaContractAddress: any\n//   wallet: any\n//   validUntil: any\n//   message?: { [key: string]: any }\n// }) {\n//   const typedData = {\n//     types: {\n//       EIP712Domain,\n//       addGuardian: [\n//         { name: 'wallet', type: 'address' },\n//         { name: 'validUntil', type: 'uint256' },\n//         { name: 'guardian', type: 'address' },\n//       ],\n//     },\n//     domain: domain(chainId, guardiaContractAddress),\n//     primaryType: 'addGuardian',\n//     message: {\n//       wallet: wallet,\n//       validUntil: validUntil,\n//       ...message,\n//     },\n//   }\n//   return typedData\n// }\n\nfunction getRemoveGuardianTypedData({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  message,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  message?: { [key: string]: any }\n  walletVersion: 2 | 1\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      removeGuardian: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n        { name: 'guardian', type: 'address' },\n      ],\n    },\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'GuardianModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'removeGuardian',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n      guardian: message!['guardian'],\n    },\n  }\n  const hash= utils._TypedDataEncoder.hash(typedData.domain, {removeGuardian: typedData.types.removeGuardian}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\nfunction getUnlockWalletTypedData({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  walletVersion: 2 | 1\n  // message?: { [key: string]: any }\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      unlock: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n      ],\n    },\n    // EIP712.hash(\n    //   EIP712.Domain(\"LoopringWallet\", \"2.0.0\", address(this))\n    // )\n\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'GuardianModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'unlock',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n    },\n  }\n  const hash= utils._TypedDataEncoder.hash(typedData.domain, {unlock: typedData.types.unlock}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\nfunction getApproveChangeMasterCopy({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  newGuardians,\n  message,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  newGuardians?: Buffer | any\n  message?: { [key: string]: any }\n  walletVersion: 2 | 1\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      changeMasterCopy: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n        { name: 'masterCopy', type: 'address' },\n      ],\n    },\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'GuardianModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'changeMasterCopy',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n      ...message,\n    },\n  }\n  const hash= utils._TypedDataEncoder.hash(typedData.domain, {changeMasterCopy: typedData.types.changeMasterCopy}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\nfunction getDepositWalletTypedData({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  newGuardians,\n  message,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  newGuardians?: Buffer | any\n  message?: { [key: string]: any }\n  walletVersion: 2 | 1\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      callContract: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n        { name: 'to', type: 'address' },\n        { name: 'value', type: 'uint256' },\n        { name: 'data', type: 'bytes' },\n      ],\n    },\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'TransferModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'callContract',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n      ...message,\n    },\n  }\n  const hash= utils._TypedDataEncoder.hash(typedData.domain, {callContract: typedData.types.callContract}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\n\nfunction getApproveTokenCopy({\n  chainId,\n  guardiaContractAddress,\n  wallet,\n  validUntil,\n  message,\n  walletVersion,\n}: {\n  chainId: ChainId\n  guardiaContractAddress: any\n  wallet: any\n  validUntil: any\n  newGuardians?: Buffer | any\n  message?: { [key: string]: any }\n  walletVersion: 2 | 1\n}) {\n  const typedData = {\n    types: {\n      EIP712Domain,\n      approveToken: [\n        { name: 'wallet', type: 'address' },\n        { name: 'validUntil', type: 'uint256' },\n        { name: 'token', type: 'address' },\n        { name: 'to', type: 'address' },\n        { name: 'amount', type: 'uint256' },\n      ],\n    },\n    domain: domain(\n      chainId,\n      guardiaContractAddress,\n      walletVersion == 1 ? 'TransferModule' : 'LoopringWallet',\n      walletVersion == 1 ? '1.2.0' : '2.0.0',\n    ),\n    primaryType: 'approveToken',\n    message: {\n      wallet: wallet,\n      validUntil: validUntil,\n      ...message,\n    },\n  }\n  const hash= utils._TypedDataEncoder.hash(typedData.domain, {approveToken: typedData.types.approveToken}, typedData.message)\n  console.log('EIP712 hash', hash)\n  return {\n    typedData,\n    hash\n  }\n}\n\nexport async function signHebaoApproveWrap(\n  props: {\n    web3: any\n    chainId: ChainId\n    owner: string\n    isHWAddr: boolean\n    type: HEBAO_META_TYPE\n  } & {\n    newGuardians?: any\n    masterCopy?: string\n    wallet: string\n    validUntil: number\n    forwarderModuleAddress?: string\n    messageData?: {\n      [key: string]: any\n    }\n    guardian: any\n    walletVersion: 1 | 2\n  },\n) {\n  try {\n    const {\n      chainId,\n      web3,\n      type,\n      owner,\n      isHWAddr,\n      wallet,\n      validUntil,\n      forwarderModuleAddress,\n      masterCopy,\n      messageData,\n      guardian,\n      walletVersion,\n    } = props as any\n    let messageHash\n    let data: {typedData: any, hash: string} | undefined\n    myLog('backend hash', guardian?.messageHash)\n    switch (type) {\n      case HEBAO_META_TYPE.recovery:\n        let newOwner = messageData?.newOwner\n        if (!newOwner) {\n          throw 'no newOwner'\n        }\n        data = getApproveRecoverTypedData({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          message: {\n            newOwner,\n            ...(walletVersion == 1\n              ? {}\n              : {\n                  newGuardians: messageData?.newGuardians,\n                  //   : ethers.utils.solidityKeccak256(\n                  //   Array(messageData?.newGuardians?.length).fill('address'),\n                  //   messageData?.newGuardians,\n                  // ),\n                  //   ethUtil.keccak256(\n                  //   messageData?.newGuardians\n                  //     .map((address: string) => address.toLowerCase().replace('0x', ''))\n                  //     .join(''),\n                  // ),\n                  //   ethers.utils.solidityKeccak256(\n                  //   Array(messageData?.newGuardians?.length).fill('address'),\n                  //   messageData?.newGuardians,\n                  // ),\n                }),\n          },\n          walletVersion,\n        })\n        break\n      case HEBAO_META_TYPE.remove_guardian:\n        data = getRemoveGuardianTypedData({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          message: {\n            guardian: messageData?.guardianAddress,\n          },\n          walletVersion,\n        })\n\n        break\n\n      case HEBAO_META_TYPE.unlock_wallet:\n        data = getUnlockWalletTypedData({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          // message: {\n          //   guardian: messageData.guardian,\n          // },\n          walletVersion,\n        })\n        break\n      case HEBAO_META_TYPE.transfer:\n        data = getApproveTransferTypedData({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          message: {\n            token: messageData.token,\n            to: messageData.to,\n            amount: messageData.amount,\n            logdata: messageData.logdata,\n          },\n          walletVersion,\n        })\n        break\n      case HEBAO_META_TYPE.deposit_wallet:\n        data = getDepositWalletTypedData({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          message: {\n            to: messageData.to,\n            value: messageData.value,\n            data: messageData.data,\n          },\n          walletVersion,\n        })\n        break\n      case HEBAO_META_TYPE.approve_token:\n        data = getApproveTokenCopy({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          message: {\n            token: messageData.token,\n            to: messageData.to,\n            amount: messageData.amount,\n            // logdata: messageData.logdata,\n            // masterCopy: messageData.newMasterCopy,\n          },\n          walletVersion,\n        })\n        break\n      case HEBAO_META_TYPE.upgrade_contract:\n        data = getApproveChangeMasterCopy({\n          chainId,\n          guardiaContractAddress: forwarderModuleAddress ? forwarderModuleAddress : masterCopy,\n          wallet, // guardian.signedRequest.wallet,\n          validUntil, // guardian.signedRequest.validUntil,\n          message: {\n            masterCopy: messageData.newMasterCopy,\n          },\n          walletVersion,\n        })\n        break\n      default:\n        messageHash = guardian?.messageHash\n    }\n\n    if (data && data?.typedData) {\n      const result = await getEcDSASig(\n        web3,\n        data.typedData,\n        owner,\n        isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n        chainId,\n        undefined,\n        '',\n        ConnectorNames.Unknown,\n        // counterFactualInfo\n      )\n      // ecdsaSignature\n      return {\n        signature: result.ecdsaSig += SigSuffix.Suffix02,\n        hash: data.hash\n      }\n    } else {\n      // const messageHash =\n      const signature: any = await personalSign(\n        web3,\n        owner,\n        '',\n        messageHash,\n        ConnectorNames.Unknown,\n        chainId,\n      )\n      if (signature?.sig) {\n        return {\n          signature: signature.sig += SigSuffix.Suffix03,\n          hash: data?.hash\n        }\n      } else {\n        throw 'empty'\n      }\n    }\n\n    // }\n  } catch (error) {\n    // console.log('EcDSASig error try sign WithoutDataStruct')\n    throw error\n  }\n}\n"
  },
  {
    "path": "src/api/config/index.ts",
    "content": "/* tslint:disable */\n// @ts-nocheck\nimport { toBig, toFixed } from '../../utils/formatter'\nimport BigNumber from 'bignumber.js'\n\nfunction getTokenBySymbol(symbol, tokens) {\n  if (typeof symbol === 'undefined') {\n    return {}\n  }\n  return tokens.find((token) => token.symbol.toLowerCase() === symbol.toLowerCase()) || {}\n}\n\nfunction fromWEI(symbol, valueInWEI, tokens, { precision, ceil }: any = {}) {\n  try {\n    const token = getTokenBySymbol(symbol, tokens)\n    const precisionToFixed = precision ? precision : token.precision\n    const value = toBig(valueInWEI).div('1e' + token.decimals)\n    return toFixed(value, precisionToFixed, ceil)\n  } catch (err) {\n    return undefined\n  }\n}\n\nfunction toWEI(symbol, value, tokens, rm = BigNumber.ROUND_FLOOR) {\n  const token = getTokenBySymbol(symbol, tokens)\n  if (typeof token === 'undefined') {\n    return 0\n  }\n  return toBig(value)\n    .times('1e' + token.decimals)\n    .toFixed(0, rm)\n}\n\nexport { fromWEI, toWEI }\nexport * from './guardianTypeData'\n"
  },
  {
    "path": "src/api/contacts_api.ts",
    "content": "/* eslint-disable camelcase  */\nimport { BaseAPI } from './base_api'\n\nimport * as loopring_defs from '../defs'\n\nexport class ContactAPI extends BaseAPI {\n  public async getContacts<R = loopring_defs.GetContactsResponse>(\n    request: loopring_defs.GetContactsRequest,\n    apiKey: string,\n    // url: string = loopring_defs.LOOPRING_URLs.GET_CONTACTS\n  ) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_CONTACTS,\n      queryParams: request, //request\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      apiKey,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    } as {\n      raw_data: R\n    } & R\n  }\n\n  public async createContact(request: loopring_defs.CreateContactRequest, apiKey: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.CREATE_CONTACT,\n      bodyParams: request, //request\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      apiKey,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  public async updateContact(request: loopring_defs.UpdateContactRequest, apiKey: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.UPDATE_CONTACT,\n      bodyParams: request, //request\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      apiKey,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n  public async deleteContact(\n    request: loopring_defs.DeleteContactRequest,\n    apiKey: string,\n    // url: string = loopring_defs.LOOPRING_URLs.GET_CONTACTS\n  ) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.DELETE_CONTACT,\n      bodyParams: request, //request\n      method: loopring_defs.ReqMethod.DELETE,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      apiKey,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n}\n\n// ContactAPI.get\n"
  },
  {
    "path": "src/api/contract_api.ts",
    "content": "import Web3 from 'web3'\nimport { Transaction } from '@ethereumjs/tx'\n\nimport * as loopring_defs from '../defs'\n\nimport * as fm from '../utils/formatter'\n\nimport { addHexPrefix, toHex, toNumber } from '../utils/formatter'\nimport { Contracts } from './ethereum/contracts'\n\nexport enum ERC20Method {\n  Approve = 'approve',\n  Deposit = 'deposit',\n  ForceWithdraw = 'forceWithdraw',\n}\n\nexport const ApproveVal = {\n  Zero: '0x0',\n  Max: '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF',\n}\n\nfunction checkWeb3(web3: any) {\n  if (!web3) throw new Error('got undefined web3')\n}\n\n/**\n * @description sign hash\n * @param web3\n * @param account\n * @param hash\n * @returns {Promise.<*>}\n */\nexport async function sign(web3: any, account: string, pwd: string, hash: string) {\n  checkWeb3(web3)\n  return new Promise((resolve) => {\n    web3.eth.sign(hash, account, pwd, function (err: any, result: any) {\n      if (!err) {\n        const r = result.slice(0, 66)\n        const s = addHexPrefix(result.slice(66, 130))\n        let v = toNumber(addHexPrefix(result.slice(130, 132)))\n        if (v === 0 || v === 1) v = v + 27 // 修复ledger的签名\n        resolve({ result: { r, s, v } })\n      } else {\n        const errorMsg = err.message.substring(0, err.message.indexOf(' at '))\n        resolve({ error: { message: errorMsg } })\n      }\n    })\n  })\n}\n\n/**\n * @description Signs ethereum tx\n * @param web3\n * @param account\n * @param rawTx\n * @returns {Promise.<*>}\n */\nexport async function signEthereumTx(\n  web3: any,\n  account: string,\n  rawTx: any,\n  chainId: loopring_defs.ChainId,\n): Promise<{ result: string; rawTx: object } | { error: any }> {\n  const ethTx = Transaction.fromSerializedTx(rawTx)\n  const hash = toHex(ethTx.hash())\n  try {\n    const response: any = await sign(web3, account, '', hash)\n    if (!response.error) {\n      const signature = response['result']\n      signature.v += chainId * 2 + 8\n\n      const jsonTx = Object.assign(ethTx.toJSON(), signature)\n\n      jsonTx.from = rawTx.from\n\n      return { result: fm.toHex(JSON.stringify(jsonTx)), rawTx: jsonTx }\n    } else {\n      return { error: response.error }\n      // throw new Error(response[\"error\"][\"message\"]);\n    }\n  } catch (err) {\n    return { error: err }\n  }\n}\n\nexport async function getNonce(web3: Web3, addr: string) {\n  if (web3) return await web3.eth.getTransactionCount(addr)\n  return -1\n}\n\nexport async function sendRawTx(\n  web3: any,\n  from: string,\n  to: string,\n  value: any,\n  data: any,\n  chainId: loopring_defs.ChainId,\n  nonce: string | number | undefined | null,\n  gasPrice: any,\n  gasLimit: string | number | undefined,\n  sendByMetaMask = true,\n) {\n  checkWeb3(web3)\n\n  gasPrice = fm.fromGWEI(gasPrice).toNumber()\n  const rawTx = {\n    from,\n    to,\n    value,\n    data,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n  }\n\n  if (sendByMetaMask) {\n    return await sendTransaction(web3, rawTx)\n  }\n\n  const res: any = await signEthereumTx(web3, from, rawTx, chainId)\n\n  if (res?.rawTx) {\n    return await sendTransaction(web3, res.rawTx)\n  } else {\n  }\n\n  return res\n}\n\nfunction _genContractData(Contract: any, method: string, data: any) {\n  return Contract.encodeInputs(method, data)\n}\n\nfunction genERC20Data(method: string, data: any) {\n  return _genContractData(Contracts.ERC20Token, method, data)\n}\n\nexport function genExchangeData(method: string, data: any) {\n  return _genContractData(Contracts.ExchangeContract, method, data)\n}\n\nexport async function approve(\n  web3: Web3,\n  from: string,\n  to: string,\n  depositAddress: string,\n  _value: string,\n  chainId: loopring_defs.ChainId,\n  nonce: string | number,\n  gasPrice: string | number,\n  gasLimit: string | number,\n  sendByMetaMask: boolean,\n) {\n  const data = genERC20Data(ERC20Method.Approve, {\n    _spender: depositAddress,\n    _value,\n  })\n\n  return await sendRawTx(\n    web3,\n    from,\n    to,\n    '0',\n    data,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n    sendByMetaMask,\n  )\n}\n\n// 3.6\n/**\n * Approve Zero\n * @param tokenAddress: approve token symbol to zero\n * @param nonce: Ethereum nonce of this address\n * @param gasPrice: gas price in gwei\n * @param sendByMetaMask\n */\nexport async function approveZero(\n  web3: any,\n  owner: string,\n  tokenAddress: string,\n  depositAddress: string,\n  gasPrice: number,\n  gasLimit: number,\n  chainId: loopring_defs.ChainId = loopring_defs.ChainId.GOERLI,\n  nonce: number,\n  sendByMetaMask = false,\n) {\n  return await approve(\n    web3,\n    owner,\n    tokenAddress,\n    depositAddress,\n    ApproveVal.Zero,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n    sendByMetaMask,\n  )\n}\n\n// 3.6\n/**\n * Approve Max\n * @param tokenAddress: approve token symbol to max\n * @param nonce: Ethereum nonce of this address\n * @param gasPrice: gas price in gwei\n * @param sendByMetaMask\n */\nexport async function approveMax(\n  web3: any,\n  owner: string,\n  tokenAddress: string,\n  depositAddress: string,\n  gasPrice: string,\n  gasLimit: string,\n  chainId: loopring_defs.ChainId = loopring_defs.ChainId.GOERLI,\n  nonce: string,\n  sendByMetaMask = false,\n) {\n  return await approve(\n    web3,\n    owner,\n    tokenAddress,\n    depositAddress,\n    ApproveVal.Max,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n    sendByMetaMask,\n  )\n}\n\n// 3.6\n/**\n * deposit\n */\nexport async function deposit(\n  web3: any,\n  from: string,\n  exchangeAddress: string,\n  token: loopring_defs.TokenInfo,\n  value: number,\n  fee: number,\n  gasPrice: string,\n  gasLimit: string,\n  chainId: loopring_defs.ChainId = loopring_defs.ChainId.GOERLI,\n  nonce: string,\n  sendByMetaMask = true,\n  to?: string,\n) {\n  let valueC = fm.toBig(value).times('1e' + token.decimals)\n\n  const amount = fm.toHex(valueC)\n\n  const data = genExchangeData(ERC20Method.Deposit, {\n    tokenAddress: token.address,\n    amount,\n    from,\n    to: to ? to : from,\n    extraData: '',\n  })\n\n  if (token.type === 'ETH') {\n    valueC = valueC.plus(fee)\n  } else {\n    valueC = fm.toBig(fee)\n  }\n\n  return await sendRawTx(\n    web3,\n    from,\n    exchangeAddress,\n    valueC.toFixed(),\n    data,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n    sendByMetaMask,\n  )\n}\n\n/**\n * forceWithdrawal\n */\nexport async function forceWithdrawal(\n  web3: any,\n  from: string,\n  accountID: number,\n  exchangeAddress: string,\n  token: loopring_defs.TokenInfo,\n  fee: number,\n  gasPrice: number,\n  gasLimit: number,\n  chainId: loopring_defs.ChainId = loopring_defs.ChainId.GOERLI,\n  nonce: number,\n  sendByMetaMask = false,\n) {\n  const valueC = fm.toBig(fee)\n  const data = genExchangeData(ERC20Method.ForceWithdraw, {\n    owner: from,\n    tokenAddress: token.address,\n    accountID,\n  })\n  return await sendRawTx(\n    web3,\n    from,\n    exchangeAddress,\n    valueC.toFixed(),\n    data,\n    chainId,\n    nonce,\n    gasPrice,\n    gasLimit,\n    sendByMetaMask,\n  )\n}\n\n/**\n * @description Sends ethereum tx through MetaMask\n * @param web3\n * @param tx\n * @returns {*}\n */\nexport async function sendTransaction(web3: any, tx: any) {\n  delete tx.gasPrice\n  // delete tx.gas;\n  const response: any = await new Promise((resolve) => {\n    web3.eth.sendTransaction(tx, function (err: any, transactionHash: string) {\n      if (!err) {\n        resolve({ result: transactionHash })\n      } else {\n        resolve({ error: { message: err.message } })\n      }\n    })\n  })\n\n  if (response['result']) {\n    return response\n  } else {\n    throw new Error(response['error']['message'])\n  }\n}\n\nexport async function isContract(web3: any, address: string) {\n  const code = await web3.eth.getCode(address)\n  return code && code.length > 2\n}\n"
  },
  {
    "path": "src/api/defi_api.ts",
    "content": "/* eslint-disable camelcase  */\nimport { BaseAPI } from './base_api'\nimport * as loopring_defs from '../defs'\nimport { makeInvestMarkets, makeMarkets, sortObjDictionary } from '../utils'\nimport * as sign_tools from './sign/sign_tools'\nimport { AxiosResponse } from 'axios'\nimport { getMidPrice } from './exchange_api'\nimport { getEdDSASigWithPoseidon } from './sign/sign_tools'\nimport * as string_decoder from 'string_decoder'\n\nexport class DefiAPI extends BaseAPI {\n  /*\n   * Returns the fee rate of users placing orders in specific markets\n   */\n  public async getDefiToken<R>(): Promise<{\n    raw_data: R\n    tokensMap: loopring_defs.LoopringMap<loopring_defs.TokenInfo>\n    idIndex: loopring_defs.LoopringMap<string>\n    addressIndex: loopring_defs.LoopringMap<loopring_defs.TokenAddress>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DEFI_TOKENS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const tokensMap: loopring_defs.LoopringMap<loopring_defs.TokenInfo> = {}\n    const addressIndex: loopring_defs.LoopringMap<loopring_defs.TokenAddress> = {}\n    const idIndex: loopring_defs.LoopringMap<string> = {}\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.TokenInfo) => {\n        if (item.symbol.startsWith('LP-')) {\n          item.isLpToken = true\n        } else {\n          item.isLpToken = false\n        }\n        tokensMap[item.symbol] = item\n\n        const coinInfo = {\n          icon: loopring_defs.SoursURL + `ethereum/assets/${item.address}/logo.png`,\n          name: item.symbol,\n          simpleName: item.symbol,\n          description: item.type,\n          company: '',\n        }\n        // totalCoinMap[item.symbol] = coinInfo;\n        addressIndex[item.address.toLowerCase()] = item.symbol\n        idIndex[item.tokenId] = item.symbol\n      })\n    }\n\n    return {\n      tokensMap,\n      idIndex,\n      addressIndex,\n      raw_data,\n    }\n  }\n\n  public async getDefiMarkets<R>(\n    request: loopring_defs.GetDefiMarketRequest,\n    url: string = loopring_defs.LOOPRING_URLs.GET_DEFI_MARKETS,\n  ): Promise<{\n    markets: loopring_defs.LoopringMap<loopring_defs.DefiMarketInfo>\n    pairs: loopring_defs.LoopringMap<loopring_defs.TokenRelatedInfo>\n    tokenArr: string[]\n    tokenArrStr: string\n    marketArr: string[]\n    marketArrStr: string\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url,\n      queryParams: {},\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const types = request?.defiType?.toString()?.split(',')\n    return {\n      ...makeInvestMarkets(raw_data, types),\n      raw_data,\n    }\n  }\n\n  public async orderDefi<R>(\n    request: loopring_defs.DefiOrderRequest,\n    privateKey: string,\n    apiKey: string,\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const dataToSig = [\n      request.exchange,\n      request.storageId,\n      request.accountId,\n      request.sellToken.tokenId,\n      request.buyToken.tokenId,\n      request.sellToken.volume,\n      request.buyToken.volume,\n      request.validUntil,\n      request.maxFeeBips,\n      request.fillAmountBOrS ? 1 : 0,\n      0,\n    ]\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_DEFI_ORDER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG_POSEIDON,\n      sigObj: {\n        dataToSig,\n        sigPatch: loopring_defs.SigPatchField.EddsaSignature,\n        PrivateKey: privateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return this.returnTxHash(raw_data)\n  }\n\n  public async getDefiReward<R>(\n    request: loopring_defs.GetUserDefiRewardRequest,\n    apiKey: string,\n  ): Promise<\n    | {\n        raw_data: R\n        totalNum: number\n        totalRewards: string\n        lastDayRewards: string\n        rewards: []\n      }\n    | loopring_defs.RESULT_INFO\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DEFI_REWARDS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  public async getDefiTransaction<R>(\n    request: loopring_defs.GetUserDefiTxRequest,\n    apiKey: string,\n  ): Promise<\n    | {\n        raw_data: R\n        totalNum: number\n        userDefiTxs: loopring_defs.UserDefiTxsHistory[]\n      }\n    | loopring_defs.RESULT_INFO\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DEFI_TRANSACTIONS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      totalNum: raw_data?.totalNum,\n      userDefiTxs: raw_data.transactions as loopring_defs.UserDefiTxsHistory[],\n      raw_data,\n    }\n  }\n\n  public async getDualInfos<R>(request: loopring_defs.GetDualInfosRequest): Promise<\n    | loopring_defs.RESULT_INFO\n    | {\n        totalNum: number\n        dualInfo: {\n          infos: loopring_defs.DualProductAndPrice[]\n          index: loopring_defs.DualIndex\n          balance: loopring_defs.DualBalance[]\n          rules: loopring_defs.DualRulesCoinsInfo[]\n        }\n        raw_data: R\n      }\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DUAL_INFOS,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      dualInfo: {\n        infos: raw_data.infos as loopring_defs.DualProductAndPrice[],\n        index: raw_data.index as loopring_defs.DualIndex,\n        balance: raw_data.balance as loopring_defs.DualBalance[],\n        rules: raw_data.rules as loopring_defs.DualRulesCoinsInfo[],\n      },\n      raw_data,\n    }\n  }\n\n  public async getDualBalance<R>(request = undefined) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DUAL_BALANCE,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      dualBalanceMap: [...raw_data].reduce((prev, item) => {\n        return { ...prev, [item.coin]: item }\n      }, {} as loopring_defs.LoopringMap<loopring_defs.DualBalance>),\n    }\n  }\n\n  public async getDualPrices(request: loopring_defs.GetDualPricesRequest) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DUAL_PRICES,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      totalNum: raw_data?.totalNum,\n      infos: raw_data.infos as loopring_defs.DualPrice[],\n    }\n  }\n\n  public async getDualIndex(request: { baseSymbol: string; quoteSymbol: string }) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DUAL_INDEX,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      dualPrice: raw_data as loopring_defs.DualPrice[],\n    }\n  }\n\n  public async getDualTransactions(request: loopring_defs.GetUserDualTxRequest, apiKey: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DUAL_TRANSACTIONS,\n      queryParams: {\n        ...request,\n        ...(request.retryStatuses ? { retryStatuses: request.retryStatuses.join(',') } : {}),\n      },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      totalNum: raw_data?.totalNum,\n      indexes: raw_data?.indexes,\n      userDualTxs: raw_data.transactions as loopring_defs.UserDualTxsHistory[],\n      raw_data,\n    }\n    return\n  }\n\n  public async orderDual(\n    request: loopring_defs.DualOrderRequest,\n    privateKey: string,\n    apiKey: string,\n  ) {\n    const dataToSig = [\n      request.exchange,\n      request.storageId,\n      request.accountId,\n      request.sellToken.tokenId,\n      request.buyToken.tokenId,\n      request.sellToken.volume,\n      request.buyToken.volume,\n      request.validUntil,\n      request.maxFeeBips,\n      request.fillAmountBOrS ? 1 : 0,\n      0,\n    ]\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_DUAL_ORDER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG_POSEIDON,\n      sigObj: {\n        dataToSig,\n        sigPatch: loopring_defs.SigPatchField.EddsaSignature,\n        PrivateKey: privateKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return this.returnTxHash(raw_data)\n  }\n\n  public async editDual(\n    request: loopring_defs.DualEditRequest,\n    privateKey: string,\n    apiKey: string,\n  ) {\n    const { newOrder } = request\n    let bodyParams = { ...request }\n    if (newOrder) {\n      const dataToSig = [\n        newOrder.exchange,\n        newOrder.storageId,\n        newOrder.accountId,\n        newOrder.sellToken.tokenId,\n        newOrder.buyToken.tokenId,\n        newOrder.sellToken.volume,\n        newOrder.buyToken.volume,\n        newOrder.validUntil,\n        newOrder.maxFeeBips,\n        newOrder.fillAmountBOrS ? 1 : 0,\n        0,\n      ]\n      const eddsaSignature = getEdDSASigWithPoseidon(dataToSig, privateKey).result\n      bodyParams = { ...bodyParams, newOrder: { ...newOrder, eddsaSignature } }\n    }\n\n    const _dataToSig: Map<string, any> = sortObjDictionary(bodyParams)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_DUAL_EDIT,\n      bodyParams,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig: _dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return this.returnTxHash(raw_data)\n  }\n\n  public async getDualUserLocked(\n    {\n      lockTag = [loopring_defs.DUAL_TYPE.DUAL_BASE, loopring_defs.DUAL_TYPE.DUAL_CURRENCY],\n      ...request\n    }: loopring_defs.DualUserLockedRequest,\n    apiKey: string,\n  ) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DUAL_USER_LOCKED,\n      queryParams: { ...request, lockTag: lockTag.join(',') },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      lockRecord: raw_data.lockRecord,\n      raw_data,\n    }\n    return\n  }\n\n  public async sendStakeClaim(\n    req: loopring_defs.OriginStakeClaimRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ) {\n    const { request, web3, chainId, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    const { transfer } = request\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    transfer.payeeId = 0\n    transfer.memo = `STAKE-CLAIM->${request.accountId}`\n\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: transfer as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    if (counterFactualInfo) {\n      transfer.counterFactualInfo = counterFactualInfo\n    }\n    transfer.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n      transfer as loopring_defs.OriginTransferRequestV3,\n      eddsaKey,\n    ).result\n    transfer.ecdsaSignature = ecdsaSignature\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_STAKE_CLAIM,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n      if (raw_data?.resultInfo) {\n        return {\n          ...raw_data?.resultInfo,\n        }\n      }\n      return { raw_data, ...raw_data }\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    // return this.returnTxHash(raw_data);\n    // const raw_data = (await this.makeReq().request(reqParams)).data;\n  }\n\n  public async sendStakeRedeem(\n    request: {\n      accountId: number\n      hash: string\n      token: loopring_defs.TokenVolumeV3\n    },\n    privateKey: string,\n    apiKey: string,\n  ) {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_STAKE_REDEEM,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async sendStake(\n    request: {\n      accountId: number\n      token: loopring_defs.TokenVolumeV3\n      timestamp: number\n    },\n    privateKey: string,\n    apiKey: string,\n  ) {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_STAKE,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async getStakeProducts<R>(): Promise<{\n    products: loopring_defs.STACKING_PRODUCT[]\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_STAKE_PRODUCTS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { products: raw_data, raw_data }\n  }\n\n  public async getStakeSummary<R>(\n    request: {\n      accountId: number\n      tokenId: number\n      start?: number\n      end?: number\n      limit?: number\n      offset?: number\n      hashes?: string\n      statuses?: string\n    },\n    apiKey: string,\n  ): Promise<\n    | {\n        raw_data: R\n        totalNum: number\n        totalStaked: string\n        totalStakedRewards: string\n        totalLastDayPendingRewards: string\n        totalClaimableRewards: string\n        list: loopring_defs.StakeInfoOrigin[]\n      }\n    | loopring_defs.RESULT_INFO\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_STAKE_SUMMARY,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { ...raw_data, list: raw_data.staking, raw_data }\n  }\n\n  public async getStakeTransactions<R>(\n    request: {\n      accountId: number\n      tokenId: number\n      start?: number\n      end?: number\n      limit?: number\n      offset?: number\n      hashes?: string\n      types?: string\n    },\n    apiKey: string,\n  ): Promise<{\n    list: loopring_defs.STACKING_TRANSACTIONS[]\n    totalNum: number\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_STAKE_TRANSACTIONS,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      list: raw_data.transactions,\n      totalNum: raw_data.totalNum,\n      raw_data,\n    }\n  }\n\n  public async getBtradeMarkets<R>(): Promise<{\n    markets: loopring_defs.LoopringMap<loopring_defs.BTRADE_MARKET & { type: 'BTRADE' }>\n    pairs: loopring_defs.LoopringMap<loopring_defs.TokenRelatedInfo>\n    tokenArr: string[]\n    tokenArrStr: string\n    marketArr: string[]\n    marketArrStr: string\n    raw_data: R\n  }> {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_BTRATE_MARKETS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    let result: any = {}\n\n    const pairs: loopring_defs.LoopringMap<loopring_defs.TokenRelatedInfo> = {}\n\n    // const isMix = url === loopring_defs.LOOPRING_URLs.GET_MIX_MARKETS;\n\n    if (raw_data instanceof Array) {\n      const reformat = raw_data.reduce((prev, ele: loopring_defs.BTRADE_MARKET) => {\n        if (/-/gi.test(ele.market)) {\n          return [\n            ...prev,\n            {\n              ...ele,\n              btradeMarket: ele.market,\n              market: ele.market.replace(loopring_defs.BTRADENAME, ''),\n              // enabled: true,\n            } as loopring_defs.BTRADE_MARKET,\n          ]\n        } else {\n          return prev\n        }\n      }, [] as loopring_defs.BTRADE_MARKET[])\n      result = makeMarkets({ markets: reformat })\n    }\n    return {\n      markets: result.markets,\n      pairs: result.pairs,\n      tokenArr: result.tokenArr,\n      tokenArrStr: result.tokenArrStr,\n      marketArr: result.marketArr,\n      marketArrStr: result.marketArrStr,\n      raw_data,\n    }\n  }\n\n  public async getBtradeDepth<R>({\n    request,\n    tokenMap,\n  }: {\n    request: {\n      market: string\n      level: number\n      limit?: number\n    }\n    tokenMap?: any\n  }): Promise<{\n    depth: loopring_defs.DepthData\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_BTRATE_DEPTH,\n      queryParams: { ...request },\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const symbol = raw_data.market\n    const timestamp = raw_data.timestamp\n\n    const { asks, bids, mid_price } = getMidPrice({\n      _asks: raw_data.asks,\n      _bids: raw_data.bids,\n    })\n\n    const depth: loopring_defs.DepthData = {\n      symbol,\n      // @ts-ignore\n      market: raw_data.market,\n      version: raw_data.version,\n      timestamp,\n      mid_price,\n      bids: bids.ab_arr,\n      bids_prices: bids.ab_prices,\n      bids_amtTotals: bids.ab_amtTotals,\n      bids_volTotals: bids.ab_volTotals,\n      bids_amtTotal: bids.amtTotal.toString(),\n      bids_volTotal: bids.volTotal.toString(),\n      asks: asks.ab_arr,\n      asks_prices: asks.ab_prices,\n      asks_amtTotals: asks.ab_amtTotals,\n      asks_volTotals: asks.ab_volTotals,\n      asks_amtTotal: asks.amtTotal.toString(),\n      asks_volTotal: asks.volTotal.toString(),\n    }\n\n    return {\n      depth,\n      raw_data: raw_data as unknown as R,\n    }\n  }\n\n  public async getBtradeOrders<R>({\n    request,\n    apiKey,\n  }: {\n    request: loopring_defs.GetOrdersRequest\n    apiKey: string\n  }) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_BTRATE_ORDERS,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      //  baseSettled quoteSettled\n      list: raw_data.transactions,\n      totalNum: raw_data.totalNum,\n      raw_data,\n    }\n  }\n\n  public async sendBtradeOrder({\n    request,\n    privateKey,\n    apiKey,\n  }: {\n    request: loopring_defs.OriginBTRADEV3OrderRequest\n    privateKey: string\n    apiKey: string\n  }) {\n    // const dataToSig: Map<string, any> = sortObjDictionary(request);\n    const dataToSig = [\n      request.exchange,\n      request.storageId,\n      request.accountId,\n      request.sellToken.tokenId,\n      request.buyToken.tokenId,\n      request.sellToken.volume,\n      request.buyToken.volume,\n      request.validUntil,\n      request.maxFeeBips,\n      request.fillAmountBOrS ? 1 : 0,\n      0,\n    ]\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_BTRATE_ORDER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG_POSEIDON,\n      sigObj: {\n        dataToSig,\n        sigPatch: loopring_defs.SigPatchField.EddsaSignature,\n        PrivateKey: privateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async getDefiApys<\n    R = {\n      product: string\n      defiType: string\n      apys: {\n        apy: string\n        createdAt: string\n      }[]\n    },\n  >({\n    request,\n  }: {\n    request: {\n      start?: number\n      end?: number\n      defiType: 'LIDO' | 'ROCKETPOOL' | 'L2STAKING' | 'CIAN' | string\n      product: string\n    }\n  }): Promise<{\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DEFI_APYS,\n      queryParams: { ...request },\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  public async getDefiDepositList<R = any>(\n    {\n      types,\n      markets,\n      number = 10,\n      ...request\n    }: {\n      accountId: number\n      number: number //\n      markets: Array<string> | string\n      types: Array<'LIDO' | 'ROCKETPOOL' | 'L2STAKING' | 'CIAN' | string> | string\n      product: string\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DEFI_STAKE_TRANSACTIONS,\n      apiKey,\n      queryParams: {\n        ...request,\n        number,\n        markets: typeof markets === 'string' ? markets : markets?.join(','),\n        types: typeof types === 'string' ? types : types?.join(','),\n      },\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n  public async getTaikoFarmingPositionInfo<R = any>({\n    accountId,\n  }: {\n    accountId: number\n  }): Promise<{\n    data: {\n      tokenId: number\n      symbol: string\n      address: string\n      decimals: number\n      status: number\n      apr: string\n      precision: number\n      stakedTotal: string\n      claimedTotal: string\n      holdClaimedTotal: string\n      claimableTotal: string\n      totalPoints: string\n      minAmount: string\n      maxAmount: string\n    }[]\n    account: {\n      status: number // 0 => init, 1 => opened, 2 => minting, 3 => redeeming\n    }\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_POSITION_INFO,\n      queryParams: {\n        accountId,\n      },\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data.resultInfo.code !== 0) {\n      throw raw_data.resultInfo\n    } else {\n      return raw_data\n    }\n  }\n  public async getTaikoFarmingTransactions(\n    queryParams: {\n      accountId: number\n      tokenId: number\n      start?: number\n      end?: number\n      limit?: number\n      offset?: number\n      hashes?: string\n      types?: string\n    },\n    apiKey: string,\n  ): Promise<{\n    totalNum: number\n    transactions: {\n      accountId: number\n      tokenId: number\n      amount: string\n      productId: string\n      hash: string\n      stakingType: 'subscribe' | 'unsubscribe'\n      createdAt: number\n      updatedAt: number\n    }[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_TRANSACTIONS,\n      apiKey,\n      queryParams: queryParams,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return raw_data\n  }\n  public async getTaikoFarmingUserSummary(queryParams: {\n    accountId: number\n    tokenId: number\n    start?: number\n    end?: number\n    limit?: number\n    offset?: number\n    hashes?: string\n    statuses?: string\n  }): Promise<{\n    totalNum: number\n    totalStaked: string\n    totalStakedRewards: string\n    totalLastDayPendingRewards: string\n    totalClaimableRewards: string\n    staking: {\n      accountId: number\n      tokenId: number\n      stakeAt: number\n      initialAmount: string\n      remainAmount: string\n      totalRewards: string\n      productId: string\n      hash: string\n      status: string\n      createdAt: number\n      updatedAt: number\n      claimableTime: number\n      lastDayPendingRewards: string\n      apr: string\n    }[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_USER_SUMMARY,\n      queryParams: queryParams,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return raw_data\n  }\n  public async getTaikoFarmingAvailableNft(\n    queryParams: {\n      accountId: number\n    },\n    apiKey: string,\n  ): Promise<loopring_defs.TaikoFarmingAvaiableNFT> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_AVAILABLE_NFT,\n      apiKey,\n      queryParams: queryParams,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return raw_data\n  }\n  public async getTaikoFarmingTransactionByHash(\n    queryParams: {\n      accountId: number\n      hash: string\n    },\n    apiKey: string,\n  ) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_TRANSACTION_BY_HASH,\n      apiKey,\n      queryParams: queryParams,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return raw_data as {\n      operation: {\n        accountId: number\n        tokenId: number\n        amount: string\n        productId: string\n        hash: string\n        stakingType: string\n        status: number\n        createdAt: number\n        updatedAt: number\n      }\n    }\n  }\n  public async getTaikoFarmingDepositDurationList(queryParams: {\n    accountId: number\n    tokenId: number\n    start?: number\n    end?: number\n    limit?: number\n    offset?: number\n    hashes?: string\n    statuses?: string\n  }) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_DEPOSIT_DURATION_LIST,\n      queryParams: queryParams,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return raw_data as {\n      totalNum: number\n      data: {\n        accountId: number\n        tokenId: number\n        stakeAt: number\n        txHash: string\n        eventIndex: number\n        lockDuration: number\n        hash: string\n        status: string\n        createdAt: number\n        updatedAt: number\n      }[]\n    }\n  }\n  public async getTaikoFarmingGetRedeem(\n    queryParams: {\n      accountId: number\n      tokenId: number\n    },\n    apiKey: string,\n  ) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TAIKO_FARMING_GET_REDEEM,\n      queryParams: queryParams,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      apiKey,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    return raw_data as {\n      redeemAmount: string\n      profit: string\n      profitOfU: string\n      resultInfo?: loopring_defs.RESULT_INFO\n    }\n  }\n  public async submitTaikoFarmingClaim({\n    request,\n    eddsaKey,\n    apiKey,\n  }: loopring_defs.TaikoFarmingSubmitOrderNFTRequestV3WithPatch) {\n    const takerOrderEddsaSignature = sign_tools.get_EddsaSig_NFT_Order(request, eddsaKey).result\n    const _request = {\n      ...request,\n      eddsaSignature: takerOrderEddsaSignature,\n    }\n    const dataToSig: Map<string, any> = sortObjDictionary(_request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_TAIKO_FARMING_SUMBIT_CLAIM,\n      bodyParams: _request,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n      apiKey,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return raw_data as {\n        hash: string\n        status: string\n        isIdempotent: boolean\n        accountId: number\n        tokens: number[]\n        storageId: number\n      }\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/delegate_api.ts",
    "content": "import { BaseAPI } from './base_api'\n\nimport * as loopring_defs from '../defs'\n\nexport class DelegateAPI extends BaseAPI {\n  public async getCode(address: string): Promise<string> {\n    const reqParams: loopring_defs.ReqParams = {\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      url: loopring_defs.LOOPRING_URLs.GET_DELEGATE_GET_CODE,\n      method: loopring_defs.ReqMethod.POST,\n      bodyParams: { address },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return raw_data\n  }\n\n  public async getIPFS(path: string): Promise<string> {\n    const reqParams: loopring_defs.ReqParams = {\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      url: loopring_defs.LOOPRING_URLs.GET_DELEGATE_GET_IPFS,\n      method: loopring_defs.ReqMethod.GET,\n      queryParams: { path },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return raw_data\n  }\n\n  public getCollectionDomain() {\n    return this.chainId === loopring_defs.ChainId.GOERLI\n      ? 'https://uatnftinfos.loopring.io'\n      : 'https://nftinfos.loopring.io'\n  }\n}\n"
  },
  {
    "path": "src/api/ethereum/contracts/AbiFunction.ts",
    "content": "/* tslint:disable */\n// @ts-nocheck\nimport { addHexPrefix, clearHexPrefix, toBuffer, toHex } from '../../../utils/formatter'\nimport { methodID, rawDecode, rawEncode } from 'ethereumjs-abi'\nimport BN from 'bn.js'\n\nexport class AbiFunction {\n  name\n  inputTypes\n  inputs\n  outputTypes\n  outputs\n  constant\n  methodAbiHash\n  constructor({ inputs, name, outputs, constant }: any) {\n    this.name = name\n    this.inputTypes = inputs.map(({ type }) => type)\n    this.inputs = inputs\n    this.outputTypes = outputs.map(({ type }) => type)\n    this.outputs = outputs\n    this.constant = constant\n    this.methodAbiHash = toHex(methodID(name, this.inputTypes))\n  }\n\n  /**\n   * @description Returns encoded methodId and inputs\n   * @param inputs Object, examples {owner:'0x000...}\n   * @returns {string}\n   */\n  encodeInputs(inputs) {\n    const abiInputs = this.parseInputs(inputs)\n    return this.methodAbiHash + clearHexPrefix(toHex(rawEncode(this.inputTypes, abiInputs)))\n  }\n\n  /**\n   * @description decode ethereum jsonrpc response result\n   * @param outputs\n   * @returns {*}\n   */\n  decodeOutputs(outputs) {\n    return this.parseOutputs(rawDecode(this.outputTypes, toBuffer(outputs)))\n  }\n\n  /**\n   * @description decode encoded inputs\n   * @param encoded\n   * @returns {*}\n   */\n  decodeEncodedInputs(encoded) {\n    return this.parseOutputs(rawDecode(this.inputTypes, toBuffer(addHexPrefix(encoded))))\n  }\n\n  parseInputs(inputs = {}) {\n    return this.inputs.map(({ name, type }) => {\n      if (inputs[name] === undefined) {\n        throw new Error(`Parameter ${name} of type ${type} is required!`)\n      }\n      return inputs[name]\n    })\n  }\n\n  parseOutputs(outputs) {\n    return outputs.map((output) => {\n      if (output instanceof BN) {\n        return toHex(output)\n      }\n      return output\n    })\n  }\n}\n"
  },
  {
    "path": "src/api/ethereum/contracts/Contract.ts",
    "content": "/* tslint:disable */\n// @ts-nocheck\nimport { methodID } from 'ethereumjs-abi'\nimport { toHex } from '../../../utils/formatter'\nimport { AbiFunction } from './AbiFunction'\n\nexport class Contract {\n  abiFunctions\n  constructor(abi) {\n    const funAbi = abi.filter(({ type }) => type === 'function')\n    this.abiFunctions = funAbi.reduce((acc, item) => {\n      const inputTypes = item.inputs.map(({ type }) => type)\n      const key = `${item.name}(${inputTypes.toString()})`\n      const methodHash = methodID(item.name, inputTypes)\n      return {\n        ...acc,\n        [item.name]: new AbiFunction(item),\n        [key]: new AbiFunction(item),\n        //@ts-ignore\n        [methodHash]: new AbiFunction(item),\n      }\n    }, {})\n  }\n\n  /**\n   * @description Encodes inputs data according to  ethereum abi\n   * @param method string can be full method or just method name, examples: 'balanceOf' or balanceOf(address)\n   * @param inputs array\n   * @returns {*|string}\n   */\n  encodeInputs(method, inputs) {\n    const abiFunction = this.abiFunctions[method]\n    if (abiFunction) {\n      return abiFunction.encodeInputs(inputs)\n    } else {\n      throw new Error(`No  ${method} method according to abi `)\n    }\n  }\n\n  /**\n   * @description Decodes outputs\n   * @param method string can be full method or just method name, examples: 'balanceOf' or balanceOf(address)\n   * @param outputs string\n   * @returns {*}\n   */\n  decodeOutputs(method, outputs) {\n    const abiFunction = this.abiFunctions[method]\n    if (abiFunction) {\n      return abiFunction.decodeOutputs(outputs)\n    } else {\n      throw new Error(`No  ${method} method according to abi `)\n    }\n  }\n\n  /**\n   * @description Decode encoded method and inputs\n   * @param encode string | Buffer\n   * @returns {*}\n   */\n  decodeEncodeInputs(encode) {\n    encode = toHex(encode)\n    const methodId = encode.slice(0, 10)\n    const abiFunction = this.abiFunctions[methodId]\n    if (abiFunction) {\n      return abiFunction.decodeEncodedInputs(encode.slice(10))\n    } else {\n      throw new Error(`No corresponding method according to abi `)\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/ethereum/contracts/Contracts.ts",
    "content": "/* eslint-disable */\nimport {\n  contractWalletAbi,\n  erc20Abi,\n  erc721Abi,\n  erc1155Abi,\n  exchange36Abi,\n  hebao,\n} from '../../config/abis'\nimport { Contract } from './Contract'\n\nconst ERC20Token = new Contract(erc20Abi.erc20)\nconst ExchangeContract = new Contract(exchange36Abi.exchange)\nconst ContractWallet = new Contract(contractWalletAbi.contractWallet)\nconst ERC1155 = new Contract(erc1155Abi.erc1155)\nconst ERC721 = new Contract(erc721Abi.erc721)\nconst HeBao = new Contract(hebao.hebao)\n\nexport {\n  ERC20Token,\n  ERC1155,\n  ERC721,\n  ExchangeContract,\n  ContractWallet,\n  erc721Abi,\n  erc1155Abi,\n  HeBao,\n  exchange36Abi\n}\n"
  },
  {
    "path": "src/api/ethereum/contracts/index.ts",
    "content": "import { AbiFunction } from './AbiFunction'\nimport { Contract } from './Contract'\nimport * as Contracts from './Contracts'\nconst contracts = { Contracts }\nexport { AbiFunction, Contract, contracts, Contracts }\n"
  },
  {
    "path": "src/api/exchange_api.ts",
    "content": "/* eslint-disable camelcase  */\nimport { BaseAPI } from './base_api'\nimport {\n  LOOPRING_URLs,\n  SIG_FLAG,\n  ReqMethod,\n  Side,\n  VipCatergory,\n  TradingInterval,\n  ReqParams,\n  MarketTradeInfo,\n  FiatPriceInfo,\n  LoopringMap,\n  GetAccountRequest,\n  GetCandlestickRequest,\n  GetDepthRequest,\n  GetTickerRequest,\n  GetMarketTradesRequest,\n  GetFiatPriceRequest,\n  GetTokenBalancesRequest,\n  GetAllowancesRequest,\n  MarketInfo,\n  ExchangeInfo,\n  TickerData,\n  DepthData,\n  Candlestick,\n  TokenRelatedInfo,\n  ABInfo,\n  GetEthBalancesRequest,\n  GetEthNonceRequest,\n  GetWithdrawalAgentsRequest,\n  GetAccountServicesRequest,\n  VipFeeRateInfoMap,\n  AccountInfo,\n  TokenAddress,\n  SEP,\n  GetALLTokenBalancesRequest,\n  TOKENMAPLIST,\n  DatacenterTokenInfo,\n  GetDatacenterTokenInfoRequest,\n  GetDatacenterTokenQuoteTrend,\n  GetDatacenterTokenQuoteTrendRequest,\n  DatacenterTokenInfoSimple,\n  GetDatacenterTokenOhlcvQuoteTrendRequest,\n  GetCmcTokenRelationsRequest,\n  getLatestTokenPricesRequest,\n  GetUserTradeAmount,\n} from '../defs'\n\nimport BigNumber from 'bignumber.js'\nimport { getBaseQuote, makeMarket, makeMarkets } from '../utils'\n\nconst checkAmt = (rawStr: string) => {\n  if (rawStr.trim() === '') {\n    return '0'\n  }\n  return rawStr\n}\n\nfunction getFeeMap(feeArr: any[], type = 0) {\n  const feesMap: any = {}\n\n  if (feeArr instanceof Array) {\n    feeArr.forEach((item: any, index: number, array: any) => {\n      let key = ''\n      switch (type) {\n        case 1:\n          key = item.type\n          break\n        default:\n          key = item.token\n      }\n      // feesMap[key] = new BigNumber(item.fee)\n      feesMap[key] = item.fee\n    })\n  }\n\n  return feesMap\n}\n\nfunction genAB(data: any[], isReverse = false) {\n  const ab_arr: ABInfo[] = []\n  let amtTotal: BigNumber = new BigNumber(0)\n  let volTotal: BigNumber = new BigNumber(0)\n\n  const ab_prices: number[] = []\n  const ab_amtTotals: string[] = []\n  const ab_volTotals: string[] = []\n\n  const best = 0\n\n  if (data instanceof Array) {\n    data.forEach((item: any) => {\n      const price = parseFloat(item[0])\n      const amt = new BigNumber(item[1]) // base amt\n      const vol = new BigNumber(item[2]) // quote vol\n      amtTotal = amtTotal.plus(amt)\n      volTotal = volTotal.plus(vol)\n      ab_arr.push({\n        price: price,\n        amt: amt.toString(),\n        vol: vol.toString(),\n        amtTotal: amtTotal.toString(),\n        volTotal: volTotal.toString(),\n      })\n      ab_prices.push(price)\n      ab_amtTotals.push(amtTotal.toString())\n      ab_volTotals.push(volTotal.toString())\n    })\n  }\n\n  if (isReverse) {\n    ab_arr.reverse()\n    ab_prices.reverse()\n    ab_amtTotals.reverse()\n    ab_volTotals.reverse()\n  }\n\n  return {\n    ab_arr,\n    ab_prices,\n    amtTotal,\n    volTotal,\n    ab_amtTotals,\n    ab_volTotals,\n    best,\n  }\n}\n\nexport function getMidPrice({\n  _asks,\n  askReverse,\n  _bids,\n  bidReverse,\n}: {\n  _asks: any\n  askReverse?: boolean\n  _bids: any\n  bidReverse?: boolean\n}) {\n  if (askReverse === undefined) {\n    askReverse = false\n  }\n\n  if (bidReverse === undefined) {\n    bidReverse = true\n  }\n\n  const bids = genAB(_bids, bidReverse)\n  const asks = genAB(_asks, askReverse)\n\n  const mid_price = (bids.ab_prices[bids.ab_prices.length - 1] + asks.ab_prices[0]) / 2\n\n  return {\n    bids,\n    asks,\n    mid_price,\n  }\n}\nexport function getBtradeMidPrice({ _asks, _bids }: { _asks: any[]; _bids: any[] }) {\n  const bids = genAB(_bids)\n  const asks = genAB(_asks)\n\n  const mid_price = (bids.ab_prices[bids.ab_prices.length - 1] + asks.ab_prices[0]) / 2\n\n  return {\n    bids,\n    asks,\n    mid_price,\n  }\n}\n\nexport class ExchangeAPI extends BaseAPI {\n  /*\n   * Returns the relayer's current time in millisecond\n   */\n  public async getRelayerCurrentTime<R>(): Promise<\n    {\n      raw_data: R\n    } & R\n  > {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_RELAYER_CURRENT_TIME,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns Protocol Portrait\n   */\n  public async getProtocolPortrait<R>(): Promise<\n    {\n      raw_data: R\n    } & R\n  > {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_PROTOCOL_PORTRAIT,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns exchange fee info\n   */\n  public async getExchangeFeeInfo<R>(): Promise<{\n    raw_data: R\n    orderbookTradingFeesStablecoin: VipFeeRateInfoMap\n    orderbookTradingFees: VipFeeRateInfoMap\n    ammTradingFees: VipFeeRateInfoMap\n    otherFees: { [key: string]: string }\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_EXCHANGE_FEEINFO,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      orderbookTradingFeesStablecoin: raw_data[\n        VipCatergory.ORDERBOOK_TRADING_FEES_STABLECOIN\n      ] as VipFeeRateInfoMap,\n      orderbookTradingFees: raw_data[VipCatergory.ORDERBOOK_TRADING_FEES] as VipFeeRateInfoMap,\n      ammTradingFees: raw_data[VipCatergory.AMM_TRADING_FEES] as VipFeeRateInfoMap,\n      otherFees: raw_data[VipCatergory.OTHER_FEES] as { [key: string]: string },\n      raw_data,\n    }\n  }\n\n  public async getWithdrawalAgents<R>(request: GetWithdrawalAgentsRequest): Promise<{\n    raw_data: R\n    supportTokenMap: { [key: string]: any }\n  }> {\n    const reqParams: ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_WITHDRAWAL_AGENTS,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const supportTokenMap: { [key: string]: any } = {}\n\n    if (raw_data && raw_data.length > 0) {\n      raw_data.forEach((item: any) => {\n        if (item.symbol) {\n          supportTokenMap[item.symbol] = item\n        }\n      })\n    }\n\n    return {\n      supportTokenMap,\n      raw_data,\n    }\n  }\n\n  public async getRecommendedMarkets<R>(): Promise<{\n    raw_data: R\n    recommended: string[]\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_RECOMENDED_MARKETS,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    let recommended = []\n\n    if (raw_data?.recommended) {\n      if (typeof raw_data.recommended === 'string') {\n        recommended = raw_data.recommended.split(',')\n      } else {\n        recommended = raw_data.recommended\n      }\n    }\n\n    return {\n      recommended,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns the configurations of all supported markets (trading pairs)\n   */\n  public async getMarkets<R>(url: string = LOOPRING_URLs.GET_MARKETS): Promise<{\n    markets: LoopringMap<MarketInfo>\n    pairs: LoopringMap<TokenRelatedInfo>\n    tokenArr: string[]\n    tokenArrStr: string\n    marketArr: string[]\n    marketArrStr: string\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const { markets, pairs, tokenArr, tokenArrStr, marketArr, marketArrStr } = makeMarkets(\n      raw_data,\n      url,\n    )\n\n    return {\n      markets,\n      pairs,\n      tokenArr,\n      tokenArrStr,\n      // tokenArrStr: tokenArr.join(SEP),\n      marketArr,\n      marketArrStr,\n      // marketArrStr: marketArr.join(SEP),\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns the configurations of all supported markets (trading pairs)\n   */\n  public async getMixMarkets<R>(): Promise<{\n    markets: LoopringMap<MarketInfo>\n    pairs: LoopringMap<TokenRelatedInfo>\n    tokenArr: string[]\n    tokenArrStr: string\n    marketArr: string[]\n    marketArrStr: string\n    raw_data: R\n  }> {\n    return await this.getMarkets(LOOPRING_URLs.GET_MIX_MARKETS)\n  }\n\n  /*\n   * Returns the configurations of all supported tokens, including Ether.\n   */\n  public async getTokens<R>(): Promise<\n    TOKENMAPLIST & {\n      raw_data: R\n    }\n  > {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_TOKENS,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    // raw_data\n    // const coinMap: LoopringMap<{\n    //   icon?: string;\n    //   name: string;                   makeMarket\n    //   simpleName: string;\n    //   description?: string;\n    //   company: string;\n    // }> = {};\n    // const totalCoinMap: LoopringMap<{\n    //   icon?: string;\n    //   name: string;\n    //   simpleName: string;\n    //   description?: string;\n    //   company: string;\n    // }> = {};\n    // const addressIndex: LoopringMap<TokenAddress> = {};\n    // const idIndex: LoopringMap<string> = {};\n    // const tokensMap: LoopringMap<TokenInfo> = {};\n    // if (raw_data instanceof Array) {\n    //   raw_data.forEach((item: TokenInfo) => {\n    //     if (item.symbol.startsWith(\"LP-\")) {\n    //       item.isLpToken = true;\n    //     } else {\n    //       item.isLpToken = false;\n    //     }\n    //     tokensMap[item.symbol] = item;\n    //\n    //     const coinInfo = {\n    //       icon: SoursURL + `ethereum/assets/${item.address}/logo.png`,\n    //       name: item.symbol,\n    //       simpleName: item.symbol,\n    //       description: item.type,\n    //       company: \"\",\n    //     };\n    //     if (!item.symbol.startsWith(\"LP-\")) {\n    //       coinMap[item.symbol] = coinInfo;\n    //     }\n    //     totalCoinMap[item.symbol] = coinInfo;\n    //     addressIndex[item.address.toLowerCase()] = item.symbol;\n    //     idIndex[item.tokenId] = item.symbol;\n    //   });\n    // }\n    // raw_data: R;\n    return {\n      ...makeMarket(raw_data),\n      // tokensMap,\n      // coinMap,\n      // totalCoinMap,\n      // idIndex,\n      // addressIndex,\n      raw_data,\n    }\n  }\n\n  // private splitTokens(token: string, tokens: LoopringMap<TokenInfo>) {\n  //   let tokenArray: any = [];\n  //   const tokenAddrArr: string[] = [];\n  //\n  //   if (tokens) {\n  //     if (token) {\n  //       tokenArray = token.split(SEP);\n  //     }\n  //\n  //     if (\n  //       tokenArray.length <= 0 ||\n  //       (tokenArray.length === 1 && tokenArray[0] === \"\")\n  //     ) {\n  //       tokenArray = Reflect.ownKeys(tokens);\n  //     }\n  //\n  //     tokenArray.forEach((item: string) => {\n  //       tokenAddrArr.push(tokens[item].address);\n  //     });\n  //\n  //     token = tokenAddrArr.join(SEP);\n  //   }\n  //\n  //   return {\n  //     tokenArray,\n  //     token,\n  //   };\n  // }\n\n  /*\n   * Returns the balances of all supported tokens, including Ether.\n   */\n  public async getEthBalances<R>(request: GetEthBalancesRequest): Promise<{\n    raw_data: R\n    ethBalance: string\n  }> {\n    const reqParams: ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_ETH_BALANCES,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const ethBalance = raw_data.amount\n\n    return {\n      ethBalance,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns the balances of all supported tokens, including Ether.\n   */\n  public async getTokenBalances<R, T = TokenAddress>(\n    request: GetTokenBalancesRequest,\n  ): Promise<{\n    tokenBalances: Map<T, string>\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      queryParams: { ...request, token: request.token.join(SEP) },\n      url: LOOPRING_URLs.GET_TOKEN_BALANCES,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const tokenBalances: Map<T, string> = new Map<T, string>()\n\n    if (raw_data?.amount instanceof Array) {\n      raw_data.amount.forEach((value: any, index: number) => {\n        // tokenBalances[tokenArray[index]] = raw_data.amount[index];\n        tokenBalances.set(request.token[index] as unknown as T, value)\n      })\n    }\n\n    return {\n      tokenBalances,\n      raw_data,\n    }\n  }\n  public async getAllTokenBalances<R, T = TokenAddress>(\n    request: GetALLTokenBalancesRequest,\n  ): Promise<{\n    tokenBalances: LoopringMap<string>\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      queryParams: { ...request },\n      url: LOOPRING_URLs.GET_AKK_TOKEN_BALANCES,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      tokenBalances: raw_data,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns the allowances of all supported tokens\n   */\n  public async getAllowances<R, T = TokenAddress>(\n    request: GetAllowancesRequest,\n    // tokens: any\n  ): Promise<{\n    raw_data: R\n    tokenAllowances: Map<T, string>\n  }> {\n    const reqParams: ReqParams = {\n      queryParams: {\n        ...request,\n        token: request.token.join(SEP),\n      },\n      url: LOOPRING_URLs.GET_ALLOWANCES,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const tokenAllowances: Map<T, string> = new Map<T, string>()\n\n    if (raw_data?.allowances instanceof Array) {\n      raw_data.allowances.forEach((value: any, index: number) => {\n        tokenAllowances.set(request.token[index] as unknown as T, value)\n      })\n    }\n\n    return {\n      tokenAllowances,\n      raw_data,\n    }\n  }\n\n  /*\n   * Return various configurations of Loopring.io\n   */\n  public async getExchangeInfo<R>(): Promise<{\n    exchangeInfo: ExchangeInfo\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_EXCHANGE_INFO,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const exchangeInfo: ExchangeInfo = {\n      ammExitFees: getFeeMap(raw_data.ammExitFees),\n      chainId: raw_data.chainId,\n      depositAddress: raw_data.depositAddress,\n      exchangeAddress: raw_data.exchangeAddress,\n      fastWithdrawalFees: getFeeMap(raw_data.fastWithdrawalFees),\n      onchainFees: getFeeMap(raw_data.onchainFees, 1),\n      openAccountFees: getFeeMap(raw_data.openAccountFees),\n      transferFees: getFeeMap(raw_data.transferFees),\n      updateFees: getFeeMap(raw_data.updateFees),\n      withdrawalFees: getFeeMap(raw_data.withdrawalFees),\n    }\n\n    return {\n      exchangeInfo,\n      raw_data,\n    }\n  }\n\n  public async getMixDepth<R>(request: GetDepthRequest) {\n    return await this.getDepth<R>(request, LOOPRING_URLs.GET_MIX_DEPTH)\n  }\n\n  /*\n   * Returns the order book of a given trading pair.\n   */\n  public async getDepth<R>(\n    request: GetDepthRequest,\n    url: string = LOOPRING_URLs.GET_DEPTH,\n  ): Promise<{\n    depth: DepthData\n    raw_data: R\n  }> {\n    if (request?.level === undefined) {\n      request.level = 0\n    }\n\n    if (request?.limit === undefined) {\n      request.limit = 50\n    }\n\n    const reqParams: ReqParams = {\n      queryParams: request,\n      url,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const timestamp = raw_data['timestamp']\n\n    const { asks, bids, mid_price } = getMidPrice({\n      _asks: raw_data['asks'],\n      _bids: raw_data['bids'],\n    })\n\n    const depth: DepthData = {\n      symbol: raw_data.market,\n      version: parseInt(raw_data.version),\n      timestamp,\n      mid_price,\n      bids: bids.ab_arr,\n      bids_prices: bids.ab_prices,\n      bids_amtTotals: bids.ab_amtTotals,\n      bids_volTotals: bids.ab_volTotals,\n      bids_amtTotal: bids.amtTotal.toString(),\n      bids_volTotal: bids.volTotal.toString(),\n      asks: asks.ab_arr,\n      asks_prices: asks.ab_prices,\n      asks_amtTotals: asks.ab_amtTotals,\n      asks_volTotals: asks.ab_volTotals,\n      asks_amtTotal: asks.amtTotal.toString(),\n      asks_volTotal: asks.volTotal.toString(),\n    }\n\n    return {\n      depth,\n      raw_data,\n    }\n  }\n\n  public async getMixTicker<R>(request: GetTickerRequest): Promise<{\n    tickMap: LoopringMap<TickerData>\n    tickList: TickerData[]\n    raw_data: R\n  }> {\n    return await this.getTicker<R>(request, LOOPRING_URLs.GET_MIX_TICKER)\n  }\n\n  /*\n   * Gets a markets ticker.\n   * Generally speaking, a ticker in Loopring consists in data from the market taken last 24Hours.\n   */\n  public async getTicker<R>(\n    request: GetTickerRequest,\n    url: string = LOOPRING_URLs.GET_TICKER,\n  ): Promise<{\n    tickMap: LoopringMap<TickerData>\n    tickList: TickerData[]\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const tickers = raw_data.tickers\n    const tickMap: LoopringMap<TickerData> = {}\n    const tickList: TickerData[] = []\n\n    if (tickers && tickers.length) {\n      tickers.forEach((item: any, ind: number, arr: any) => {\n        const open = parseFloat(item[4])\n        const close = parseFloat(item[7])\n\n        const symbol = item[0].replace('COMBINE-', '')\n\n        const { base, quote } = getBaseQuote(symbol)\n\n        let change = 0\n        if (!isNaN(open) && !isNaN(close)) {\n          change = (close - open) / open\n        }\n\n        const timestamp = parseInt(item[1])\n\n        const tick: TickerData = {\n          symbol,\n          base,\n          quote,\n          timestamp,\n          base_token_volume: item[2],\n          quote_token_volume: item[3],\n          open,\n          high: parseFloat(item[5]),\n          low: parseFloat(item[6]),\n          close,\n          count: parseInt(item[8]),\n          bid: parseFloat(item[9]),\n          ask: parseFloat(item[10]),\n          base_fee_amt: checkAmt(item[11]),\n          quote_fee_amt: checkAmt(item[12]),\n          change,\n        }\n\n        tickMap[symbol] = tick\n        tickList.push(tick)\n      })\n    }\n\n    return {\n      tickMap,\n      tickList,\n      raw_data,\n    }\n  }\n\n  public async getAllMixTickers(markets: string | undefined = undefined) {\n    let request: GetTickerRequest\n    if (!markets) {\n      const result = await this.getMixMarkets()\n      if (result.marketArrStr) {\n        request = {\n          market: result.marketArrStr,\n        }\n      } else {\n        return result\n      }\n    } else {\n      request = {\n        market: markets,\n      }\n    }\n\n    return await this.getMixTicker(request)\n  }\n\n  public async getAllTickers(markets: string | undefined = undefined) {\n    let request: GetTickerRequest\n    if (!markets) {\n      const result = await this.getMarkets()\n      if (result.marketArrStr) {\n        request = {\n          market: result.marketArrStr,\n        }\n      } else {\n        return result\n      }\n    } else {\n      request = {\n        market: markets,\n      }\n    }\n\n    return await this.getTicker(request)\n  }\n\n  public async getMixCandlestick<R>(request: GetCandlestickRequest) {\n    return await this.getCandlestick<R>(request, LOOPRING_URLs.GET_MIX_CANDLESTICK)\n  }\n\n  /*\n   * Gets candlesticks.\n   */\n  public async getCandlestick<R>(\n    request: GetCandlestickRequest,\n    url: string = LOOPRING_URLs.GET_CANDLESTICK,\n  ): Promise<{\n    candlesticks: Candlestick[]\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    let tsStep = 60000\n\n    switch (request.interval) {\n      case TradingInterval.min1:\n        break\n      case TradingInterval.min5:\n        tsStep = 300000\n        break\n      case TradingInterval.min15:\n        tsStep = 900000\n        break\n      case TradingInterval.min30:\n        tsStep = 1800000\n        break\n      case TradingInterval.hr1:\n        tsStep = 3600000\n        break\n      case TradingInterval.hr2:\n        tsStep = 7200000\n        break\n      case TradingInterval.hr4:\n        tsStep = 14400000\n        break\n      case TradingInterval.hr12:\n        tsStep = 43200000\n        break\n      case TradingInterval.d1:\n        tsStep = 86400000\n        break\n      case TradingInterval.w1:\n        tsStep = 604800000\n        break\n      default:\n        break\n    }\n\n    let candlesticks: Candlestick[] = []\n\n    if (raw_data?.candlesticks instanceof Array) {\n      const rawCandlesticks = raw_data.candlesticks.reverse()\n\n      let lastCandlestick: Candlestick | undefined = undefined\n      let lastTs = -1\n\n      rawCandlesticks.forEach((item: any) => {\n        const curTs = parseInt(item[0])\n\n        if (lastCandlestick === undefined) {\n          lastTs = curTs\n\n          const candlestick: Candlestick = {\n            timestamp: curTs,\n            txs: parseInt(item[1]),\n            open: parseFloat(item[2]),\n            close: parseFloat(item[3]),\n            high: parseFloat(item[4]),\n            low: parseFloat(item[5]),\n            baseVol: item[6],\n            quoteVol: item[7],\n          }\n\n          lastCandlestick = candlestick\n\n          candlesticks.push(candlestick)\n        } else {\n          const counter = (curTs - lastTs) / tsStep\n\n          // myLog('counter:', curTs, lastTs, counter)\n\n          for (let i = 1; i <= counter; i++) {\n            let candlestick: Candlestick\n\n            if (i === counter) {\n              candlestick = {\n                timestamp: lastTs + i * tsStep,\n                txs: parseInt(item[1]),\n                open: parseFloat(item[2]),\n                close: parseFloat(item[3]),\n                high: parseFloat(item[4]),\n                low: parseFloat(item[5]),\n                baseVol: item[6],\n                quoteVol: item[7],\n              }\n\n              lastTs = curTs\n              lastCandlestick = candlestick\n            } else {\n              candlestick = {\n                timestamp: lastTs + i * tsStep,\n                txs: 0,\n                open: lastCandlestick.close,\n                close: lastCandlestick.close,\n                high: lastCandlestick.close,\n                low: lastCandlestick.close,\n                baseVol: '0',\n                quoteVol: '0',\n              }\n            }\n\n            candlesticks.push(candlestick)\n          }\n        }\n      })\n    }\n\n    candlesticks = candlesticks.reverse()\n\n    return {\n      candlesticks,\n      raw_data,\n    }\n  }\n\n  /*\n   * Fetches, for all the tokens supported by Loopring, their fiat price.\n   */\n  public async getFiatPrice<R>(request: GetFiatPriceRequest) {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_FIAT_PRICE,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const fiatPrices: LoopringMap<FiatPriceInfo> = {}\n\n    if (raw_data?.prices instanceof Array) {\n      raw_data.prices.forEach((item: FiatPriceInfo) => {\n        fiatPrices[item.symbol] = item\n      })\n    }\n\n    return {\n      fiatPrices,\n      raw_data,\n    }\n  }\n\n  /*\n   * Fetches, for all the tokens supported by Loopring, their fiat price.\n   */\n  public async disableWithdrawTokenList<R>(): Promise<{\n    raw_data: R\n    disableWithdrawTokenList: any[]\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_IGNORE_WITHDRAW,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const disableWithdrawTokenList = [...raw_data]\n    return {\n      disableWithdrawTokenList,\n      raw_data,\n    }\n  }\n\n  /*\n   * Query trades with specified market\n   */\n  public async getMarketTrades<R>(request: GetMarketTradesRequest): Promise<{\n    totalNum: number\n    marketTrades: MarketTradeInfo[]\n    raw_data: R\n  }> {\n    if (request.limit === undefined) {\n      request.limit = 20\n    }\n\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_TRADES,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const marketTrades: MarketTradeInfo[] = []\n\n    if (raw_data?.trades instanceof Array) {\n      raw_data.trades.forEach((item: any) => {\n        marketTrades.push({\n          tradeTime: parseInt(item[0]),\n          tradeId: item[1],\n          side: item[2] as Side,\n          volume: item[3],\n          price: item[4],\n          market: item[5],\n          fee: item[6],\n          type: item[13],\n        })\n      })\n    }\n\n    return {\n      totalNum: raw_data.totalNum,\n      marketTrades,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns data associated with the user's exchange account.\n   */\n  public async getAccount<R>(request: GetAccountRequest): Promise<{\n    accInfo: AccountInfo\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.ACCOUNT_ACTION,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const accInfo: AccountInfo = raw_data as AccountInfo\n    return {\n      accInfo,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getEthNonce<R>(\n    request: GetEthNonceRequest,\n  ): Promise<{ nonce: number; raw_data: R }> {\n    const reqParams: ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_ETH_NONCE,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      nonce: raw_data?.nonce,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getGasPrice<R>(): Promise<{\n    gasPrice: number\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_GAS_PRICE,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const gasPrice = raw_data?.price\n\n    return {\n      gasPrice,\n      raw_data,\n    }\n  }\n\n  /*\n   */\n  public async getGasPriceRange<R>(): Promise<{\n    gasPriceRanges: any\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_GAS_PRICE_RANGE,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const gasPriceRanges = raw_data?.ranges\n\n    return {\n      gasPriceRanges,\n      raw_data,\n    }\n  }\n\n  public async getAccountServices<R>(request: GetAccountServicesRequest): Promise<{\n    register: any\n    order: any\n    joinAmm: any\n    dAppTrade: any\n    legal: any\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_ACCOUNT_SERVICES,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      register: raw_data?.register,\n      order: raw_data?.order,\n      joinAmm: raw_data?.joinAmm,\n      dAppTrade: raw_data?.dAppTrade,\n      legal: raw_data?.dAppTrade,\n      raw_data,\n    }\n  }\n  public async getTokenInfo<R = DatacenterTokenInfo>(\n    request: { token: string; currency: 'USD' },\n    url: string = LOOPRING_URLs.GET_QUOTE_TOKEN_INFO,\n  ) {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: { ...request },\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      list: raw_data.data,\n    }\n  }\n\n  public async getSupportTokens<R = DatacenterTokenInfoSimple[]>(\n    request: GetDatacenterTokenInfoRequest,\n    url: string = LOOPRING_URLs.GET_SUPPORT_TOKENS,\n  ): Promise<{ raw_data: R; list: R }> {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: {\n        ...request,\n        cmcTokenIds:\n          typeof request.cmcTokenIds === 'string'\n            ? request.cmcTokenIds\n            : request.cmcTokenIds?.join(','),\n      },\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      list: raw_data.data,\n    }\n  }\n  public async getQuoteTokenInfo<R = [][], _X = GetDatacenterTokenQuoteTrend>(\n    request: GetDatacenterTokenQuoteTrendRequest,\n    url: string = LOOPRING_URLs.GET_QUOTE_TREND,\n  ): Promise<{ list: R; raw_data: R }> {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: { ...request },\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      list: raw_data?.data,\n    }\n  }\n\n  public async getQuoteTokenOhlcv<R = [][], _X = GetDatacenterTokenOhlcvQuoteTrendRequest>(\n    request: GetDatacenterTokenQuoteTrendRequest,\n    url: string = LOOPRING_URLs.GET_QUOTE_TOKEN_OHLCV_TREND,\n  ): Promise<{ list: R; raw_data: R }> {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: {\n        ...request,\n      },\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      list: raw_data?.data,\n    }\n  }\n  public async getCmcTokenRelations<\n    R = {\n      cmcTokenId: number\n      tokenAddress: string\n      symbol: string\n    }[],\n  >(\n    request: GetCmcTokenRelationsRequest,\n    url: string = LOOPRING_URLs.GET_QUOTE_TOKEN_GETCMCTOKENRELATIONS,\n  ): Promise<{ list: R; raw_data: R }> {\n    const reqParams: ReqParams = {\n      url,\n      queryParams: {\n        ...request,\n        cmcTokenIds:\n          typeof request.cmcTokenIds === 'string'\n            ? request.cmcTokenIds\n            : request.cmcTokenIds?.join(','),\n        tokenAddresses:\n          typeof request.tokenAddresses === 'string'\n            ? request.tokenAddresses\n            : request.tokenAddresses?.join(',') ?? '',\n      },\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      list: raw_data?.data,\n    }\n  }\n\n  public async getLatestTokenPrices(request?: getLatestTokenPricesRequest) {\n    const reqParams: ReqParams = {\n      queryParams: request,\n      url: LOOPRING_URLs.GET_LATEST_TOKEN_PRICES,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const tokenPrices: LoopringMap<number> = {}\n\n    if (raw_data?.data instanceof Array) {\n      raw_data.data.forEach((item: any) => {\n        tokenPrices[item.token.toLowerCase()] = parseFloat(item.price)\n      })\n    }\n\n    return {\n      tokenPrices,\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user trade amount\n   */\n  public async getUserTradeAmount(request: GetUserTradeAmount) {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_USER_TRADE_AMOUNT,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/global_api.ts",
    "content": "import { BaseAPI } from './base_api'\nimport * as loopring_defs from '../defs'\nimport { sortObjDictionary } from '../utils'\n\nconst GLOBAL_KEY = {\n  GOERLI: {\n    key: '685xvATlBCsvzyiTxaS02vu0b1xN0DAFpNpslKUNCuSxDhx8gyyz8VmvUqqe5HSQ',\n    id: 10013,\n  },\n  MAIN: {\n    key: 're356TcrQ6KhlpkvWxP4UN0C4EqxQVV7ZjvLjunwTjaQPZ20ue2ZgClFeT7okpDQ',\n    id: 22638,\n  },\n}\n\nexport class GlobalAPI extends BaseAPI {\n  public async getActiveFeeInfo(request: { accountId?: number }) {\n    const _request: loopring_defs.GetOffchainFeeAmtRequest = {\n      accountId: request.accountId\n        ? request.accountId\n        : this.chainId === loopring_defs.ChainId.MAINNET\n        ? GLOBAL_KEY.MAIN.id\n        : GLOBAL_KEY.GOERLI.id,\n      requestType: loopring_defs.OffchainFeeReqType.UPDATE_ACCOUNT,\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_OFFCHAIN_FEE_AMT,\n      queryParams: _request,\n      apiKey:\n        this.chainId === loopring_defs.ChainId.MAINNET\n          ? GLOBAL_KEY.MAIN.key\n          : GLOBAL_KEY.GOERLI.key,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const gasPrice = parseInt(raw_data.gasPrice)\n    const fees: loopring_defs.LoopringMap<loopring_defs.OffchainFeeInfo> = {}\n    if (raw_data?.fees instanceof Array) {\n      raw_data.fees.forEach((item: loopring_defs.OffchainFeeInfo) => {\n        fees[item.token] = item\n      })\n    }\n\n    return {\n      fees,\n      gasPrice,\n      raw_data,\n    }\n  }\n  public async getUserBalanceForFee(request: { accountId: number; tokens: string }) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_EXCHANGE_BALANCES,\n      queryParams: request,\n      apiKey:\n        this.chainId === loopring_defs.ChainId.MAINNET\n          ? GLOBAL_KEY.MAIN.key\n          : GLOBAL_KEY.GOERLI.key,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userBalances: loopring_defs.LoopringMap<loopring_defs.UserBalanceInfo> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.UserBalanceInfo) => {\n        userBalances[item.tokenId] = item\n      })\n    }\n\n    return {\n      userBalances,\n      raw_data,\n    }\n  }\n  public async getAmmPoolGameUserRank<R>(\n    request: loopring_defs.GetAmmPoolGameUserRankRequest,\n  ): Promise<{\n    raw_data: R\n    userRank: loopring_defs.GameRankInfo\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_AMMPOOL_GAME_USER_RANK,\n      queryParams: request,\n      apiKey:\n        this.chainId === loopring_defs.ChainId.MAINNET\n          ? GLOBAL_KEY.MAIN.key\n          : GLOBAL_KEY.GOERLI.key,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    const userRank: loopring_defs.GameRankInfo = raw_data.data\n    return {\n      userRank,\n      raw_data: raw_data.data,\n    }\n  }\n  public async getBanxaAPI<R>(\n    {\n      method,\n      query,\n      payload,\n      url,\n      accountId,\n    }: {\n      method: loopring_defs.ReqMethod\n      query: string\n      payload: string\n      url: string\n      accountId: number\n    },\n    eddsaKey: string,\n    apiKey: string,\n  ): Promise<{\n    result: R\n    raw_data: R\n  }> {\n    const queryParams = {\n      accountId,\n      url,\n      method: method.toString(),\n      query: query,\n      payload: payload ? payload : '',\n    }\n    const dataToSig = sortObjDictionary({\n      ...queryParams,\n      url: encodeURIComponent(queryParams.url),\n      query: encodeURIComponent(queryParams.query),\n      payload: encodeURIComponent(queryParams.payload),\n    })\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_BANXA_API_KEY,\n      method: loopring_defs.ReqMethod.GET,\n      queryParams,\n      apiKey,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        PrivateKey: eddsaKey,\n        dataToSig: dataToSig,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n    return {\n      result: raw_data.result,\n      raw_data: raw_data,\n    }\n  }\n  // public async getBanxaAPIRequest<R>({}) {}\n  // http://dev.loopring.io?method=GET&query=/api/coins&payload\n}\n"
  },
  {
    "path": "src/api/index.ts",
    "content": "export * from './ws_api'\nexport * from './exchange_api'\nexport * from './ammpool_api'\nexport * from './user_api'\nexport * from './wallet_api'\nexport * from './whitelisted_user_api'\nexport * from './contract_api'\nexport * from './sign/sign_tools'\nexport * from './nft_api'\nexport * from './global_api'\nexport * from './delegate_api'\nexport * from './base_api'\nexport * from './defi_api'\nexport * from './luckToken_api'\nexport * from './contacts_api'\nexport * from './vault_api'\nexport * from './ethereum/contracts'\nexport { signHebaoApproveWrap }  from './config'\nexport { RabbitWithdrawAPI }  from './rabbitWithdraw_api'\n"
  },
  {
    "path": "src/api/luckToken_api.ts",
    "content": "/* eslint-disable camelcase  */\nimport { BaseAPI } from './base_api'\nimport {\n  LOOPRING_URLs,\n  NFTTokenInfo,\n  ReqMethod,\n  ReqParams,\n  RESULT_INFO,\n  SIG_FLAG,\n  UserNFTBalanceInfo,\n} from '../defs'\nimport * as loopring_defs from '../defs'\nimport { sortObjDictionary } from '../utils'\nimport * as sign_tools from './sign/sign_tools'\nimport { AxiosResponse } from 'axios'\n\nexport class LuckTokenAPI extends BaseAPI {\n  public async getLuckTokenAgents<R>(): Promise<{\n    raw_data: R\n    luckTokenAgents: { [key: string]: loopring_defs.LuckyTokenInfo }\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_AGENTS,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const luckTokenAgents = raw_data.reduce(\n      (\n        prev: { [key: string]: loopring_defs.LuckyTokenInfo },\n        item: { owner: string; infos: any[] },\n      ) => {\n        prev[item.owner] = {\n          signer: item.infos[0],\n          signerUrl: item.infos[1],\n          logoUrl: item.infos[2],\n          memo: item.infos[3],\n        }\n        return prev\n      },\n      {} as { [key: string]: loopring_defs.LuckyTokenInfo },\n    )\n    return {\n      raw_data,\n      luckTokenAgents,\n    }\n  }\n\n  public async getLuckTokenAuthorizedSigners<R>(): Promise<{\n    raw_data: R\n    luckTokenAgents: { [key: string]: loopring_defs.LuckyTokenInfo }\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_AUTHORIZEDSIGNERS,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const luckTokenAgents = raw_data.reduce(\n      (\n        prev: { [key: string]: loopring_defs.LuckyTokenInfo },\n        item: { owner: string; infos: any[] },\n      ) => {\n        prev[item.owner] = {\n          signer: item.infos[0],\n          signerUrl: item.infos[1],\n          logoUrl: item.infos[2],\n          memo: item.infos[3],\n        }\n        return prev\n      },\n      {} as { [key: string]: loopring_defs.LuckyTokenInfo },\n    )\n    return {\n      raw_data,\n      luckTokenAgents,\n    }\n  }\n\n  public async getLuckTokenClaimHistory<R>(\n    request: { fromId: number; limit?: number; isNft?: boolean },\n    apiKey: string,\n  ): Promise<{\n    totalNum: number\n    list: loopring_defs.LuckTokenHistory[]\n    raw_data: R\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_CLAIMHISTORY,\n      queryParams: request,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const totalNum: number = raw_data.totalNum\n    const list: loopring_defs.LuckTokenHistory[] = raw_data.list\n\n    return {\n      totalNum,\n      list,\n      raw_data,\n    }\n  }\n\n  public async getLuckTokenLuckyTokens<R>(\n    request: {\n      senderId: number\n      hash: string\n      partitions: string\n      modes: string\n      scopes: string\n      statuses: string\n      startTime: number\n      endTime: number\n      fromId: number\n      limit?: number\n      official: boolean\n      isNft?: boolean\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    list: loopring_defs.LuckyTokenItemForReceive[]\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_LUCKYTOKENS,\n      queryParams: request,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const totalNum: number = raw_data.totalNum\n    const list: loopring_defs.LuckyTokenItemForReceive[] = raw_data.list\n\n    return {\n      totalNum,\n      list,\n      raw_data,\n    }\n  }\n\n  public async getLuckTokenDetail<R>(\n    request: {\n      limit?: number\n      hash: string\n      fromId?: number\n      accountId?: number,\n      serialNo?: number\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    detail: loopring_defs.LuckTokenClaimDetail\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_LUCKYTOKENDETAIL,\n      queryParams: request,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, detail: raw_data }\n  }\n\n  public async getBlindBoxDetail<R>(\n    request: {\n      limit?: number\n      hash: string\n      fromId?: number\n      showHelper: boolean\n      accountId?: number,\n      serialNo?: number\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    // detail: loopring_defs.LuckTokenClaimDetail;\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_BLINDBOXDETAIL,\n      queryParams: request,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data }\n  }\n\n  public async getLuckTokenWithdrawals<R>(\n    request: {\n      statuses: loopring_defs.LuckyTokenWithdrawStatus[]\n      tokenId?: number\n      startTime?: number\n      endTime?: number\n      fromId?: number\n      offset?: number\n      limit?: number\n      isNft?: boolean\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    luckTokenWithdraw: loopring_defs.LuckTokenWithdraw[]\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_WITHDRAWALS,\n      queryParams: { ...request, statuses: request.statuses.join(',') },\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      totalNum: raw_data?.totalNum,\n      luckTokenWithdraw: raw_data.list,\n    }\n  }\n\n  public async getLuckTokenBalances<R>(\n    request: {\n      accountId: number\n      tokens?: number[]\n      isNft?: boolean\n      offset?: number\n      limit?: number\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    tokenBalance: Array<\n      loopring_defs.UserBalanceInfo & {\n        isNft?: boolean\n        nftTokenInfo?: loopring_defs.NFTTokenInfo\n      }\n    >\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_BALANCES,\n      queryParams: {\n        ...request,\n        // statuses: request.tokens?.join(\",\")\n      },\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      totalNum: raw_data?.length,\n      tokenBalance: raw_data,\n    }\n  }\n\n  public async getLuckTokenClaimedLuckyTokens<R>(\n    request: {\n      fromId: number\n      limit?: number\n      hashes?: string[]\n      isNft?: boolean\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    claimedHistory: Array<loopring_defs.LuckyTokenItemForReceive & { id: number }>\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_CLAIMEDLUCKYTOKENS,\n      queryParams: { ...request, hashes: request?.hashes?.join(',') },\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      totalNum: raw_data?.totalNum,\n      claimedHistory: raw_data.list,\n    }\n  }\n\n  public async getLuckTokenSummary<R>(apiKey: string): Promise<{\n    raw_data: R\n    tokenSummaryList: {\n      tokenId: number\n      amount: string\n      isNft?: Boolean\n      nftTokenInfo?: NFTTokenInfo & Partial<UserNFTBalanceInfo>\n    }[]\n    totalNum: number\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_SUMMARY,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      totalNum: raw_data.count,\n      tokenSummaryList: raw_data.tokenSummaryList,\n    }\n  }\n\n  public async getLuckTokenNFTBalances<R>(\n    request: {\n      accountId: number\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    amount: number\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_NFTBALANCES,\n      queryParams: request,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      amount: raw_data.amount as number,\n      // totalNum: raw_data.count,\n      // tokenSummaryList: raw_data.tokenSummaryList,\n    }\n  }\n\n  public async sendLuckTokenClaimLuckyToken<R>({\n    request,\n    apiKey,\n    eddsaKey,\n  }: {\n    request: {\n      hash: string\n      claimer: string\n      referrer: string,\n      serialNo?: number\n    }\n    eddsaKey: string\n    apiKey: string\n  }): Promise<{\n    raw_data: R\n  }> {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.POST_LUCK_TOKEN_CLAIMLUCKYTOKEN,\n      bodyParams: request,\n      method: ReqMethod.POST,\n      sigFlag: SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n      apiKey,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async sendLuckTokenClaimBlindBox<R>({\n    request,\n    apiKey,\n    eddsaKey,\n  }: {\n    request: {\n      hash: string\n      claimer: string\n      referrer: string\n      serialNo?: number\n    }\n    eddsaKey: string\n    apiKey: string\n  }): Promise<{\n    raw_data: R\n  }> {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.POST_LUCK_TOKEN_CLAIMBLINDBOX,\n      bodyParams: request,\n      method: ReqMethod.POST,\n      sigFlag: SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n      apiKey,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async sendLuckTokenWithdraws<T>(\n    req: loopring_defs.OriginLuckTokenWithdrawsRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<(Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | RESULT_INFO> {\n    let { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    let { transfer } = request\n    transfer.payeeId = 0\n    transfer.memo = `LuckTokenWithdrawalBy${request.claimer}`\n\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: transfer as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    if (counterFactualInfo) {\n      transfer.counterFactualInfo = counterFactualInfo\n    }\n    let { maxFee, token, ..._transfer } = transfer\n    // @ts-ignore\n    _transfer = {\n      ..._transfer,\n      maxFeeAmount: maxFee?.volume ? maxFee?.volume : '0',\n      feeToken: maxFee?.tokenId ? maxFee?.tokenId : 0,\n      amount: token.volume,\n      token: token.tokenId,\n      ecdsaAuth: ecdsaSignature,\n      eddsaSig: sign_tools.get_EddsaSig_Transfer(\n        transfer as loopring_defs.OriginTransferRequestV3,\n        eddsaKey,\n      ).result,\n    } as any\n\n    request = {\n      ...request,\n      transfer: JSON.stringify(_transfer) as any,\n    }\n\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.POST_LUCK_TOKEN_WITHDRAWALS,\n      apiKey,\n      method: ReqMethod.POST,\n      bodyParams: { ...request },\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  public async sendLuckTokenSend<\n    R = {\n      hash: string\n      status: string\n      isIdempotent: boolean\n      accountId: number\n      tokenId: number\n      storageId: number\n    },\n  >(\n    req: loopring_defs.OriginLuckTokenSendRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<(Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | RESULT_INFO> {\n    let { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n\n    const { accountId, counterFactualInfo }: any = options\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n\n    const {\n      luckyToken: { maxFeeAmount, token, amount, feeToken, ...rest },\n      // @ts-ignore\n      nftData,\n    } = request\n\n    try {\n      let transfer: any, eddsaSig\n      if (nftData) {\n        transfer = {\n          ...rest,\n          fromAccountId: rest.payerId,\n          fromAddress: rest.payerAddr,\n          toAccountId: 0,\n          toAddress: rest.payeeAddr,\n          maxFee: {\n            tokenId: feeToken,\n            amount: maxFeeAmount,\n          },\n          payeeId: 0,\n          memo: `LuckTokenSendBy${accountId}`,\n          token: {\n            nftData,\n            tokenId: token,\n            amount: amount,\n          },\n        } as loopring_defs.OriginNFTTransferRequestV3\n        try {\n          ecdsaSignature = await sign_tools.transferNFTWrap({\n            transfer,\n            chainId,\n            web3,\n            isHWAddr,\n            accountId,\n            counterFactualInfo,\n          })\n          // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n        } catch (error) {\n          throw error\n        }\n        eddsaSig = sign_tools.get_EddsaSig_NFT_Transfer(transfer, eddsaKey).result\n      } else {\n        transfer = {\n          ...rest,\n          maxFee: {\n            tokenId: feeToken,\n            volume: maxFeeAmount,\n          },\n          payeeId: 0,\n          memo: `LuckTokenSendBy${accountId}`,\n          token: {\n            tokenId: token,\n            volume: amount,\n          },\n        } as loopring_defs.OriginTransferRequestV3\n        try {\n          ecdsaSignature = await sign_tools.transferWrap({\n            transfer: transfer as loopring_defs.OriginTransferRequestV3,\n            chainId,\n            web3,\n            isHWAddr,\n            accountId,\n            counterFactualInfo,\n          })\n          // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n        } catch (error) {\n          throw error\n        }\n\n        if (counterFactualInfo) {\n          transfer.counterFactualInfo = counterFactualInfo\n        }\n        transfer.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n          transfer as loopring_defs.OriginTransferRequestV3,\n          eddsaKey,\n        ).result\n        eddsaSig = sign_tools.get_EddsaSig_Transfer(transfer, eddsaKey).result\n      }\n\n      request = {\n        ...request,\n        nftData,\n        luckyToken: {\n          ...request.luckyToken,\n          payeeId: 0,\n          memo: `LuckTokenSendBy${accountId}`,\n          eddsaSig,\n          counterFactualInfo,\n        },\n      }\n      const reqParams: loopring_defs.ReqParams = {\n        url: LOOPRING_URLs.POST_LUCK_TOKEN_SENDLUCKYTOKEN,\n        bodyParams: { ...request },\n        apiKey,\n        method: ReqMethod.POST,\n        sigFlag: SIG_FLAG.NO_SIG,\n        ecdsaSignature,\n      }\n      let raw_data\n      try {\n        raw_data = (await this.makeReq().request(reqParams)).data\n      } catch (error) {\n        throw error as AxiosResponse\n      }\n      return this.returnTxHash(raw_data)\n    } catch (error) {\n      throw error\n    }\n  }\n\n  public async getLuckTokenClaimedBlindBox<R>(\n    request: {\n      fromId: number\n      limit?: number\n      isNft?: boolean\n      offset?: number\n      statuses?: number[]\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    list: Array<loopring_defs.LuckyTokenBlindBoxItemReceive & { id: number }>\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_CLAIMEDBLINDBOX,\n      queryParams: { ...request, statuses: request?.statuses?.join(',') },\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      totalNum: raw_data?.totalNum,\n      list: raw_data.list,\n    }\n  }\n\n  public async getLuckTokenUnclaimNFTBlindboxCnt<R>(\n    request: {\n      accountId: number\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    count: number\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.POST_LUCK_TOKEN_UNCLAIMNFTANDBLINDCNT,\n      queryParams: request,\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      count: raw_data?.count,\n    }\n  }\n\n  public async getLuckTokenUserLuckyTokenTargets<R>(\n    request: {\n      statuses?: number[]\n      fromId?: number\n      limit?: number\n      offset?: number\n      isAll?: number // 0-all, 1-unexpired\n    },\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    list: loopring_defs.LuckyTokenItemForReceive[]\n  }> {\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.GET_LUCK_TOKEN_LUCKYTOKENTARGETS,\n      queryParams: {\n        ...request,\n        statuses: request.statuses ? request.statuses.join(',') : undefined,\n      },\n      apiKey,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n      totalNum: raw_data?.totalNum as number,\n      list: raw_data?.list as loopring_defs.LuckyTokenItemForReceive[],\n    }\n  }\n  public async sendLuckTokenSubmitAddTarget<R>(\n    request: {\n      claimer: string[]\n      hash: string\n      notifyType: number // 0-red dot, 1-pop\n    },\n    eddsaSignKey: string,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: ReqParams = {\n      url: LOOPRING_URLs.POST_LUCK_TOKEN_SUBMITADDTARGET,\n      bodyParams: request,\n      apiKey,\n      method: ReqMethod.POST,\n      sigFlag: SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaSignKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/nft_api.ts",
    "content": "/* eslint-disable @typescript-eslint/no-var-requires */\nimport { BaseAPI } from './base_api'\nimport CID from 'cids'\nimport * as loopring_defs from '../defs'\nimport {\n  ChainId,\n  ConnectorError,\n  LoopringErrorCode,\n  NftData,\n  NFTFactory,\n  NFTTokenInfo,\n  ReqMethod,\n  ReqParams,\n  SIG_FLAG,\n} from '../defs'\nimport { myLog } from '../utils/log_tools'\nimport * as ethUtil from 'ethereumjs-util'\nimport { genExchangeData, sendRawTx } from './contract_api'\nimport { contracts } from './ethereum/contracts'\n\nimport BN from 'bn.js'\n\nconst CREATION_CODE = {\n  [ChainId.GOERLI]:\n    '3d602d80600a3d3981f3363d3d373d3d3d363d735854e62554ce1c146a375c370bc0d323368b372d5af43d82803e903d91602b57fd5bf3',\n  [ChainId.MAINNET]:\n    '3d602d80600a3d3981f3363d3d373d3d3d363d73b25f6d711aebf954fb0265a3b29f7b9beba7e55d5af43d82803e903d91602b57fd5bf3',\n  [ChainId.SEPOLIA]:\n    '3d602d80600a3d3981f3363d3d373d3d3d363d73f5c315fe77e81f49e3390b167b78a72bfffcf01c5af43d82803e903d91602b57fd5bf3',\n  [ChainId.TAIKOHEKLA]:\n    '',\n  [ChainId.TAIKO]:\n    '',\n  [ChainId.BASE]:\n    '',\n  [ChainId.BASESEPOLIA]:\n    '',\n}\nconst {\n  Contracts: {\n    erc721Abi: { erc721 },\n    erc1155Abi: { erc1155 },\n  },\n} = contracts\n\nexport enum NFTType {\n  ERC1155 = 0,\n  ERC721,\n}\n\nexport enum NFT_TYPE_STRING {\n  ERC1155 = 'ERC1155',\n  ERC721 = 'ERC721',\n}\n\nexport enum NFTMethod {\n  setApprovalForAll = 'setApprovalForAll',\n  isApprovedForAll = 'isApprovedForAll',\n  uri = 'uri',\n  tokenURI = 'tokenURI',\n  depositNFT = 'depositNFT',\n  balanceOf = 'balanceOf',\n  ownerOf = 'ownerOf',\n  // Deposit = 'deposit',\n  // ForceWithdraw = 'forceWithdraw'\n}\n\nexport class NFTAPI extends BaseAPI {\n  private async callContractMethod(\n    web3: any,\n    method: string,\n    data: any[],\n    contractAddress: string,\n    type: NFTType = NFTType.ERC1155,\n  ) {\n    // return _genContractData(Contracts.ERC20Token, method, data)\n    const contract = this._genContract(web3, contractAddress, type)\n    return contract.methods[method](...data).call()\n  }\n\n  private _genContractData(Contract: any, method: string, data: any) {\n    return Contract.encodeInputs(method, data)\n  }\n\n  private _genERC1155Data(method: string, data: any) {\n    return this._genContractData(contracts.Contracts.ERC1155, method, data)\n  }\n\n  private _genERC721Data(method: string, data: any) {\n    return this._genContractData(contracts.Contracts.ERC721, method, data)\n  }\n\n  private _genContract(web3: any, contractAddress: string, type: NFTType = NFTType.ERC1155) {\n    return new web3.eth.Contract(type === NFTType.ERC1155 ? erc1155 : erc721, contractAddress)\n  }\n\n  /**\n   * getNFTBalance\n   * @param web3\n   * @param tokenAddress\n   * @param account\n   * @param nftId\n   * @param nftType\n   */\n  public async getNFTBalance({\n    web3,\n    tokenAddress,\n    account,\n    nftId,\n    nftType = NFTType.ERC1155,\n  }: loopring_defs.UserNFTBalanceParam): Promise<{\n    count?: string\n  }> {\n    try {\n      if (nftType === NFTType.ERC721) {\n        const result: string = await this.callContractMethod(\n          web3,\n          NFTMethod.ownerOf,\n          [nftId],\n          tokenAddress,\n          nftType,\n        )\n        if (result.toLowerCase() === account.toLowerCase()) {\n          return {\n            count: '1',\n          }\n        } else {\n          return {\n            count: '0',\n          }\n        }\n      } else {\n        const result: string = await this.callContractMethod(\n          web3,\n          NFTMethod.balanceOf,\n          [account, web3.utils.hexToNumberString(nftId)],\n          tokenAddress,\n          nftType,\n        )\n        return {\n          count: result.toString(),\n        }\n      }\n    } catch (err) {\n      return {\n        ...(err as any),\n        code: LoopringErrorCode.CONTRACTNFT_BALANCE,\n        message: ConnectorError.CONTRACTNFT_BALANCE,\n      }\n    }\n  }\n\n  /**\n   * getInfoForNFTTokens\n   * @param nftDatas NftData[]\n   */\n  public async getInfoForNFTTokens({\n    nftDatas,\n  }: {\n    nftDatas: NftData[]\n  }): Promise<{ [key: string]: NFTTokenInfo } | undefined> {\n    try {\n      const reqParams: ReqParams = {\n        sigFlag: SIG_FLAG.NO_SIG,\n        url: loopring_defs.LOOPRING_URLs.GET_NFTs_INFO,\n        method: ReqMethod.GET,\n        queryParams: { nftDatas: nftDatas.join(',') },\n      }\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      if (raw_data?.resultInfo) {\n        return {\n          ...raw_data?.resultInfo,\n        }\n      }\n      const result = raw_data.reduce(\n        (prev: { [key: string]: NFTTokenInfo }, item: NFTTokenInfo) => {\n          if (item.nftId && item.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.nftId.replace('0x', ''), 16)\n            item.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n          }\n          prev[item.nftData] = item\n          return prev\n        },\n        {},\n      )\n      return {\n        ...result,\n        raw_data,\n      }\n    } catch (err) {\n      return undefined\n    }\n  }\n\n  public async callRefreshNFT(\n    request: loopring_defs.CallRefreshNFT,\n  ): Promise<{ status: string; createdAt: number; updatedAt: number } | undefined> {\n    try {\n      const reqParams: ReqParams = {\n        sigFlag: SIG_FLAG.NO_SIG,\n        bodyParams: request,\n        url: loopring_defs.LOOPRING_URLs.POST_NFT_VALIDATE_REFRESH_NFT,\n        method: ReqMethod.POST,\n      }\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      if (raw_data?.resultInfo) {\n        return {\n          ...raw_data?.resultInfo,\n        }\n      }\n      const result = raw_data.reduce(\n        (prev: { [key: string]: NFTTokenInfo }, item: NFTTokenInfo) => {\n          if (item.nftId && item.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.nftId.replace('0x', ''), 16)\n            item.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n          }\n          prev[item.nftData] = item\n          return prev\n        },\n        {},\n      )\n      return {\n        ...result,\n        raw_data,\n      }\n    } catch (err) {\n      return undefined\n    }\n  }\n\n  /**\n   * getContractNFTMeta\n   * @param web3\n   * @param tokenAddress\n   * @param _id\n   * @param nftType\n   */\n  public async getContractNFTMeta(\n    { web3, tokenAddress, nftId, nftType = NFTType.ERC1155 }: loopring_defs.ContractNFTMetaParam,\n    _IPFS_META_URL: string = loopring_defs.LOOPRING_URLs.IPFS_META_URL,\n  ) {\n    try {\n      myLog(tokenAddress, 'nftid', nftId, web3.utils.hexToNumberString(nftId))\n      let result: string\n      result = await this.callContractMethod(\n        web3,\n        nftType === NFTType.ERC1155 ? NFTMethod.uri : NFTMethod.tokenURI,\n        [web3.utils.hexToNumberString(nftId)],\n        tokenAddress,\n        nftType,\n      )\n      result = result.replace(/^ipfs:\\/\\/(ipfs\\/)?/, loopring_defs.LOOPRING_URLs.IPFS_META_URL)\n      result = result.replace('{id}', web3.utils.hexToNumberString(nftId))\n      return await fetch(result).then((response) => response.json())\n    } catch (err) {\n      return {\n        code: LoopringErrorCode.CONTRACTNFT_URI,\n        message: ConnectorError.CONTRACTNFT_URI,\n        ...(err as any),\n      }\n    }\n  }\n\n  /**\n   * approveNFT\n   * @param web3\n   * @param from  The address that deposits the funds to the exchange\n   * @param to  The address deposits to\n   * @param nftId the nftId\n   * @param chainId\n   * @param nftType The type of NFTAction contract address (ERC721/ERC1155/...)\n   * @param nonce\n   * @param gasPrice\n   * @param gasLimit\n   * @param sendByMetaMask\n   */\n  public async approveNFT({\n    web3,\n    from,\n    depositAddress,\n    tokenAddress,\n    nftId,\n    nftType = NFTType.ERC1155,\n    gasPrice,\n    gasLimit,\n    chainId,\n    nonce,\n    approved = true,\n    sendByMetaMask = true,\n  }: loopring_defs.ApproveParam) {\n    let data: any\n\n    if (nftType === NFTType.ERC1155) {\n      data = this._genERC1155Data(NFTMethod.setApprovalForAll, {\n        operator: depositAddress,\n        approved,\n      })\n    } else if (nftType === NFTType.ERC721) {\n      data = this._genERC721Data(NFTMethod.setApprovalForAll, {\n        operator: depositAddress,\n        approved,\n      })\n    }\n    try {\n      return await sendRawTx(\n        web3,\n        from,\n        tokenAddress,\n        '0',\n        data,\n        chainId,\n        nonce,\n        gasPrice,\n        gasLimit,\n        sendByMetaMask,\n      )\n    } catch (err) {\n      return {\n        ...(err as any),\n        code: LoopringErrorCode.CONTRACTNFT_SET_APPROVE,\n        message: ConnectorError.CONTRACTNFT_SET_APPROVE,\n      }\n    }\n  }\n  public ipfsCid0ToNftID(cidV0Str: string): string {\n    // eslint-disable-next-line @typescript-eslint/no-var-requires\n    const cid = new CID(cidV0Str)\n    const hashHex = Buffer.from(cid.multihash.slice(2)).toString('hex')\n    const hashBN = new BN(hashHex, 16)\n    return '0x' + hashBN.toString('hex').padStart(64, '0')\n  }\n\n  /**\n   *\n   * @param nftId  16\n   */\n  public ipfsNftIDToCid(nftId: string) {\n    const hashBN = new BN(nftId.replace('0x', ''), 16)\n    const hex = hashBN.toString(16, 64)\n    const buf = Buffer.from('1220' + hex, 'hex')\n    const cid = new CID(buf)\n    return cid.toString()\n  }\n  /**\n   * isApprovedForAll\n   * @param web3\n   * @param from The address that deposits the funds to the exchange\n   * @param exchangeAddress loopring exchange address\n   * @param nftType  NFTType\n   * @param tokenAddress  The address of NFT token\n   */\n  public async isApprovedForAll({\n    web3,\n    from,\n    exchangeAddress,\n    nftType = NFTType.ERC1155,\n    tokenAddress,\n  }: loopring_defs.IsApproveParam) {\n    try {\n      const result = await this.callContractMethod(\n        web3,\n        NFTMethod.isApprovedForAll,\n        [from, exchangeAddress],\n        tokenAddress,\n        nftType,\n      )\n      return result\n    } catch (err) {\n      return {\n        ...(err as any),\n        code: LoopringErrorCode.CONTRACTNFT_IS_APPROVE,\n        message: ConnectorError.CONTRACTNFT_IS_APPROVE,\n      }\n    }\n  }\n\n  /**\n   * @DepositParam  an NFTAction to the specified account.\n   * @param web3\n   * @param from The address that deposits the funds to the exchange\n   * @param to The account owner's address receiving the funds\n   * @param nftType The type of NFTAction contract address (ERC721/ERC1155/...)\n   * @param tokenAddress The address of NFTAction token\n   * @param nftId The token type 'id`.\n   * @param amount The amount of tokens to deposit.\n   * @param nonce: number,\n   * @param gasPrice: number,\n   * @param gasLimit: number,\n   * @param extraData Optional extra data used by the deposit contract.\n   * @param chainId  0|5\n   * @param sendByMetaMask boolean\n   */\n  public async depositNFT({\n    web3,\n    from,\n    exchangeAddress,\n    nftType = NFTType.ERC1155,\n    tokenAddress,\n    nftId,\n    amount,\n    gasPrice,\n    gasLimit,\n    chainId = ChainId.MAINNET,\n    nonce,\n    extraData,\n    sendByMetaMask = true,\n  }: loopring_defs.DepositNFTParam) {\n    const data = genExchangeData(NFTMethod.depositNFT, {\n      from,\n      to: from,\n      nftType,\n      tokenAddress,\n      nftId,\n      amount,\n      extraData: extraData ? extraData : '',\n    })\n    // myLog('depositNFT data',data)\n    return await sendRawTx(\n      web3,\n      from,\n      exchangeAddress,\n      '0',\n      data,\n      chainId as ChainId,\n      nonce,\n      gasPrice,\n      gasLimit,\n      sendByMetaMask,\n    )\n  }\n\n  /**\n   *\n   * @function computeNFTAddress\n   * @param owner {string} nftOwner address\n   * @param nftFactory {string} Hash address\n   * @return tokenAddress\n   * @throws Error\n   */\n  public computeNFTAddress({\n    nftOwner,\n    nftFactory = '0xDB42E6F6cB2A2eFcF4c638cb7A61AdE5beD82609',\n    nftBaseUri = '',\n  }: {\n    nftOwner: string\n    nftFactory?: string\n    nftBaseUri?: string\n  }): { tokenAddress: string } {\n    try {\n      if (!nftFactory) {\n        nftFactory = NFTFactory[this.chainId]\n      }\n      if (nftOwner.startsWith('0x')) {\n        nftOwner = nftOwner.slice(2)\n      }\n\n      const saltBuf = Buffer.concat([\n        Buffer.from('NFT_CONTRACT_CREATION', 'utf8'),\n        Buffer.from(nftOwner, 'hex'),\n        Buffer.from(nftBaseUri, 'utf8'),\n      ])\n\n      const codeHash = ethUtil.keccak(Buffer.from(CREATION_CODE[this.chainId], 'hex'))\n\n      const saltHash = ethUtil.keccak(saltBuf)\n\n      const rawBuf = Buffer.concat([\n        Buffer.from('ff', 'hex'),\n        Buffer.from(nftFactory.slice(2), 'hex'),\n        saltHash,\n        codeHash,\n      ])\n\n      const addr = ethUtil.keccak(rawBuf).slice(12).toString('hex')\n      return {\n        tokenAddress: ethUtil.toChecksumAddress('0x' + addr),\n      }\n    } catch (err) {\n      return err as any\n    }\n  }\n\n  public async getPublicCollectionById<R extends loopring_defs.CollectionMeta>(request: {\n    id: string\n  }): Promise<({ raw_data: R } & loopring_defs.CollectionMeta) | loopring_defs.RESULT_INFO> {\n    try {\n      const reqParams: ReqParams = {\n        sigFlag: SIG_FLAG.NO_SIG,\n        queryParams: request,\n        url: loopring_defs.LOOPRING_URLs.GET_NFT_COLLECTION_PUBLISH,\n        method: ReqMethod.GET,\n      }\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      if (raw_data?.resultInfo) {\n        return {\n          ...raw_data?.resultInfo,\n        }\n      }\n      const result = raw_data as loopring_defs.CollectionMeta\n      return {\n        ...result,\n        raw_data,\n      }\n    } catch (err) {\n      return {\n        ...(err as any),\n        code: exports.LoopringErrorCode.SKD_UNKNOW,\n      }\n    }\n  }\n\n  async getCollectionWholeNFTs<R>(request: loopring_defs.GetCollectionWholeNFTsRequest) {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_COLLECTION_WHOLE_NFTS,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    if (raw_data.nftTokenInfos.length) {\n      raw_data.nftTokenInfos = raw_data.nftTokenInfos.reduce(\n        (prev: loopring_defs.UserNFTBalanceInfo[], item: loopring_defs.UserNFTBalanceInfo) => {\n          if (item.nftId && item.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.nftId.replace('0x', ''), 16)\n            item.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            if (\n              request.metadata === true &&\n              item.metadata &&\n              item.metadata.nftId &&\n              item.metadata.nftId.startsWith('0x')\n            ) {\n              // const hashBN = new BN(item.metadata.nftId.replace(\"0x\", \"\"), 16);\n              item.metadata.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            }\n          }\n          return [...prev, item]\n        },\n        [],\n      )\n      // const hashBN = new BN(raw_data.transactions.metadata.nftId.replace(\"0x\", \"\"), 16);\n      // raw_data.transactions.metadata.nftId= \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTBalances: raw_data.nftTokenInfos as loopring_defs.UserNFTBalanceInfo[],\n      raw_data,\n    }\n  }\n  async getHadUnknownCollection<R>(request: { accountId: number }): Promise<boolean> {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_HAD_UNKNOWN_COLLECTION,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return raw_data\n  }\n  async getUserNFTBurnAddress<R>(request: {\n    accountId: number\n    tokenId: number\n  }): Promise<boolean> {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_BURN_ADDRESS,\n      queryParams: request,\n      method: ReqMethod.GET,\n      sigFlag: SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return raw_data\n  }\n}\n"
  },
  {
    "path": "src/api/rabbitWithdraw_api.ts",
    "content": "import { BaseAPI } from './base_api'\nimport * as loopring_defs from '../defs'\nimport {RabbitWithdrawRequest} from '../defs'\nimport { ethers, utils  } from 'ethers';\nimport { get_EddsaSig_Transfer } from './sign/sign_tools';\nimport { AxiosResponse } from 'axios';\n\nconst {_TypedDataEncoder} = utils\n\ninterface CounterFactualInfo {\n  walletFactory: string;\n  walletOwner: string;\n  walletSalt: string;\n}\n\nexport class RabbitWithdrawAPI extends BaseAPI {\n  public async getConfig(): Promise<{ config: string }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_RABBIT_WITHDRAW_CONFIG, // You'll need to add this URL in url_defs.ts\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const data = (await this.makeReq().request(reqParams)).data\n    return data as {\n      config: string\n    }\n  }\n  public async getNetworkWithdrawalAgents(req: {\n    tokenId: number\n    amount: string\n    network: string\n  }): Promise<\n    {\n      address: string\n      tokenId: number\n      symbol: string\n      totalAmount: string\n      freezeAmount: string\n      timestamp: number\n    }[]\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: req,\n      url: loopring_defs.LOOPRING_URLs.GET_NETWORK_WITHDRAWAL_AGENTS, // You'll need to add this URL in url_defs.ts\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const data = (await this.makeReq().request(reqParams)).data\n    return data\n  }\n\n  public async submitRabitWithdraw(\n    req: RabbitWithdrawRequest,\n    extra: {\n      signer: ethers.providers.JsonRpcSigner\n      chainId: number\n      exchangeAddr: string\n      eddsaSignKey: string\n    },\n  ): Promise<{\n    hash: string\n    status: string\n    isIdempotent: boolean\n    accountId: number\n    tokenId: number\n    storageId: number\n  }> {\n    const { signer, chainId, exchangeAddr } = extra\n    const mapRequestToTypedData = (request: Record<string, any>) => {\n      return {\n        fromNetwork: request['fromNetwork'],\n        toNetwork: request['toNetwork'],\n        withdrawToAddr: request['toAddress'],\n        payerId: request['transfer']['payerId'],\n        payerAddr: request['transfer']['payerAddr'],\n        payeeId: request['transfer']['payeeId'],\n        payeeAddr: request['transfer']['payeeAddr'],\n        tokenID: request['transfer']['token']['tokenId'],\n        amount: request['transfer']['token']['volume'],\n        feeTokenID: request['transfer']['maxFee']['tokenId'],\n        maxFee: request['transfer']['maxFee']['volume'],\n        validUntil: request['transfer']['validUntil'],\n        storageID: request['transfer']['storageId'],\n      } as Record<string, any>\n    }\n\n    const signFastWithdrawTypedData = (args: {\n      signer: ethers.providers.JsonRpcSigner\n      chainId: number\n      exchangeAddress: string\n      data: Record<string, any>\n    }) => {\n      const { signer, chainId, exchangeAddress } = args\n      const domain = {\n        name: 'Loopring Protocol',\n        version: '3.6.0',\n        chainId: chainId,\n        verifyingContract: exchangeAddress,\n      }\n      const types = {\n        RabbitWithdraw: [\n          { type: 'uint32', name: 'payerId' },\n          { type: 'address', name: 'payerAddr' },\n          { type: 'uint32', name: 'payeeId' },\n          { type: 'address', name: 'payeeAddr' },\n          { type: 'uint16', name: 'tokenID' },\n          { type: 'uint96', name: 'amount' },\n          { type: 'uint16', name: 'feeTokenID' },\n          { type: 'uint96', name: 'maxFee' },\n          { type: 'uint32', name: 'validUntil' },\n          { type: 'uint32', name: 'storageID' },\n          { type: 'string', name: 'fromNetwork' },\n          { type: 'string', name: 'toNetwork' },\n          { type: 'address', name: 'withdrawToAddr' },\n        ],\n      }\n      console.log('EIP712 hash', _TypedDataEncoder.hash(domain, types, args.data))\n      return signer._signTypedData(domain, types, args.data)\n    }\n    const ecdsaSignature = await signFastWithdrawTypedData({\n      signer: signer,\n      chainId: chainId,\n      exchangeAddress: exchangeAddr,\n      data: mapRequestToTypedData(req),\n    })\n    const eddsaSignature = get_EddsaSig_Transfer(req.transfer, extra.eddsaSignKey).result\n    const reqParams: loopring_defs.ReqParams = {\n      bodyParams: {\n        ...req,\n        transfer: { ...req.transfer, eddsaSignature },\n      },\n      url: loopring_defs.LOOPRING_URLs.POST_RABBIT_WITHDRAW, // You'll need to add this URL in url_defs.ts\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature: ecdsaSignature,\n    }\n    const data = (await this.makeReq().request(reqParams)).data\n    return data\n  }\n  \n  public async getUserCrossChainFee<R>(\n    request: loopring_defs.GetUserCrossChainFeeRequest,\n    apiKey: string,\n  ): Promise<{\n    gasPrice: string\n    fees: {\n      token: string\n      tokenId: number\n      fee: string\n      discount: number\n    }[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_CROSSCHAIN_OFFCHAIN_FEE_AMT,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    return raw_data\n  }\n}\n"
  },
  {
    "path": "src/api/request.ts",
    "content": "import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'\nimport { SIG_FLAG, ReqParams, ReqOptions } from '../defs/loopring_enums'\nimport { getEdDSASig, getEdDSASigWithPoseidon } from './sign/sign_tools'\nimport { sortObject } from '../utils/obj_tools'\n\n/**\n *\n * @export\n */\nexport const setSearchParams = function (url: URL, ...objects: any[]) {\n  const searchParams = new URLSearchParams(url.search)\n\n  for (const object of objects) {\n    if (object) {\n      const objectTmp = sortObject(object)\n      for (const key in objectTmp) {\n        if (objectTmp[key] != undefined) searchParams.set(key, objectTmp[key])\n      }\n    }\n  }\n\n  url.search = searchParams.toString()\n}\n\n/**\n *\n * @export\n */\nexport const serializeDataIfNeeded_For_SetReffer = function (value: any) {\n  return JSON.stringify(value, Object.keys(value).sort())\n}\n\nexport const serializeDataIfNeeded = function (value: any) {\n  const nonString = typeof value !== 'string'\n\n  return nonString ? JSON.stringify(value !== undefined ? sortObject(value) : {}) : value || ''\n}\n\n/**\n *\n * @export\n */\nexport const toPathString = function (url: URL) {\n  return url.pathname + url.search + url.hash\n}\n\nexport class Request {\n  private _axios: AxiosInstance\n\n  private baseOptions: any = {}\n\n  public getIns() {\n    return this._axios\n  }\n\n  constructor(baseUrl: string, timeout: number) {\n    this.baseOptions = {\n      baseURL: baseUrl,\n      timeout: timeout,\n\n      headers: {\n        // 'Accept': '*/*',\n        // 'Accept-Encoding': 'gzip, deflate, br',\n        feeVersion: 'v2',\n        'Content-Type': 'application/json',\n        pf: 'web', // tag for recognizing source\n      },\n\n      validateStatus: function (status: any) {\n        if ((status >= 200 && status < 300) || status === 400) {\n          return true\n        }\n        return false\n        // return true // always true, handle exception in each bussiness logic\n      },\n\n      insecure: true,\n    }\n\n    this._axios = axios.create(this.baseOptions)\n  }\n\n  public async request(params: ReqParams, options: any = {}) {\n    const localUrl = new URL(params.url, this.baseOptions.baseURL)\n\n    const localVarRequestOptions = { method: params.method, ...options }\n\n    setSearchParams(localUrl, params?.queryParams)\n\n    const urlPathStr = toPathString(localUrl)\n\n    let headers: any = {}\n\n    if (params?.apiKey) {\n      headers['X-API-KEY'] = params?.apiKey\n    }\n\n    let sig: any = params.sigObj?.sig\n\n    if (params.sigFlag !== SIG_FLAG.NO_SIG && !params?.sigObj?.dataToSig) {\n      throw Error('no dataToSig field!')\n    }\n\n    switch (params.sigFlag) {\n      case SIG_FLAG.NO_SIG:\n        break\n      case SIG_FLAG.EDDSA_SIG_POSEIDON:\n        sig = getEdDSASigWithPoseidon(params.sigObj?.dataToSig, params.sigObj?.PrivateKey).result\n        break\n      case SIG_FLAG.EDDSA_SIG:\n        sig = getEdDSASig(\n          params.method,\n          this.baseOptions.baseURL,\n          params.url,\n          params.sigObj?.dataToSig,\n          params.sigObj?.PrivateKey,\n        )\n        break\n      default:\n        break\n    }\n\n    if (sig) {\n      headers['X-API-SIG'] = sig\n    } else if (params?.ecdsaSignature) {\n      headers['X-API-SIG'] = params?.ecdsaSignature\n    } else if (params?.eddsaSignature) {\n      headers['X-API-SIG'] = params?.eddsaSignature\n    }\n\n    if (params?.eddsaSignatureREFER && params.sigObj?.PrivateKey) {\n      const sig = getEdDSASig(\n        params.method,\n        this.baseOptions.baseURL,\n        params.url,\n        params.sigObj?.dataToSig,\n        params.sigObj?.PrivateKey,\n      )\n      headers['X-API-SIG-REFER'] = sig\n    }\n\n    // myLog('headers[\"X-API-SIG\"]', headers[\"X-API-SIG\"]);\n    if (params?.bodyParams) {\n      const bodyParams = params?.bodyParams\n      if (sig && params.sigObj?.sigPatch) {\n        bodyParams[params.sigObj?.sigPatch] = sig\n      }\n\n      if (params?.ecdsaSignature) {\n        bodyParams.ecdsaSignature = params?.ecdsaSignature\n      }\n\n      if (params?.eddsaSignature) {\n        bodyParams.eddsaSignature = params?.eddsaSignature\n      }\n\n      localVarRequestOptions.data = serializeDataIfNeeded(bodyParams)\n    }\n\n    headers = { ...this.baseOptions.headers, ...headers }\n\n    const optInOne = {\n      ...this.baseOptions,\n      headers: {\n        ...headers,\n        ...params.extraHeaders,\n      },\n      ...localVarRequestOptions,\n      url: this.baseOptions.baseURL + urlPathStr,\n    }\n\n    // myLog(optInOne);\n    // myLog(\"headers config\", optInOne);\n    return await this._axios.request(optInOne)\n  }\n\n  public updateOpt(reqOpt: ReqOptions) {\n    // @ts-ignore\n    this._axios.interceptors.request.use((req: AxiosRequestConfig) => {\n      if (reqOpt?.baseUrl) {\n        req.baseURL = reqOpt?.baseUrl\n      }\n      if (reqOpt?.url) {\n        req.url = reqOpt?.url\n      }\n      req.headers = req.headers ?? {}\n      if (reqOpt?.apiKey) {\n        req.headers['X-API-KEY'] = reqOpt?.apiKey\n      }\n      if (reqOpt?.signature) {\n        req.headers['X-API-SIG'] = reqOpt?.signature\n      }\n      return req\n    })\n    return this\n  }\n\n  public addApiKey(apiKey: string) {\n    return this.updateOpt({ apiKey })\n  }\n\n  public addSig(signature: string) {\n    return this.updateOpt({ signature })\n  }\n\n  public updateBaseUrl(baseUrl: string) {\n    return this.updateOpt({ baseUrl })\n  }\n\n  public handle400(callback: any = undefined) {\n    this._axios.interceptors.response.use((res: AxiosResponse) => {\n      if (res.status == 400) {\n        // eslint-disable-next-line no-console\n        console.log(res.request + ' got ' + res.statusText)\n      }\n\n      if (callback) {\n        callback()\n      }\n\n      return res\n    })\n  }\n}\n"
  },
  {
    "path": "src/api/sign/poseidon/EDDSAUtil.ts",
    "content": "import { BigNumber } from \"ethers\";\nimport { SignatureScheme } from \"./eddsa\";\nimport { FQ } from \"./field\";\nimport { jubjub } from \"./jubjub\";\nimport { babyJub } from \"./babyJub\";\n\nexport class EDDSAUtil {\n  \n  static sign(PrivateKey: string | undefined, hash: any) {\n    const strKey = BigNumber.from(PrivateKey)\n    const msg = BigNumber.from(hash)\n\n    // console.log(\"strKey\", strKey.toString())\n    // console.log(\"msg\", msg.toString())\n    const copyKey = new FQ(strKey)\n    const B = SignatureScheme.B()\n    const signed = SignatureScheme.sign(msg, copyKey, B)\n    // console.log(\"signed\", signed.toStr())\n    const x = EDDSAUtil.formatted(signed.sig.R.x.n.toHexString().slice(2))\n    const y = EDDSAUtil.formatted(signed.sig.R.y.n.toHexString().slice(2))\n    const s = EDDSAUtil.formatted(signed.sig.s.n.toHexString().slice(2))\n    const result = `0x${x}${y}${s}`\n    // console.log(\"result\", result)\n    return {\n      \"Rx\": signed.sig.R.x.n.toString(),\n      \"Ry\": signed.sig.R.y.n.toString(),\n      \"s\": signed.sig.s.n.toString()\n    }\n  }\n\n  static formatted(hexString: string) {\n    const outputLength = 32 * 2\n    const more = outputLength - hexString.length\n    if (more > 0) {\n      for (let i = 0; i < more; i++) {\n        hexString = \"0\" + (hexString)\n      }\n    } else {\n      hexString = hexString.slice(0, outputLength)\n    }\n    return hexString\n  }\n\n  static generateKeyPair(seed: any) {\n    let bigInt = BigNumber.from(0)\n    for (let i = 0; i < seed.length; i++) {\n      const item = seed[i]\n      const itemBigInt = BigNumber.from(item)\n      const tmp = BigNumber.from(\"256\").pow(BigNumber.from(i))\n      bigInt = bigInt.add(itemBigInt.mul(tmp))\n    }\n    // console.log(\"sum\", bigInt.toString())\n    const secretKey = bigInt.mod(jubjub.JUBJUB_L)\n    // console.log(\"secretKey\", secretKey.toString())\n\n    const copySecretKey = BigNumber.from(secretKey.toString())\n    // console.log(\"copySecretKey\", copySecretKey.toString())\n\n    const B = SignatureScheme.B()\n    // console.log(\"B\", B.toString())\n\n    const publicKey = B.mul(copySecretKey)\n    // console.log(\"publicKey\", publicKey.x.n.toString(), publicKey.y.n.toString())\n\n    const keyPair = {\n      \"publicKeyX\": publicKey.x.n.toString(),\n      \"publicKeyY\": publicKey.y.n.toString(),\n      \"secretKey\": secretKey.toString()\n    }\n\n    return keyPair\n  }\n\n  static pack(publicKeyX: string, publicKeyY: string) {\n    const P0 = BigNumber.from(publicKeyX)\n    const P1 = BigNumber.from(publicKeyY)\n    const newPack = babyJub.packPoint(P0, P1)\n    return newPack\n  }\n\n}\n"
  },
  {
    "path": "src/api/sign/poseidon/TestsEDDSAUtil_test.ts",
    "content": "import { BigNumber } from \"ethers\";\nimport { EDDSAUtil } from \"./EDDSAUtil\";\nimport { bnToBuf, bnToBufWithFixedLength, SignatureScheme } from \"./eddsa\";\nimport { assert } from \"console\";\n\nfunction testEddsaPack_1() {\n  console.log(\"testEddsaPack\")\n\n  // Input\n  const publicKeyX = \"0x10440b6de1fc92536e20501e7513b5ca78d4c8c876450d97cfc2a4e24a4c67c7\"\n  const publicKeyY = \"0x10dfbb7cd80bde2eeedbf9e0fad12819ca20be36b96a7f28c37c6a7550ed366c\"\n\n  // Output\n  const eddsaPackOutput = \"10dfbb7cd80bde2eeedbf9e0fad12819ca20be36b96a7f28c37c6a7550ed366c\"\n\n  const packed = EDDSAUtil.pack(publicKeyX, publicKeyY)  \n  assert(packed === eddsaPackOutput)\n  console.log(\"testEddsaPack passed\")\n}\n\nfunction testEddsaPack_2() {\n  console.log(\"testEddsaPack\")\n\n  // Input\n  const publicKeyX = \"0x191f8455196d7c9116065b69a745edbe3f5b6193125f48d818e16101b0ebd13f\"\n  const publicKeyY = \"0x0729569e74800ba4344767d608ec54f12b14cc4404a8726b5f73ebf8b58f9a09\"\n\n  // Output\n  const eddsaPackOutput = \"8729569e74800ba4344767d608ec54f12b14cc4404a8726b5f73ebf8b58f9a09\"\n\n  const packed = EDDSAUtil.pack(publicKeyX, publicKeyY)  \n  assert(packed === eddsaPackOutput)\n  console.log(\"testEddsaPack passed\")\n}\n\nfunction testEddsaPack_3() {\n  console.log(\"testEddsaPack\")\n\n  // Input\n  const publicKeyX = \"0x1ae187c43a6b534be1ac60b335d5cc8c12a9d479339e5ce4134315e20c2940c4\"\n  const publicKeyY = \"0x16fb785193a8657feb41b7944afde61fe05ea519621fa0f19d872a8fbba83463\"\n\n  // Output\n  const eddsaPackOutput = \"96fb785193a8657feb41b7944afde61fe05ea519621fa0f19d872a8fbba83463\"\n\n  const packed = EDDSAUtil.pack(publicKeyX, publicKeyY)  \n  assert(packed === eddsaPackOutput)\n  console.log(\"testEddsaPack passed\")\n}\n\nfunction testEddsaSign() {\n  console.log(\"testEddsaSign\")\n  const strKey = \"1965533437444427599736796973543479035828634172708055838572430750620147597402\"\n  const msg = \"20823375595941673465102915960468301465677704522962441935281926279865178787657\"\n  const result = EDDSAUtil.sign(strKey, msg)\n  // assert(result == \"0x04ad08469a4a8622a661a793615ebddfa6ea2b72c8f1b02e33288ea2bd71cede0ed7f67939097ab95d3c9d8647e198f4ef523bf6cfb8da0ead89a57e27eff0d12ea6ac32cc118b1bc0aeb8f1be37f317f399197f9e41c8a90ecfe9e296be42e5\")\n  console.log(result.Rx)\n  console.log(result.Ry)\n  console.log(result.s)\n  \n  assert(result.Rx === \"2114973053955517366033592592501464590076342821657201629830614924692550700766\")\n  assert(result.Ry === \"6713953096854639492359183468711112854151280690992619923536842965423886430417\")\n  assert(result.s === \"21100876117443371431735908718802018647851328087147897184613053393129281831653\")\n\n  console.log(\"testEddsaSign passed\")\n}\n\nfunction test_generateKeyPair() {\n  console.log(\"generateKeyPair\")\n  const seedHex = \"0x\" + \"7f16a4c491d3494c3bc8ef097e7c123a9da6fa8167631efd5f82b89e803b0682\"\n  const seed = BigNumber.from(seedHex)\n  console.log(`seed ${seed.toString()}`)\n  const bitIntDataItems = bnToBufWithFixedLength(seed.toString(), 32);\n  console.log(`bigIntData ${bitIntDataItems}`)\n  \n  const keyPair = EDDSAUtil.generateKeyPair(bitIntDataItems)\n\n  assert(keyPair.publicKeyX === \"18584920749226215196041463810216086509508234553287520526360090588893385486657\")\n  assert(keyPair.publicKeyY === \"4521439321743413283487130903749053907482128013050103604539374548984130428531\")\n\n  console.log(\"generateKeyPair passed\")\n}\n\nfunction main() {\n  console.log(\"\\n\\TestsEDDSAUtil_test\\n\")\n  // testEddsaPack_1()\n  // testEddsaPack_2()\n  // testEddsaPack_3()\n  test_generateKeyPair()\n  // testEddsaSign()\n}\n\nmain();"
  },
  {
    "path": "src/api/sign/poseidon/babyJub.ts",
    "content": "import { BigNumber } from \"ethers\";\nimport { SignatureScheme, bytesToHexString } from \"./eddsa\";\nimport { field } from \"./field\";\n\n\nexport class babyJub {\n  \n  static packPoint(P0: BigNumber, P1: BigNumber) {\n    const packed = SignatureScheme.to_bytes(P1).reverse()\n    // console.log(\"packed\", packed)\n    if (babyJub.lt(P0, BigNumber.from(\"0\"))) {\n      // console.log(\"Update .... lt \")\n      packed[0] = packed[0] | 0x80\n    }\n    const hexStr = bytesToHexString(packed)\n    // console.log(\"hexStr\", hexStr)\n    return hexStr\n  }\n\n  static lt(a: BigNumber, b: BigNumber) {\n    const half = field.SNARK_SCALAR_FIELD.div(BigNumber.from(\"2\"))\n    const p = field.SNARK_SCALAR_FIELD\n    let aa: BigNumber\n    let bb: BigNumber\n    if (a.gt(half)) {\n      aa = a.sub(p)\n    } else {\n      aa = a\n    }\n    if (b.gt(half)) {\n      bb = b.sub(p)\n    } else {\n      bb = b\n    }\n    // console.log(\"lt\", a.toString(), b.toString(), aa.toString(), bb.toString());\n    return aa.lt(bb)\n  }\n\n  static gt(a: BigNumber, b: BigNumber) {\n    const half = field.SNARK_SCALAR_FIELD.div(BigNumber.from(\"2\"))\n    const p = field.SNARK_SCALAR_FIELD\n    let aa: BigNumber\n    let bb: BigNumber\n    if (a.gt(half)) {\n      aa = a.sub(p)\n    } else {\n      aa = a\n    }\n    if (b.gt(half)) {\n      bb = b.sub(p)\n    } else {\n      bb = b\n    }\n    // console.log(\"gt\", a.toString(), b.toString(), aa.toString(), bb.toString());\n    return aa.gt(bb)\n  }\n\n}\n"
  },
  {
    "path": "src/api/sign/poseidon/eddsa.ts",
    "content": "/*\nImplements Pure-EdDSA and Hash-EdDSA\n\nThe signer has two secret values:\n\n    * k = Secret key\n    * r = Per-(message,key) nonce\n\nThe signer provides a signature consiting of two values:\n\n    * R = Point, image of `r*B`\n    * s = Image of `r + (k*t)`\n\nThe signer provides the verifier with their public key:\n\n    * A = k*B\n\nBoth the verifier and the signer calculate the common reference string:\n\n    * t = H(R, A, M)\n\nThe nonce `r` is secret, and protects the value `s` from revealing the\nsigners secret key.\n\nFor Hash-EdDSA, the message `M` is compressed before H(R,A,M)\n\nFor further information see: https://ed2519.cr.yp.to/eddsa-20150704.pdf\n*/\n\nimport { BigNumber } from \"ethers\";\nimport { field, FQ } from \"./field\";\nimport { jubjub, Point } from \"./jubjub\";\nimport { sha512 } from \"js-sha512\";\nimport { permunation, PoseidonParams } from \"./permutation\";\n\nexport class Signature {\n  public R: Point;\n  public s: FQ;\n\n  constructor(R: Point, s: FQ) {\n    this.R = R;\n    this.s = s;\n  }\n\n  toStr() {\n    return `${this.R.x.n} ${this.R.y.n} ${this.s.n}`;\n  }\n}\n\nexport class SignedMessage {\n  public A: Point;\n  public sig: Signature;\n  public msg: BigNumber;\n\n  constructor(A: Point, sig: Signature, msg: BigNumber) {\n    this.A = A;\n    this.sig = sig;\n    this.msg = msg;\n  }\n\n  toStr() {\n    return `${this.A.x.n} ${\n      this.A.y.n\n    } ${this.sig.toStr()} ${this.msg.toString()}`;\n  }\n}\n\nexport class SignatureScheme {\n  static to_bytes(arg: BigNumber) {\n    const outputLength = 32;\n\n    // console.log(`input ${arg.toString()}`)\n\n    let bitIntDataItems = bnToBuf(arg.toString());\n    // console.log(`bigIntData ${bitIntDataItems}`)\n\n    const more = outputLength - bitIntDataItems.length;\n    // console.log('more', more)\n    if (more > 0) {\n      for (let i = 0; i < more; i++) {\n        bitIntDataItems = [0].concat(bitIntDataItems);\n      }\n    } else {\n      bitIntDataItems = bitIntDataItems.slice(0, outputLength);\n    }\n\n    bitIntDataItems = bitIntDataItems.reverse();\n    // console.log(`bigIntData return ${bitIntDataItems}`)\n    return bitIntDataItems;\n  }\n\n  /*\n  Identity function for message\n\n  Can be used to truncate the message before hashing it\n  as part of the public parameters.\n  */\n  static prehash_message(M: BigNumber) {\n    return M;\n  }\n\n  /*\n  Hash the key and message to create `r`, the blinding factor for this signature.\n\n  If the same `r` value is used more than once, the key for the signature is revealed.\n\n  From: https://eprint.iacr.org/2015/677.pdf (EdDSA for more curves)\n\n  Page 3:\n\n      (Implementation detail: To save time in the computation of `rB`, the signer\n      can replace `r` with `r mod L` before computing `rB`.)\n  */\n  static hash_secret_python(k: FQ, arg: BigNumber) {\n    const byteArray0 = this.to_bytes(k.n);\n    const byteArray1 = this.to_bytes(arg);\n\n    const sum = byteArray0.concat(byteArray1);\n    // console.log(\"sum\", sum)\n\n    // let byteArrayHexStr = bytesToHexString(sum)\n    // console.log(\"byteArrayHexStr\", byteArrayHexStr)\n\n    const digest1 = sha512.array(new Uint8Array(sum).buffer);\n\n    // let digest1 = createHash('sha512').update .digest(\"SHA-512\", new Uint8Array(sum).buffer)\n    let sha512StrItems: any;\n    // console.log('digest1', digest1);\n    for (let i = 0; i < digest1.length; i++) {\n      const itemInt = digest1[i];\n      let st = itemInt.toString(16);\n      if (st.length == 1) {\n        st = \"0\" + st;\n      }\n      sha512StrItems = [st].concat(sha512StrItems);\n    }\n    const sha512MessageHexStr = sha512StrItems.join(\"\");\n    // console.log(`sha512MessageHexStr ${sha512MessageHexStr}`)\n    const sha512MessageHexStrBigInt = BigNumber.from(\n      \"0x\" + sha512MessageHexStr\n    );\n    // console.log(`sha512MessageHexStrBigInt ${sha512MessageHexStrBigInt}`)\n    const hashed = sha512MessageHexStrBigInt.mod(jubjub.JUBJUB_L);\n    // console.log(`hashed ${hashed.toString()}`)\n    return hashed;\n  }\n\n  static B() {\n    return Point.generate();\n  }\n\n  static sign(msg: BigNumber, key: FQ, B: Point) {\n    // console.log(\"B \", B.x.n.toString(), B.y.n.toString())\n\n    const copyKey = new FQ(key.n, key.m);\n    const A = B.mul(copyKey.n);\n\n    // console.log(\"A.x \", A.x.n.toString(), A.x.m.toString())\n    // console.log(\"A.y \", B.y.n.toString(), A.y.m.toString())\n\n    const M = this.prehash_message(msg);\n    // console.log(\"M \", M.toString())\n\n    const r = this.hash_secret_python(key, M);\n    // console.log(\"r \", r.toString())\n\n    const copy_r = BigNumber.from(r.toString());\n\n    const R = B.mul(copy_r);\n\n    // console.log(\"R.x \", R.x.n.toString(), R.x.m.toString())\n    // console.log(\"R.y \", R.y.n.toString(), R.y.m.toString())\n\n    const t = this.hash_public(R, A, M);\n    // console.log(\"hello world\")\n    // console.log(\"t \", t.toString())\n\n    const t_c = t;\n    const key_n_t = key.n.mul(t_c);\n    const left = r.add(key_n_t);\n    const S = left.mod(jubjub.JUBJUB_E);\n\n    // console.log(\"S \", S.toString())\n\n    const signatureResult = new Signature(R, new FQ(S));\n    // console.log(\"signatureResult\", signatureResult.toStr())\n\n    const signedMessage = new SignedMessage(A, signatureResult, msg);\n    // console.log(\"signedMessage\", signedMessage.toStr())\n\n    return signedMessage;\n  }\n\n  static as_scalar(point: Point) {\n    // console.log(`as_scalar ${point.x.n.toString()}`)\n    return [point.x.n, point.y.n];\n  }\n\n  static hash_public(R: Point, A: Point, M: BigNumber) {\n    let inputMsg: any;\n    inputMsg = this.as_scalar(R).concat(this.as_scalar(A)).concat([M]);\n    // console.log(`inputMsg ${inputMsg}`)\n    const params = new PoseidonParams(\n      field.SNARK_SCALAR_FIELD,\n      6,\n      6,\n      52,\n      \"poseidon\",\n      BigNumber.from(5),\n      null,\n      null,\n      128\n    );\n    const result = permunation.poseidon(inputMsg, params);\n    return result;\n  }\n}\n\nexport function bnToBuf(bn: string) {\n  let hex = BigInt(bn).toString(16);\n  if (hex.length % 2) {\n    hex = \"0\" + hex;\n  }\n  const len = hex.length / 2;\n  // console.log(\"length\", len);\n\n  const u8 = new Uint8Array(len);\n  let i = 0;\n  let j = 0;\n  while (i < len) {\n    u8[i] = parseInt(hex.slice(j, j + 2), 16);\n    i += 1;\n    j += 2;\n  }\n  return Array.from(u8);\n}\n\nexport function bnToBufWithFixedLength(bn: string, outputLength: number) {\n  let hex = BigInt(bn).toString(16);\n  if (hex.length % 2) {\n    hex = \"0\" + hex;\n  }\n  const len = hex.length / 2;\n\n  // console.log(\"len\", len);\n\n  const u8 = new Uint8Array(len);\n  let i = 0;\n  let j = 0;\n  while (i < len) {\n    u8[i] = parseInt(hex.slice(j, j + 2), 16);\n    i += 1;\n    j += 2;\n  }\n\n  let bitIntDataItems = Array.from(u8);\n\n  const more = outputLength - bitIntDataItems.length;\n  // console.log('diff len', more)\n  if (more > 0) {\n    for (let i = 0; i < more; i++) {\n      bitIntDataItems = [0].concat(bitIntDataItems);\n    }\n  } else {\n    bitIntDataItems = bitIntDataItems.slice(0, outputLength);\n  }\n\n  return bitIntDataItems;\n}\n\nexport function bufToBn(buf: any) {\n  let hex: any;\n  hex = [];\n  const u8 = Uint8Array.from(buf);\n\n  u8.forEach(function (i) {\n    let h = i.toString(16);\n    if (h.length % 2) {\n      h = \"0\" + h;\n    }\n    hex.push(h);\n  });\n\n  return BigInt(\"0x\" + hex.join(\"\"));\n}\n\nexport function bytesToHexString(bytes: any) {\n  let strItems: any;\n  strItems = [];\n  for (let i = 0; i < bytes.length; i++) {\n    const item = bytes[i];\n    let st = item.toString(16);\n    if (st.length == 1) {\n      st = \"0\" + st;\n    }\n    // st = st.toUpperCase()\n    strItems.push(st);\n  }\n  const strItemsJoined = strItems.join(\"\");\n  return strItemsJoined;\n}\n"
  },
  {
    "path": "src/api/sign/poseidon/eddsa_test.ts",
    "content": "import { assert } from \"console\"\nimport { BigNumber } from \"ethers\"\nimport { SignatureScheme } from \"./eddsa\"\nimport { FQ } from \"./field\"\nimport { Point } from \"./jubjub\"\n\nfunction test_sign_1() {\n  // console.log(\"test_sign_1\")\n  const startTime: any = new Date();\n  const msgHash = BigNumber.from(\"20693456676802104653139582814194312788878632719314804297029697306071204881418\")\n  const private_key = new FQ(BigNumber.from(\"1\"))\n  const signed = SignatureScheme.sign(msgHash, private_key, SignatureScheme.B())\n  assert(signed.toStr() === \"16540640123574156134436876038791482806971768689494387082833631921987005038935 20819045374670962167435360035096875258406992893633759881276124905556507972311 4991609103248925747358645194965349262579784734809679007552644294476920671344 423391641476660815714427268720766993055332927752794962916609674122318189741 4678160339597842896640121413028167917237396460457527040724180632868306529961 20693456676802104653139582814194312788878632719314804297029697306071204881418\")\n  const endTime: any = new Date();\n  let timeDiff = endTime - startTime; //in ms\n  timeDiff /= 1000;\n  // console.log(timeDiff + \" seconds\");\n  // console.log(\"test_sign_1 passed\")\n}\n\nfunction test_prehash_message_1() {\n  // console.log(\"test_prehash_message_1\")\n  const msg = BigNumber.from(\"20693456676802104653139582814194312788878632719314804297029697306071204881418\")\n  const result = SignatureScheme.prehash_message(msg)\n  assert(result.eq(BigNumber.from(\"20693456676802104653139582814194312788878632719314804297029697306071204881418\")))\n  // console.log(\"test_prehash_message_1 passed\")\n}\n\nfunction test_to_bytes_1() {\n  // console.log(\"test_to_bytes_1\")\n  const arg = BigNumber.from(\"20693456676802104653139582814194312788878632719314804297029697306071204881418\")\n  const resutls = SignatureScheme.to_bytes(arg)\n  assert(JSON.stringify(resutls) === JSON.stringify([10, 228, 215, 147, 146, 102, 9, 42, 66, 160, 26, 94, 171, 73, 235, 194, 245, 106, 249, 114, 50, 52, 155, 182, 188, 18, 133, 216, 215, 20, 192, 45]))\n  // console.log(\"test_to_bytes_1 passed\")\n}\n\nfunction test_hash_secret_1() {\n  // console.log(\"test_hash_secret_1\")\n  const startTime: any = new Date();\n  const arg = BigNumber.from(\"20693456676802104653139582814194312788878632719314804297029697306071204881418\")\n  const result = SignatureScheme.hash_secret_python(new FQ(BigNumber.from(\"1\")), arg)\n  assert(result.eq(BigNumber.from(\"456425617452149303537516185998917840598824274191970480768523181450944242406\")))\n  const endTime: any = new Date();\n  let timeDiff = endTime - startTime; //in ms\n  timeDiff /= 1000;\n  // console.log(timeDiff + \" seconds\");\n  // strip the ms\n  // console.log(\"test_hash_secret_1 passed\")\n}\n\nfunction test_hash_public_1() {\n  // console.log(\"test_hash_public_1\")\n  const R = new Point(new FQ(BigNumber.from(\"4991609103248925747358645194965349262579784734809679007552644294476920671344\")), new FQ(BigNumber.from(\"423391641476660815714427268720766993055332927752794962916609674122318189741\")))\n  const A = new Point(new FQ(BigNumber.from(\"16540640123574156134436876038791482806971768689494387082833631921987005038935\")), new FQ(BigNumber.from(\"20819045374670962167435360035096875258406992893633759881276124905556507972311\")))\n  const M = BigNumber.from(\"20693456676802104653139582814194312788878632719314804297029697306071204881418\")\n  const result = SignatureScheme.hash_public(R, A, M)\n  assert(result.eq(BigNumber.from(\"4221734722145693593102605227029250076638572186265556559955657451417362287555\")))\n  // console.log(\"test_hash_public_1 passed\")\n}\n\nfunction main() {\n  // console.log(\"\\n\\neddsa_test\\n\")\n  test_sign_1()\n  test_prehash_message_1()\n  test_to_bytes_1()\n  test_hash_secret_1()\n  test_hash_public_1()\n}\n\nmain();\n"
  },
  {
    "path": "src/api/sign/poseidon/field.ts",
    "content": "import { BigNumber } from \"ethers\";\nimport { BigInteger } from \"jsbn\";\n\nexport class field {\n  // Fq is the base field of Jubjub\n  static SNARK_SCALAR_FIELD = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n\n  // Fr is the scalar field of Jubjub\n  static FR_ORDER = BigNumber.from(\"21888242871839275222246405745257275088614511777268538073601725287587578984328\")\n}\n\n// A class for field elements in FQ. Wrap a number in this class,\n// and it becomes a field element.\nexport class FQ {\n  public m: BigNumber;\n  public n: BigNumber;\n\n  constructor(n: BigNumber, field_modulus = field.SNARK_SCALAR_FIELD) {\n    this.m = field_modulus;\n    this.n = n.mod(this.m);\n  }\n\n  //\n  // Use this.n as other\n  //\n\n  add(other: BigNumber) {\n    const on = other\n    const n = (this.n.add(on)).mod(this.m)\n    return new FQ(n, this.m)\n  }\n\n  mul(other: BigNumber) {\n    const on = other\n    const n = this.n.mul(on).mod(this.m)\n    return new FQ(n, this.m)\n  }\n\n  sub(other: BigNumber) {\n    const on = other\n    let new_n: BigNumber;\n    if (this.n.gte(on)) {\n      new_n = (this.n.sub(on)).mod(this.m)\n    } else {\n      new_n = (this.n.sub(on).add(this.m)).mod(this.m)\n    }\n    return new FQ(new_n, this.m)\n  }\n\n  div(other: BigNumber) {\n    const on_c = other\n    const m_c = this.m\n    const two_c = BigNumber.from(\"2\")\n    const on_power_c = modulo(on_c, m_c.sub(two_c), m_c)\n    const n_on_power_remainder = this.n.mul(on_power_c).mod(this.m)\n\n    return new FQ(n_on_power_remainder, this.m)\n  }\n\n  static one(modulus: BigNumber = field.SNARK_SCALAR_FIELD) {\n    return new FQ(BigNumber.from(\"1\"), modulus)\n  }\n\n  static zero(modulus: BigNumber = field.SNARK_SCALAR_FIELD) {\n    return new FQ(BigNumber.from(\"0\"), modulus)\n  }\n\n}\n\nexport function modulo(n: BigNumber, p: BigNumber, m: BigNumber) {\n  const n_ = new BigInteger(n.toString())\n  const p_ = new BigInteger(p.toString())\n  const m_ = new BigInteger(m.toString())\n\n  // console.log(\"modulo\", n_.toString(), p_.toString(), m_.toString());\n  const result = n_.modPow(p_, m_)\n  // console.log(n_.toString(), p_.toString(), m_.toString(), result.toString())\n  return BigNumber.from(result.toString())\n}"
  },
  {
    "path": "src/api/sign/poseidon/field_test.ts",
    "content": "import { assert } from \"console\";\nimport { BigNumber } from \"ethers\";\n\nimport { field, FQ, modulo } from \"./field\";\n\nfunction test_constants() {\n  // console.log(\"test_constants\")\n  assert(field.SNARK_SCALAR_FIELD.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  assert(field.FR_ORDER.eq(BigNumber.from(\"21888242871839275222246405745257275088614511777268538073601725287587578984328\")))\n  // console.log(\"test_constants passed\")\n}\n\nfunction test_half() {\n  // console.log(\"test_half\")\n  const half = BigNumber.from(\"10944121435919637611123202872628637544274182200208017171849102093287904247808\")\n  assert(field.SNARK_SCALAR_FIELD.div(2).eq(half))\n  // console.log(\"test_half passed\")\n}\n\nfunction test_p() {\n  // console.log(\"test_p\")\n  const p = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n  assert(field.SNARK_SCALAR_FIELD.eq(p))\n  // console.log(\"test_p passed\")\n}\n\nfunction test_FQ_1() {\n  // console.log(\"test_FQ_1\")\n  const n = BigNumber.from(\"1\")\n  const privateKey = new FQ(n)\n  assert(privateKey.n.eq(BigNumber.from(\"1\")))\n  assert(privateKey.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  // console.log(\"test_FQ_1 passed\")\n}\n\nfunction test_FQ_add_1() {\n  // console.log(\"test_FQ_add_1\")\n  const field1 = new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const field2 = new FQ(BigNumber.from(\"64019726205844806607227168444173457603185468776494125031546307012808629654\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const result1 = field1.add(field2.n)\n  const result2 = field2.add(field1.n)\n\n  assert(result1.n.eq(result2.n))\n  assert(result1.m.eq(result2.m))\n  // console.log(\"test_FQ_add_1 passed\")\n}\n\nfunction test_FQ_mul_1() {\n  // console.log(\"test_FQ_mul_1\")\n  const other = BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\")\n  const field = new FQ(BigNumber.from(\"8023312754331632317345164874475855606161388395970421403351236980717209379200\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const result = field.mul(other)\n\n  assert(result.n.eq(\"7078307911818432186422689430568175567157289995259698798344014234848622444761\"))\n  assert(result.m.eq(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  // console.log(\"test_FQ_mul_1 passed\")\n}\n\nfunction test_FQ_mul_2() {\n  // console.log(\"test_FQ_mul_2\")\n  const other = BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\")\n  const field = new FQ(BigNumber.from(\"64019726205844806607227168444173457603185468776494125031546307012808629654\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const result = field.mul(other)\n\n  assert(result.n.eq(\"8023312754331632317345164874475855606161388395970421403351236980717209379200\"))\n  assert(result.m.eq(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  // console.log(\"test_FQ_mul_2 passed\")\n}\n\nfunction test_FQ_mul_3() {\n  // console.log(\"test_FQ_mul_3\")\n  const field1 = new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const field2 = new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const result1 = field1.add(field2.n)\n  const result2 = field2.add(field1.n)\n\n  assert(result1.n.eq(result2.n))\n  assert(result1.m.eq(result2.m))\n  // console.log(\"test_FQ_mul_3 passed\")\n}\n\nfunction test_FQ_mul_4() {\n  // console.log(\"test_FQ_mul_4\")\n  const field1 = new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const field2 = new FQ(BigNumber.from(\"64019726205844806607227168444173457603185468776494125031546307012808629654\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const field3 = new FQ(BigNumber.from(\"8023312754331632317345164874475855606161388395970421403351236980717209379200\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n\n  const result1 = field1.mul(field2.n).mul(field3.n)\n  const result2 = field2.mul(field1.n).mul(field3.n)\n  const result3 = field3.mul(field1.n).mul(field2.n)\n  const result4 = field3.mul(field2.n).mul(field1.n)\n\n  assert(result1.n.eq(result2.n))\n  assert(result1.m.eq(result2.m))\n  assert(result1.n.eq(result3.n))\n  assert(result1.m.eq(result3.m))\n  assert(result1.n.eq(result4.n))\n  assert(result1.m.eq(result4.m))\n\n  // console.log(\"test_FQ_mul_4 passed\")\n}\n\nfunction test_FQ_module() {\n  // console.log(\"test_FQ_module\")\n  const n = BigNumber.from(\"-14716512740585223458018047979811180521493135094147670344522878941283115968141\")\n  const m = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n  const n_m = n.add(m).mod(m)\n  assert(n_m.eq(BigNumber.from(\"7171730131254051764228357765446094567055229306268363999175325245292692527476\")))\n  // console.log(\"test_FQ_module passed\")\n}\n\nfunction test_FQ_sub() {\n  // console.log(\"test_FQ_sub\")\n  const field = new FQ(BigNumber.from(\"397593468802287547516812218524989251246873285051017590397180750166966730405\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const other = BigNumber.from(\"15114106209387511005534860198336169772740008379198687934920059691450082698546\")\n  // console.log(\"test_FQ_sub passed\")\n}\n\nfunction test_modulo() {\n  console.log(\"test_modulo\")\n  const n = BigNumber.from(\"15511699678189798553051672416861159023986881664249705525317240441617049428951\")\n  const p = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495615\")\n  const m = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n  const on_power_c = modulo(n, p, m)\n  console.log(\"on_power_c\", on_power_c.toString())\n  assert(on_power_c.toString() === \"5307867014497036273760343161114758635681413365004069877684017182635568142756\")\n}\n\nfunction main() {\n  // console.log(\"\\n\\nfield_test\\n\")\n  // test_constants()\n  // test_half()\n  // test_p()\n  // test_FQ_1()\n  // test_FQ_add_1()\n  // test_FQ_mul_1()\n  // test_FQ_mul_2()\n  // test_FQ_mul_3()\n  // test_FQ_mul_4()\n  // test_FQ_module()\n  // test_FQ_sub()\n  test_modulo()\n}\n\nmain();"
  },
  {
    "path": "src/api/sign/poseidon/jubjub.ts",
    "content": "/*\nThis module implements the extended twisted edwards and extended affine coordinates\ndescribed in the paper \"Twisted Edwards Curves Revisited\":\n\n - https://iacr.org/archive/asiacrypt2008/53500329/53500329.pdf\n   Huseyin Hisil, Kenneth Koon-Ho Wong, Gary Carter, and Ed Dawson\n\n        Information Security Institute,\n        Queensland University of Technology, QLD, 4000, Australia\n        {h.hisil, kk.wong, g.carter, e.dawson}@qut.edu.au\n\nBy using the extended coordinate system we can avoid expensive modular exponentiation\ncalls, for example - a scalar multiplication call (or multiple...) may perform only\none 3d->2d projection at the point where affine coordinates are necessary, and every\nintermediate uses a much faster form.\n\n# XXX: none of these functions are constant time, they should not be used interactively!\n*/\nimport { BigNumber } from \"ethers\";\nimport { field, FQ } from \"./field\";\n\nexport class jubjub {\n  static JUBJUB_Q = field.SNARK_SCALAR_FIELD\n  static JUBJUB_E = BigNumber.from(\"21888242871839275222246405745257275088614511777268538073601725287587578984328\")\n  static JUBJUB_C = BigNumber.from(\"8\")  // Cofactor\n\n  static JUBJUB_L = jubjub.JUBJUB_E.div(jubjub.JUBJUB_C)  // L*B = 0, and (2^C)*L == #E\n  static JUBJUB_A = BigNumber.from(\"168700\") // Coefficient A\n  static JUBJUB_D = BigNumber.from(\"168696\") // Coefficient D\n}\n\nexport class Point {\n  public x: FQ\n  public y: FQ\n\n  constructor(x: FQ, y: FQ) {\n    this.x = x\n    this.y = y\n  }\n\n  static generate() {\n    const xBigInt = BigNumber.from(\"16540640123574156134436876038791482806971768689494387082833631921987005038935\")\n    const yBigInt = BigNumber.from(\"20819045374670962167435360035096875258406992893633759881276124905556507972311\")\n    const point = new Point(new FQ(xBigInt), new FQ(yBigInt))\n    return point\n  }\n\n  mul(scaler: BigNumber) {\n    let p = new Point(this.x, this.y)\n    let a = Point.infinity()\n    let i = 0\n\n    while (!scaler.eq(BigNumber.from(\"0\"))) {\n      const bitwiseAnd = scaler.and(BigNumber.from(\"1\"))\n      if (!bitwiseAnd.eq(BigNumber.from(\"0\"))) {\n        a = a.add(p)\n      }\n      let copyP1 = new Point(p.x, p.y)\n      let copyP2 = new Point(p.x, p.y)\n      p = copyP1.add(copyP2)\n      scaler = scaler.div(BigNumber.from(\"2\"))\n      // console.log(i + \" scaler\", scaler.toString())\n      i = i + 1\n    }\n    return a\n  }\n\n  add(other: Point) {\n    if (this.x.n.eq(BigNumber.from(\"0\")) && this.y.n.eq(BigNumber.from(\"0\"))) {\n      return other\n    }\n    const u1 = this.x\n    const v1 = this.y\n    const u2 = other.x\n    const v2 = other.y\n\n    const u3_tmp0 = (u1.mul(v2.n)).add(v1.mul(u2.n).n)\n    const u3_tmp1 = u1.mul(u2.n).mul(v1.n).mul(v2.n).mul(jubjub.JUBJUB_D)\n    const u3_tmp2 = FQ.one().add(u3_tmp1.n)\n\n    const u3 = u3_tmp0.div(u3_tmp2.n)\n\n    const v3_tmp0 = v1.mul(v2.n)\n    const v3_tmp1 = u1.mul(u2.n).mul(jubjub.JUBJUB_A)\n    const v3_tmp3 = v3_tmp0.sub(v3_tmp1.n)  \n    const v3_tmp5 = FQ.one().sub(u3_tmp1.n)\n\n    const v3 = v3_tmp3.div(v3_tmp5.n)\n\n    return new Point(u3, v3)\n  }\n\n  static infinity() {\n    return new Point(new FQ(BigNumber.from(\"0\")), new FQ(BigNumber.from(\"1\")))\n  }\n}\n"
  },
  {
    "path": "src/api/sign/poseidon/jubjub_test.ts",
    "content": "import { assert } from \"console\";\nimport { BigNumber } from \"ethers\";\nimport { FQ } from \"./field\";\n\nimport { jubjub, Point } from \"./jubjub\";\n\nfunction test_constants() {\n  // console.log(\"test_constants\")\n  assert(jubjub.JUBJUB_Q.eq(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  assert(jubjub.JUBJUB_E.eq(\"21888242871839275222246405745257275088614511777268538073601725287587578984328\"))\n  assert(jubjub.JUBJUB_C.eq(\"8\"))\n  assert(jubjub.JUBJUB_L.eq(\"2736030358979909402780800718157159386076813972158567259200215660948447373041\"))\n  assert(jubjub.JUBJUB_A.eq(\"168700\"))\n  assert(jubjub.JUBJUB_D.eq(\"168696\"))\n  // console.log(\"test_constants passed\")\n}\n\nfunction test_add_1() {\n  // console.log(\"test_add_1\")\n  const point = new Point(new FQ(BigNumber.from(\"5925710879559963920674585068280151559572021649049974518737186312396312983287\")), new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\")))\n  const other = new Point(new FQ(BigNumber.from(\"5925710879559963920674585068280151559572021649049974518737186312396312983287\")), new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\")))\n  const sum = point.add(other)\n  assert(sum.x.n.eq(BigNumber.from(\"3921821752680400551661691533275335336907961697969280331905459386565873550491\")))\n  assert(sum.x.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  assert(sum.y.n.eq(BigNumber.from(\"8522068897570808837785568881356377871354274006792075192589502922612862896342\")))\n  assert(sum.y.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  // console.log(\"test_add_1 passed\")\n}\n\nfunction test_add_2() {\n  // console.log(\"test_add_2\")\n  const point = new Point(new FQ(BigNumber.from(\"10975113445185536695224737904225227344281568447400334915125839333792816477396\")), new FQ(BigNumber.from(\"18445435810976842694581549336952093637971779711294581156054437925992025486446\")))\n  const other = new Point(new FQ(BigNumber.from(\"5925710879559963920674585068280151559572021649049974518737186312396312983287\")), new FQ(BigNumber.from(\"16975020951829843291561856284829257584634286376639034318405002894754175986822\")))\n  const sum = point.add(other)\n  assert(sum.x.n.eq(BigNumber.from(\"4991609103248925747358645194965349262579784734809679007552644294476920671344\")))\n  assert(sum.x.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  assert(sum.y.n.eq(BigNumber.from(\"423391641476660815714427268720766993055332927752794962916609674122318189741\")))\n  assert(sum.y.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  // console.log(\"test_add_2 passed\")\n}\n\nfunction test_divide_1() {\n  // console.log(\"test_divide_1\")\n  const scaler = BigNumber.from(\"1\")\n  const result = scaler.div(2)\n  assert(result.eq(BigNumber.from(\"0\")))\n  // console.log(\"test_divide_1 passed\")\n}\n\nfunction test_divide_2() {\n  // console.log(\"test_divide_2\")\n  const scaler = BigNumber.from(\"2\")\n  const result = scaler.div(2)\n  assert(result.eq(BigNumber.from(\"1\")))\n  // console.log(\"test_divide_2 passed\")\n}\n\nfunction test_bitwiseand_1() {\n  // console.log(\"test_bitwiseand_1\")\n  const scaler_c = BigNumber.from(\"1\")\n  const result_c = scaler_c.and(BigNumber.from(1))\n  assert(result_c.eq(BigNumber.from(\"1\")))\n  // console.log(\"test_bitwiseand_1 passed\")\n}\n\nfunction test_bitwiseand_2() {\n  // console.log(\"test_bitwiseand_2\")\n  const scaler_c = BigNumber.from(\"2\")\n  const result_c = scaler_c.and(BigNumber.from(1))\n  assert(result_c.eq(BigNumber.from(\"0\")))\n  // console.log(\"test_bitwiseand_2 passed\")\n}\n\nfunction test_mul_1() {\n  // console.log(\"test_mul_1\")\n  const B = new Point(new FQ(BigNumber.from(\"16540640123574156134436876038791482806971768689494387082833631921987005038935\")), new FQ(BigNumber.from(\"20819045374670962167435360035096875258406992893633759881276124905556507972311\")))\n  const k = BigNumber.from(\"1\")\n  const A = B.mul(k)\n  assert(A.x.n.eq(BigNumber.from(\"16540640123574156134436876038791482806971768689494387082833631921987005038935\")))\n  assert(A.x.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  assert(A.y.n.eq(BigNumber.from(\"20819045374670962167435360035096875258406992893633759881276124905556507972311\")))\n  assert(A.y.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  // console.log(\"test_mul_1 passed\")\n}\n\nfunction test_mul_2() {\n  // console.log(\"test_mul_2\")\n  const B = new Point(new FQ(BigNumber.from(\"16540640123574156134436876038791482806971768689494387082833631921987005038935\")), new FQ(BigNumber.from(\"20819045374670962167435360035096875258406992893633759881276124905556507972311\")))\n  const k = BigNumber.from(\"2\")\n  const A = B.mul(k)\n  assert(A.x.n.eq(BigNumber.from(\"17324563846726889236817837922625232543153115346355010501047597319863650987830\")))\n  assert(A.x.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  assert(A.y.n.eq(BigNumber.from(\"20022170825455209233733649024450576091402881793145646502279487074566492066831\")))\n  assert(A.y.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")))\n  // console.log(\"test_mul_2 passed\")\n}\n\nfunction test_mul_3() {\n  // console.log(\"test_mul_3\")\n  const x = new FQ(BigNumber.from(\"16540640123574156134436876038791482806971768689494387082833631921987005038935\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const y = new FQ(BigNumber.from(\"20819045374670962167435360035096875258406992893633759881276124905556507972311\"), BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\"))\n  const B = new Point(x, y)\n  const k = BigNumber.from(\"456425617452149303537516185998917840598824274191970480768523181450944242406\")\n  const A = B.mul(k)\n  assert(A.x.n.eq(BigNumber.from(\"4991609103248925747358645194965349262579784734809679007552644294476920671344\")), \"A.x.n\" + A.x.n.toString())\n  assert(A.x.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")), \"A.x.m\" + A.x.m.toString())\n  assert(A.y.n.eq(BigNumber.from(\"423391641476660815714427268720766993055332927752794962916609674122318189741\")), \"A.y.n\" + A.y.n.toString())\n  assert(A.y.m.eq(BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")), \"A.y.m\" + A.y.m.toString())\n  // console.log(\"test_mul_3 passed\")\n}\n\nfunction main() {\n  // console.log(\"hello\")\n  test_constants()\n  test_add_1()\n  test_add_2()\n  test_divide_1()\n  test_divide_2()\n  test_bitwiseand_1()\n  test_bitwiseand_2()\n  test_mul_1()\n  test_mul_2()\n  test_mul_3()\n}\n\nmain();"
  },
  {
    "path": "src/api/sign/poseidon/permutation.ts",
    "content": "/*\n Implements the Poseidon permutation:\n\n Starkad and Poseidon: New Hash Functions for Zero Knowledge Proof Systems\n  - Lorenzo Grassi, Daniel Kales, Dmitry Khovratovich, Arnab Roy, Christian Rechberger, and Markus Schofnegger\n  - https://eprint.iacr.org/2019/458.pdf\n\n Other implementations:\n\n  - https://github.com/shamatar/PoseidonTree/\n  - https://github.com/iden3/circomlib/blob/master/src/poseidon.js\n  - https://github.com/dusk-network/poseidon252\n */\n\nimport { BigNumber } from 'ethers'\nimport { SignatureScheme } from './eddsa'\nimport { modulo } from './field'\n\nimport { TextEncoder } from 'web-encoding'\n\nimport blake2b from 'blake2b'\n\nexport class PoseidonParams {\n  public p: BigNumber\n  public t: number\n  public nRoundsF: number\n  public nRoundsP: number\n  public seed: string\n  public e: BigNumber\n  public constants_C: [BigNumber]\n  public constants_M: [[BigNumber]]\n  public security_target: number\n\n  constructor(\n    p: BigNumber,\n    t: number,\n    nRoundsF: number,\n    nRoundsP: number,\n    seed: string,\n    e: BigNumber,\n    constants_C: [BigNumber] | null,\n    constants_M: [[BigNumber]] | null,\n    security_target: number,\n  ) {\n    this.p = p\n    this.t = t\n    this.nRoundsF = nRoundsF\n    this.nRoundsP = nRoundsP\n    this.seed = seed\n    this.e = e\n\n    if (constants_C == null) {\n      this.constants_C = permunation.poseidon_constants(p, `${seed}_constants`, nRoundsF + nRoundsP)\n    } else {\n      this.constants_C = constants_C\n    }\n\n    if (constants_M == null) {\n      this.constants_M = permunation.poseidon_matrix(p, `${seed}_matrix_0000`, t)\n    } else {\n      this.constants_M = constants_M\n    }\n\n    this.security_target = security_target\n  }\n}\n\nexport class permunation {\n  static H(arg: string) {\n    const outputLength = 32\n\n    const enc = new TextEncoder()\n    const message = enc.encode(arg)\n    // console.log(`message ${message}`)\n\n    const buf = Buffer.alloc(outputLength)\n    // console.log(`hashOfSize32Bytes ${buf.toString()}`)\n    // console.log(`message ${message}`)\n    // @ts-ignore\n    blake2b(buf.length, undefined).update(message).final(buf)\n    const items = buf.toJSON().data\n    // console.log(`H items ${items}`)\n\n    let sum = BigNumber.from('0')\n    var i = 0\n    for (var i = 0; i < items.length; i++) {\n      const itemBigInt = BigNumber.from(items[i])\n      const tmp = itemBigInt.mul(BigNumber.from('256').pow(BigNumber.from(i)))\n      sum = sum.add(tmp)\n    }\n    // console.log(`sum ${sum}`)\n    return sum\n  }\n\n  static H_Bigint(arg: BigNumber) {\n    const outputLength = 32\n\n    const message = new Uint8Array(SignatureScheme.to_bytes(arg))\n    // console.log(`message ${message}`)\n\n    const buf = Buffer.alloc(outputLength)\n    // console.log(`hashOfSize32Bytes ${buf.toString()}`)\n    // @ts-ignore\n    blake2b(buf.length, undefined).update(message).final(buf)\n    const items = buf.toJSON().data\n    // console.log(`H_Bigint items ${items}`)\n\n    let sum = BigNumber.from('0')\n    var i = 0\n    for (var i = 0; i < items.length; i++) {\n      const itemBigInt = BigNumber.from(items[i])\n      const tmp = itemBigInt.mul(BigNumber.from('256').pow(BigNumber.from(i)))\n      sum = sum.add(tmp)\n    }\n    // console.log(`sum ${sum}`)\n    return sum\n  }\n\n  static poseidon_constants(p: BigNumber, seed: string, n: number) {\n    let c: any\n    c = []\n    let seedBigInt = this.H(seed)\n    const result = seedBigInt.mod(p)\n    c.push(result)\n    for (let i = 0; i < n - 1; i++) {\n      seedBigInt = this.H_Bigint(seedBigInt)\n      const result = seedBigInt.mod(p)\n      c.push(result)\n    }\n    return c\n  }\n\n  static poseidon_matrix(p: BigNumber, seed: string, t: number) {\n    const c = this.poseidon_constants(p, seed, t * 2)\n    let matrix: any\n    matrix = []\n    for (let i = 0; i < t; i++) {\n      let row: any\n      row = []\n      for (let j = 0; j < t; j++) {\n        const c_i = c[i]\n        const c_t_j = c[t + j]\n        const p_c = p\n        const c_t_j_p = c_t_j.mod(p_c)\n        const left = c_i.sub(c_t_j_p)\n        const p_2 = p_c.sub(2)\n        const item_c = modulo(left, p_2, p_c)\n        row.push(item_c)\n      }\n      matrix.push(row)\n    }\n    return matrix\n  }\n\n  static poseidon_sbox(state: [BigNumber], i: number, params: PoseidonParams) {\n    /*\n    iacr.org/2019/458 § 2.2 The Hades Strategy (pg 6)\n\n    In more details, assume R_F = 2 · R_f is an even number. Then\n    - the first R_f rounds have a full S-Box layer,\n    - the middle R_P rounds have a partial S-Box layer (i.e., 1 S-Box layer),\n    - the last R_f rounds have a full S-Box layer\n    */\n    const half_F = params.nRoundsF / 2\n\n    if (i < half_F || i >= half_F + params.nRoundsP) {\n      for (let j = 0; j < state.length; j++) {\n        const element_c = state[j]\n        const e_c = params.e\n        const p_c = params.p\n        const item = modulo(element_c, e_c, p_c)\n        state[j] = item\n      }\n    } else {\n      const element_c = state[0]\n      const e_c = params.e\n      const p_c = params.p\n      const item = modulo(element_c, e_c, p_c)\n      state[0] = item\n    }\n    return state\n  }\n\n  static poseidon_mix(state: [BigNumber], M: [[BigNumber]], p: BigNumber) {\n    /*\n    The mixing layer is a matrix vector product of the state with the mixing matrix\n      - https://mathinsight.org/matrix_vector_multiplication\n    */\n    let newState: any\n    newState = []\n    for (let i = 0; i < M.length; i++) {\n      let sum = BigNumber.from(0)\n      for (let j = 0; j < state.length; j++) {\n        const element = state[j]\n        sum = sum.add(M[i][j].mul(element))\n      }\n      newState.push(sum.mod(p))\n    }\n    return newState\n  }\n\n  // poseidon\n  /*\n    Main instansiation of the Poseidon permutation\n\n    The state is `t` elements wide, there are `F` full-rounds\n    followed by `P` partial rounds, then `F` full rounds again.\n\n        [    ARK    ]    --,\n          | | | | | |       |\n        [    SBOX   ]       -  Full Round\n          | | | | | |       |\n        [    MIX    ]    --`\n\n\n        [    ARK    ]    --,\n          | | | | | |       |\n        [    SBOX   ]       -  Partial Round\n                    |       |   Only 1 element is substituted in partial round\n        [    MIX    ]    --`\n\n    There are F+P rounds for the full permutation.\n\n    You can provide `r = N - 2s` bits of input per round, where `s` is the desired\n    security level, in most cases this means you can provide `t-1` inputs with\n    appropriately chosen parameters. The permutation can be 'chained' together\n    to form a sponge construct.\n  */\n  static poseidon(inputs: [BigNumber], params: PoseidonParams) {\n    let state: any\n    state = []\n    state = state.concat(inputs)\n    // console.log(`state ${state}`)\n    for (var i = 0; i < params.t - inputs.length; i++) {\n      state.push(BigNumber.from(0))\n    }\n\n    // console.log(`state ${state}`)\n    // console.log(`params.constants_C.length ${params.constants_C.length}`)\n\n    for (var i = 0; i < params.constants_C.length; i++) {\n      const C_i = params.constants_C[i]\n\n      for (let index = 0; index < state.length; index++) {\n        const element = state[index]\n        state[index] = element.add(C_i)\n      }\n\n      state = this.poseidon_sbox(state, i, params)\n      // console.log(`after poseidon_sbox ${state}`)\n\n      state = this.poseidon_mix(state, params.constants_M, params.p)\n      // console.log(`after poseidon_mix ${state}`)\n    }\n    // console.log(`hash is ${state[0]}`)\n    return state[0]\n  }\n}\n"
  },
  {
    "path": "src/api/sign/poseidon/permutation_test.ts",
    "content": "import { assert } from \"console\";\nimport { BigNumber } from \"ethers\";\nimport { field } from \"./field\";\nimport { permunation, PoseidonParams } from \"./permutation\";\n\nfunction test_PoseidonParams() {\n  // console.log(\"test_PoseidonParams\")\n  const p = field.SNARK_SCALAR_FIELD\n  const t = 6\n  const nRoundsF = 8\n  const nRoundsP = 57\n  const seed = \"poseidon\"\n  const e = BigNumber.from(5)\n  const security_target = 126\n\n  const poseidonParams = new PoseidonParams(p, t, nRoundsF, nRoundsP, seed, e, null, null, security_target)\n  // console.log(`poseidonParams ${poseidonParams.constants_C}`)\n  // @ts-ignore\n  assert(poseidonParams.constants_C[0].eq(BigNumber.from(\"14397397413755236225575615486459253198602422701513067526754101844196324375522\")), \"poseidonParams.constants_C[0]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_C[1].eq(BigNumber.from(\"10405129301473404666785234951972711717481302463898292859783056520670200613128\")), \"poseidonParams.constants_C[2]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_C[63].eq(BigNumber.from(\"14423660424692802524250720264041003098290275890428483723270346403986712981505\")), \"poseidonParams.constants_C[3]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_C[64].eq(BigNumber.from(\"10635360132728137321700090133109897687122647659471659996419791842933639708516\")), \"poseidonParams.constants_C[64]\")\n  \n  // @ts-ignore\n  assert(poseidonParams.constants_M[0][0].eq(BigNumber.from(\"19167410339349846567561662441069598364702008768579734801591448511131028229281\")), \"poseidonParams.constants_M[0][0]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_M[0][1].eq(BigNumber.from(\"14183033936038168803360723133013092560869148726790180682363054735190196956789\")), \"poseidonParams.constants_M[0][1]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_M[0][2].eq(BigNumber.from(\"9067734253445064890734144122526450279189023719890032859456830213166173619761\")), \"poseidonParams.constants_M[0][2]\")\n\n  // @ts-ignore\n  assert(poseidonParams.constants_M[5][3].eq(BigNumber.from(\"8035240799672199706102747147502951589635001418759394863664434079699838251138\")), \"poseidonParams.constants_M[0][0]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_M[5][4].eq(BigNumber.from(\"21642389080762222565487157652540372010968704000567605990102641816691459811717\")), \"poseidonParams.constants_M[0][1]\")\n  // @ts-ignore\n  assert(poseidonParams.constants_M[5][5].eq(BigNumber.from(\"20261355950827657195644012399234591122288573679402601053407151083849785332516\")), \"poseidonParams.constants_M[0][2]\")\n\n  // console.log(\"test_PoseidonParams passed\")\n}\n\nfunction test_H_1() {\n  console.log(\"test_H_1\")\n  const arg = \"poseidon_constants\"\n  const hash = permunation.H(arg)\n  assert(hash.eq(BigNumber.from(\"80062126029273061892314832722231078464247515902761170557848714403923749862373\")))\n  console.log(\"test_H_1 passed\")\n}\n\nfunction test_H_2() {\n  console.log(\"test_H_2\")\n  const arg = \"poseidon_matrix_0000\"\n  const hash = permunation.H(arg)\n  assert(hash.eq(BigNumber.from(\"14132513739920849383792069751007754351800355055139761101807090020635929082500\")))\n  console.log(\"test_H_2 passed\")\n}\n\nfunction test_H_3() {\n  console.log(\"test_H_3\")\n  const arg = BigNumber.from(\"14132513739920849383792069751007754351800355055139761101807090020635929082500\")\n  const hash = permunation.H_Bigint(arg)\n  assert(hash.eq(BigNumber.from(\"2944673226682481007627110343206629017840128596422012786319796010373889882365\")))\n  console.log(\"test_H_3 passed\")\n}\n\nfunction test_poseidon_constants() {\n  // console.log(\"test_poseidon_constants\")\n  const p = field.SNARK_SCALAR_FIELD\n  const seed = \"poseidon_constants\"\n  const n = 65\n  const constants_C = permunation.poseidon_constants(p, seed, n)\n  assert(constants_C[0].eq(BigNumber.from(\"14397397413755236225575615486459253198602422701513067526754101844196324375522\")))\n  assert(constants_C[1].eq(BigNumber.from(\"10405129301473404666785234951972711717481302463898292859783056520670200613128\")))\n  assert(constants_C[2].eq(BigNumber.from(\"5179144822360023508491245509308555580251733042407187134628755730783052214509\")))\n  assert(constants_C[63].eq(BigNumber.from(\"14423660424692802524250720264041003098290275890428483723270346403986712981505\")))\n  assert(constants_C[64].eq(BigNumber.from(\"10635360132728137321700090133109897687122647659471659996419791842933639708516\")))\n  // console.log(\"test_poseidon_constants passed\")\n}\n\nfunction test_poseidon_matrix() {\n  console.log(\"test_poseidon_matrix\")\n  const p = field.SNARK_SCALAR_FIELD\n  const seed = \"poseidon_matrix_0000\"\n  const t = 9\n  const constants_M = permunation.poseidon_matrix(p, seed, t)\n  assert(constants_M[0][0].eq(BigNumber.from(\"16378664841697311562845443097199265623838619398287411428110917414833007677155\")))\n  assert(constants_M[0][1].eq(BigNumber.from(\"12968540216479938138647596899147650021419273189336843725176422194136033835172\")))\n  assert(constants_M[0][2].eq(BigNumber.from(\"3636162562566338420490575570584278737093584021456168183289112789616069756675\")))\n  assert(constants_M[1][3].eq(BigNumber.from(\"8642889650254799419576843603477253661899356105675006557919250564400804756641\")))\n  assert(constants_M[8][8].eq(BigNumber.from(\"11398590172899810645820530606484864595574598270604175688862890426075002823331\")))\n  console.log(\"test_poseidon_matrix passed\")\n}\n\nfunction test_poseidon_1() {\n  console.log(\"test_poseidon_1\")\n  const p = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n  const MAX_INPUT = 8\n  const poseidonParams = new PoseidonParams(p, MAX_INPUT+1, 6, 53, \"poseidon\", BigNumber.from(5), null, null, 128)\n  let intputs: any\n  intputs = []\n  intputs.push(BigNumber.from(1))\n  const state0 = permunation.poseidon(intputs, poseidonParams)\n  assert(state0.eq(BigNumber.from(\"20640057815290657586474256351705900781103272844170318852926520138679251832017\")))\n  console.log(\"test_poseidon_1 passed\")\n}\n\nfunction test_poseidon_2() {\n  console.log(\"test_poseidon_2\")\n  const p = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n  const MAX_INPUT = 8\n  const poseidonParams = new PoseidonParams(p, MAX_INPUT+1, 6, 53, \"poseidon\", BigNumber.from(5), null, null, 128)\n  let intputs: any\n  intputs = []\n  intputs.push(BigNumber.from(1))\n  intputs.push(BigNumber.from(2))\n  const state0 = permunation.poseidon(intputs, poseidonParams)\n  assert(state0.eq(BigNumber.from(\"9251914430137119038619835991672259215400712688203929648293348181354900386736\")))\n  console.log(\"test_poseidon_2 passed\")\n}\n\nfunction test_poseidon_3() {\n  console.log(\"test_poseidon_3\")\n  const p = BigNumber.from(\"21888242871839275222246405745257275088548364400416034343698204186575808495617\")\n  const MAX_INPUT = 8\n  const poseidonParams = new PoseidonParams(p, MAX_INPUT+1, 6, 53, \"poseidon\", BigNumber.from(5), null, null, 128)\n  let intputs: any\n  intputs = []\n  intputs.push(BigNumber.from(1))\n  intputs.push(BigNumber.from(2))\n  intputs.push(BigNumber.from(3))\n  intputs.push(BigNumber.from(4))\n  intputs.push(BigNumber.from(5))\n  intputs.push(BigNumber.from(6))\n  intputs.push(BigNumber.from(7))\n  intputs.push(BigNumber.from(8))\n  const state0 = permunation.poseidon(intputs, poseidonParams)\n  assert(state0.eq(BigNumber.from(\"1792233229836714442925799757877868602259716425270865187624398529027734741166\")))\n  console.log(\"test_poseidon_3 passed\")\n}\n\nfunction main() {\n  // console.log(\"\\n\\npermutation_test\\n\")\n  // test_PoseidonParams()\n  test_H_1()\n  test_H_2()\n  test_H_3()\n  // test_poseidon_constants()\n  test_poseidon_matrix()\n  test_poseidon_1()\n  test_poseidon_2()\n  test_poseidon_3()\n}\n\nmain();"
  },
  {
    "path": "src/api/sign/sign_tools.ts",
    "content": "// import sha256 from 'crypto-js/sha256'\nimport * as crypto from 'crypto-js'\n\nimport * as abi from 'ethereumjs-abi'\nimport * as sigUtil from 'eth-sig-util'\n\nimport * as ethUtil from 'ethereumjs-util'\n\nimport BN from 'bn.js'\n\nimport BigInteger from 'bignumber.js'\nimport { bnToBufWithFixedLength } from './poseidon/eddsa'\nimport { EDDSAUtil } from './poseidon/EDDSAUtil'\nimport { field } from './poseidon/field'\nimport { permunation, PoseidonParams } from './poseidon/permutation'\n\nimport * as fm from '../../utils/formatter'\nimport { toBig, toHex } from '../../utils'\n\nimport {\n  AmmPoolRequestPatch,\n  ChainId,\n  ConnectorNames,\n  CounterFactualInfo,\n  DualOrderRequest,\n  ExitAmmPoolRequest,\n  IsMobile,\n  JoinAmmPoolRequest,\n  NFTMintRequestV3,\n  NFTOrderRequestV3,\n  NFTTokenAmountInfo,\n  NFTTradeRequestV3,\n  NFTWithdrawRequestV3,\n  OffChainWithdrawalRequestV3,\n  OriginNFTTransferRequestV3,\n  OriginTransferRequestV3,\n  PublicKey,\n  SubmitOrderRequestV3,\n  UpdateAccountRequestV3,\n} from '../../defs'\nimport { Buffer } from 'buffer'\n\n/**\n * BigNumber -> BigInt\n * BigNumber.from() -> BigInt() or \\dn\n * div -> /\n * sub -> -\n * gt -> >\n * lt -> <\n * gte -> >=\n * eq -> ==\n * and -> &&=\n */\nimport * as loopring_defs from '../../defs/loopring_defs'\n\nimport Web3 from 'web3'\nimport { myLog } from '../../utils/log_tools'\nimport { personalSign } from '../base_api'\n\nimport { BigNumber } from '@ethersproject/bignumber'\nimport { getWindowSafely } from 'utils/window_utils'\nimport { ethers } from 'ethers'\n// import { hashMessage } from 'ethers/lib/utils'\n\nexport enum GetEcDSASigType {\n  HasDataStruct,\n  WithoutDataStruct,\n  Contract,\n}\n\nconst MIN_NFT_TOKENID = 32768\n\nconst SNARK_SCALAR_FIELD = new BigInteger(\n  '21888242871839275222246405745257275088548364400416034343698204186575808495617',\n  10,\n)\n\nexport interface KeyPairParams {\n  web3: any\n  address: string\n  walletType: ConnectorNames\n  keySeed: string\n  chainId: ChainId\n  accountId?: number\n  counterFactualInfo?: CounterFactualInfo\n  isMobile?: boolean\n}\n\nexport function generatePrivateKey(result: { sig: string; counterFactualInfo: any; error: any }) {\n  if (!result.error && result.sig) {\n    // myLog(\"sig:\", result.sig);\n    const seedBuff = ethUtil.sha256(fm.toBuffer(result.sig))\n    // myLog(`seedBuff.toString('hex') ${seedBuff.toString('hex')}`)\n    const seed = BigNumber.from('0x' + seedBuff.toString('hex'))\n    // myLog(`seed ${seed.toString()}`)\n    const bitIntDataItems = bnToBufWithFixedLength(seed.toString(), 32)\n    // myLog(`bigIntData ${bitIntDataItems}`)\n    const keyPair = EDDSAUtil.generateKeyPair(bitIntDataItems)\n    // myLog(\"keyPair\", keyPair)\n\n    const formatedPx = fm.formatEddsaKey(fm.toHex(fm.toBig(keyPair.publicKeyX)))\n    const formatedPy = fm.formatEddsaKey(fm.toHex(fm.toBig(keyPair.publicKeyY)))\n    const sk = toHex(toBig(keyPair.secretKey))\n\n    return {\n      keyPair,\n      formatedPx,\n      formatedPy,\n      sk,\n      counterFactualInfo: result.counterFactualInfo,\n    }\n  } else {\n    console.log('generateKeyPair personalSign error', result.error)\n    throw Error(result.error)\n  }\n}\n\nexport async function generateKeyPair(\n  {\n    web3,\n    address,\n    walletType,\n    keySeed,\n    chainId,\n    accountId,\n    counterFactualInfo,\n    isMobile,\n  }: KeyPairParams,\n  publicKey: { x: string; y: string } | undefined = undefined,\n) {\n  // LOG: for signature\n  myLog(\n    'personalSign ->',\n    'counterFactualInfo',\n    counterFactualInfo,\n    'keySeed',\n    keySeed,\n    'walletType',\n    walletType,\n    'publicKey from sever side ',\n    publicKey,\n  )\n  const result: any = await personalSign(\n    web3,\n    address,\n    '',\n    keySeed,\n    walletType,\n    chainId,\n    accountId,\n    counterFactualInfo,\n    isMobile === undefined ? IsMobile.any() : isMobile,\n  )\n  \n  if (process.env.REACT_APP_LOG_SIGNATURE === 'true') {\n    try {\n      const hash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(result.sig));\n      console.log('UnlockAccountEcdsaSigHashOutput', 'message hash', keySeed, ethers.utils.hashMessage(keySeed))\n      console.log('UnlockAccountEcdsaSigHashOutput', 'signature hash', hash)\n      console.log('UnlockAccountEcdsaSigHashOutput', 'isSigEmpty', result.sig === '')\n    } catch {}\n  }\n\n  if (!result.error && !result.sig) {\n    throw Error('sig is empty')\n  }\n  \n  try {\n    let { keyPair, formatedPx, formatedPy, sk, counterFactualInfo } = generatePrivateKey(result)\n\n    if (\n      publicKey &&\n      result.sig.length > 3 &&\n      publicKey.x &&\n      publicKey.y &&\n      (!fm.toBig(formatedPx).eq(fm.toBig(publicKey.x)) ||\n        !fm.toBig(formatedPy).eq(fm.toBig(publicKey.y)))\n    ) {\n      let value = result.sig.split('')\n      let end = value.splice(result.sig.length - 2, 2).join('')\n      end = end == '1c' ? '01' : '1c'\n      result.sig = value.concat(end.split('')).join('')\n      let newValue = generatePrivateKey(result)\n      // LOG: for signature\n      myLog(\n        'personalSign ->',\n        'publicKey calc by sign',\n        'x',\n        formatedPx,\n        'y',\n        formatedPy,\n        'publicKey from server',\n        publicKey,\n        'personalSign again->',\n        'publicKey calc by sign',\n        'x',\n        end,\n        newValue.formatedPx,\n        'y',\n        newValue.formatedPy,\n      )\n      return {\n        keyPair: newValue.keyPair,\n        formatedPx: newValue.formatedPx,\n        formatedPy: newValue.formatedPy,\n        sk: newValue.sk,\n        counterFactualInfo,\n      }\n    } else {\n      return { keyPair, formatedPx, formatedPy, sk, counterFactualInfo }\n    }\n  } catch (error) {\n    throw Error(error as any)\n  }\n}\n\nconst makeRequestParamStr = (request: Map<string, any>) => {\n  const arrObj = Array.from(request)\n  arrObj.sort(function (a, b) {\n    return a[0].localeCompare(b[0])\n  })\n  const orderedMap = new Map(arrObj.map((i) => [i[0], i[1]]))\n\n  const paramlist: Array<string> = []\n\n  const keys = Object.keys(Object.fromEntries(orderedMap))\n\n  if (keys) {\n    keys.forEach((key: string) => {\n      const value = request.get(key)\n      if (value !== undefined && value !== '') paramlist.push(`${key}=${value}`)\n    })\n  }\n\n  // force to change encode ',' due to different encode rules between server and client\n  return encodeURIComponent(paramlist.join('&')).replace(/%2C/g, '%252C')\n}\n\n//submitOrderV3\nconst genSigWithPadding = (PrivateKey: string | undefined, hash: any) => {\n  const signature = EDDSAUtil.sign(PrivateKey, hash)\n\n  let signatureRx_Hex = fm.clearHexPrefix(fm.toHex(fm.toBN(signature.Rx)))\n  if (signatureRx_Hex.length < 64) {\n    const padding = new Array(64 - signatureRx_Hex.length).fill(0)\n    signatureRx_Hex = padding.join('').toString() + signatureRx_Hex\n  }\n\n  let signatureRy_Hex = fm.clearHexPrefix(fm.toHex(fm.toBN(signature.Ry)))\n  if (signatureRy_Hex.length < 64) {\n    const padding = new Array(64 - signatureRy_Hex.length).fill(0)\n    signatureRy_Hex = padding.join('').toString() + signatureRy_Hex\n  }\n\n  let signatureS_Hex = fm.clearHexPrefix(fm.toHex(fm.toBN(signature.s)))\n  if (signatureS_Hex.length < 64) {\n    const padding = new Array(64 - signatureS_Hex.length).fill(0)\n    signatureS_Hex = padding.join('').toString() + signatureS_Hex\n  }\n  const result = '0x' + signatureRx_Hex + signatureRy_Hex + signatureS_Hex\n  return result\n}\n\nconst makeObjectStr = (request: Map<string, any>) => {\n  const jsonTxt = JSON.stringify(Object.fromEntries(request))\n  return encodeURIComponent(jsonTxt).replace(/[!'()]/g, escape) //replace(/'/ig, \"%27\")\n}\n\nexport function getEdDSASig(\n  method: string,\n  basePath: string,\n  api_url: string,\n  requestInfo: any,\n  PrivateKey: string | undefined,\n) {\n  let params = undefined\n\n  method = method.toUpperCase().trim()\n\n  if (method === 'GET' || method === 'DELETE') {\n    params = makeRequestParamStr(requestInfo)\n  } else if (method === 'POST' || method === 'PUT') {\n    params = makeObjectStr(requestInfo)\n  } else {\n    throw new Error(`${method} is not supported yet!`)\n  }\n\n  const uri = encodeURIComponent(`${basePath}${api_url}`)\n\n  const message = `${method}&${uri}&${params}`\n  // LOG: for signature\n  myLog('getEdDSASig', message)\n  let _hash: any = new BigInteger(crypto.SHA256(message).toString(), 16)\n\n  let hash = _hash.mod(SNARK_SCALAR_FIELD).toFormat(0, 0, {})\n  // LOG: for signature\n  myLog('getEdDSASig hash', message, '_hash', _hash.toString(), 'hash', hash)\n\n  const sig = genSigWithPadding(PrivateKey, hash)\n\n  return sig\n}\n\nexport function creatEdDSASigHasH({\n  method,\n  basePath,\n  api_url,\n  requestInfo,\n}: {\n  method: string\n  basePath: string\n  api_url: string\n  requestInfo: any\n}) {\n  let params = undefined\n\n  method = method.toUpperCase().trim()\n\n  if (method === 'GET' || method === 'DELETE') {\n    params = makeRequestParamStr(requestInfo)\n  } else if (method === 'POST' || method === 'PUT') {\n    params = makeObjectStr(requestInfo)\n  } else {\n    throw new Error(`${method} is not supported yet!`)\n  }\n\n  const uri = encodeURIComponent(`${basePath}${api_url}`)\n\n  const message = `${method}&${uri}&${params}`\n  // LOG: for signature\n  myLog('getEdDSASig', message)\n\n  let _hash: any = new BigInteger(crypto.SHA256(message).toString(), 16)\n\n  let hash = _hash.mod(SNARK_SCALAR_FIELD).toFormat(0, 0, {})\n  // LOG: for signature\n  myLog('getEdDSASig hash', message, '_hash', _hash.toString(), 'hash', hash)\n  return { hash, hashRaw: toHex(_hash) }\n}\n\nexport function verifyEdDSASig(\n  hash: string,\n  input: { Rx: string; Ry: string; s: string },\n): Boolean {\n  return true\n}\n\nexport const getEdDSASigWithPoseidon = (inputs: any, PrivateKey: string | undefined) => {\n  const p = field.SNARK_SCALAR_FIELD\n  const poseidonParams = new PoseidonParams(\n    p,\n    inputs.length + 1,\n    6,\n    53,\n    'poseidon',\n    BigNumber.from(5),\n    null,\n    null,\n    128,\n  )\n  let bigIntInputs: any\n  bigIntInputs = []\n  for (let i = 0; i < inputs.length; i++) {\n    const input = inputs[i]\n    bigIntInputs.push(BigNumber.from(input))\n  }\n  const hash = permunation.poseidon(bigIntInputs, poseidonParams)\n  return {\n    hash,\n    result: genSigWithPadding(PrivateKey, hash),\n  }\n}\n\n/**\n * @description sign EIP712\n * @param web3\n * @param account\n * @param method\n * @param params\n * @returns {Promise.<*>}\n */\nexport async function signEip712(web3: any, account: string, method: string, params: any) {\n  const provider = new ethers.providers.Web3Provider(web3.currentProvider)\n  const response: any = await provider.send(\n    method,\n    params\n  ).catch(err => {\n    return { error: { message: err.message } }\n  })\n\n  if (response?.result) {\n    return response\n  } else {\n    throw new Error(response['error']['message'])\n  }\n}\n\nexport async function signEip712WalletConnect(web3: any, account: string, typedData: any) {\n  try {\n    let response: any\n    \n    if (getWindowSafely()?.ethereum?.isLoopring || !web3.currentProvider?.signer?.session) {\n      const result: any = await new Promise((resolve) => {\n        web3.currentProvider?.sendAsync(\n          {\n            method: 'eth_signTypedData',\n            params: [account, typedData],\n            account,\n          },\n          (err: any, result: any) => {\n            if (err) {\n              resolve({ error: { message: err.message } })\n              return\n            }\n\n            if (result.error) {\n              resolve({ error: { message: result.error.message } })\n              return\n            }\n\n            resolve({ result: result.result })\n          },\n        )\n      })\n      // LOG: for signature\n      myLog('eth_signTypedData', result)\n      response = result?.result\n    } else {\n      const provider = new ethers.providers.Web3Provider(web3.currentProvider)\n      response = await provider.send('eth_signTypedData', [account, typedData])\n    }\n    // LOG: for signature\n    myLog('eth_signTypedData success', response)\n    return response\n  } catch (err) {\n    // LOG: for signature\n    myLog('eth_signTypedData error', err)\n    return { error: err as any }\n  }\n}\n\nexport async function getEcDSASig(\n  web3: any,\n  typedData: any,\n  address: string | undefined,\n  type: GetEcDSASigType,\n  chainId: ChainId,\n  accountId?: number,\n  pwd = '',\n  walletType?: ConnectorNames,\n  counterFactualInfo?: CounterFactualInfo,\n) {\n  const msgParams = JSON.stringify(typedData)\n  const params = [address, msgParams]\n\n  let response: any, hash: Buffer | string, signEip712Result: any, signature: any\n  switch (type) {\n    case GetEcDSASigType.HasDataStruct:\n      try {\n        const provider = new ethers.providers.Web3Provider(web3.currentProvider)\n        \n        response = await provider.send(\n          'eth_signTypedData_v4',\n          params,\n        )\n      } catch (error) {\n        console.log('eth_signTypedData_v4 error', error)\n        throw error\n      }\n      return {\n        ecdsaSig: response,\n      }\n\n    case GetEcDSASigType.WithoutDataStruct:\n      hash = sigUtil.TypedDataUtils.sign(typedData)\n      hash = fm.toHex(hash)\n      if (!walletType) {\n        throw Error('no walletType set!')\n      }\n      signature = await personalSign(\n        web3,\n        address,\n        pwd,\n        hash,\n        walletType,\n        chainId,\n        counterFactualInfo ? counterFactualInfo.accountId : undefined,\n        counterFactualInfo,\n        IsMobile.any(),\n      )\n\n      if (signature?.sig) {\n        return {\n          ecdsaSig: signature.sig,\n          counterFactualInfo: signature.counterFactualInfo,\n        }\n      }\n      console.log('WithoutDataStruct error', signature?.error)\n      if (typeof signature?.error == 'string') {\n        throw new Error(signature.error)\n      } else {\n        throw signature?.error\n      }\n\n    // case GetEcDSASigType.Contract:\n    //   signEip712Result = await signEip712WalletConnect(\n    //     web3,\n    //     address as string,\n    //     msgParams\n    //   );\n    //\n    //   if (signEip712Result.error) {\n    //     throw Error(\"Contract sig error\");\n    //   }\n    //\n    //   return {\n    //     ecdsaSig: signEip712Result,\n    //   };\n    default:\n      break\n  }\n  throw Error('getEcDSASig unsupported switch case:' + type)\n}\n\nexport function convertPublicKey2(pk: PublicKey) {\n  // return new BN(EdDSA.pack(pk.x, pk.y), 16);\n  return new BN(EDDSAUtil.pack(pk.x, pk.y), 16)\n}\n\nexport function convertPublicKey(pk: PublicKey) {\n  const publicKeyX = fm.formatEddsaKey(fm.toHex(fm.toBig(pk.x)))\n  const publicKeyY = fm.formatEddsaKey(fm.toHex(fm.toBig(pk.y)))\n\n  // return new BN(EdDSA.pack(publicKeyX, publicKeyY), 16);\n  return new BN(EDDSAUtil.pack(publicKeyX, publicKeyY), 16)\n}\n\nexport function getUpdateAccountEcdsaTypedData(data: UpdateAccountRequestV3, chainId: ChainId) {\n  const message: any = {\n    owner: data.owner,\n    accountID: data.accountId,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.volume,\n    publicKey: fm.addHexPrefix(convertPublicKey2(data.publicKey).toString(16)),\n    validUntil: data.validUntil,\n    nonce: data.nonce,\n  }\n\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      AccountUpdate: [\n        { name: 'owner', type: 'address' },\n        { name: 'accountID', type: 'uint32' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'publicKey', type: 'uint256' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'nonce', type: 'uint32' },\n      ],\n    },\n    primaryType: 'AccountUpdate',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n\n  return typedData\n}\n\n// withdraw\nexport function get_EddsaSig_OffChainWithdraw(\n  request: OffChainWithdrawalRequestV3,\n  eddsaKey: string,\n) {\n  const onchainDataHash = abi\n    .soliditySHA3(\n      ['uint256', 'address', 'bytes'],\n      [\n        request.minGas,\n        new BN(fm.clearHexPrefix(request.to), 16),\n        new Buffer(request.extraData ?? ''),\n      ],\n    )\n    .slice(0, 20)\n\n  const orderHashStr = fm.addHexPrefix(onchainDataHash.toString('hex'))\n\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.accountId,\n    request.token.tokenId,\n    request.token.volume,\n    request.maxFee.tokenId,\n    request.maxFee.volume,\n    orderHashStr,\n    request.validUntil,\n    request.storageId,\n  ]\n\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport function getOrderHash(request: SubmitOrderRequestV3) {\n  const p = field.SNARK_SCALAR_FIELD\n  const poseidonParams = new PoseidonParams(\n    p,\n    12,\n    6,\n    53,\n    'poseidon',\n    BigNumber.from(5),\n    null,\n    null,\n    128,\n  )\n\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.storageId,\n    request.accountId,\n    request.sellToken.tokenId,\n    request.buyToken.tokenId,\n    request.sellToken.volume,\n    request.buyToken.volume,\n    request.validUntil,\n    request.maxFeeBips,\n    request.fillAmountBOrS ? 1 : 0,\n    new BN(ethUtil.toBuffer(request.taker)).toString(),\n  ]\n  let bigIntInputs: any\n  bigIntInputs = []\n  for (let i = 0; i < inputs.length; i++) {\n    const input = inputs[i]\n    bigIntInputs.push(BigNumber.from(input))\n  }\n  const hash = permunation.poseidon(bigIntInputs, poseidonParams)\n  let hashInHex = hash.toHexString()\n  return hashInHex\n}\n\nexport function getWithdrawTypedData(\n  data: OffChainWithdrawalRequestV3,\n  chainId: ChainId,\n): sigUtil.EIP712TypedData {\n  const message = {\n    owner: data.owner,\n    accountID: data.accountId,\n    tokenID: data.token.tokenId,\n    amount: data.token.volume,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.volume,\n    to: data.to,\n    extraData: data.extraData ? data.extraData : '0x',\n    minGas: data.minGas,\n    validUntil: data.validUntil,\n    storageID: data.storageId,\n  }\n\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      Withdrawal: [\n        { name: 'owner', type: 'address' },\n        { name: 'accountID', type: 'uint32' },\n        { name: 'tokenID', type: 'uint16' },\n        { name: 'amount', type: 'uint96' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'to', type: 'address' },\n        { name: 'extraData', type: 'bytes' },\n        { name: 'minGas', type: 'uint256' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'storageID', type: 'uint32' },\n      ],\n    },\n    primaryType: 'Withdrawal',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId: chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n  return typedData\n}\n\nexport async function offchainWithdrawWrap({\n  withdraw,\n  chainId,\n  web3,\n  accountId,\n  isHWAddr,\n  counterFactualInfo,\n}: {\n  withdraw: loopring_defs.OffChainWithdrawalRequestV3\n  web3: any\n  chainId: ChainId\n  accountId: number\n  isHWAddr: boolean\n  counterFactualInfo?: CounterFactualInfo\n}) {\n  const typedData = getWithdrawTypedData(withdraw, chainId)\n  try {\n    const result = await getEcDSASig(\n      web3,\n      typedData,\n      withdraw.owner,\n      isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n      chainId,\n      accountId,\n      '',\n      ConnectorNames.Unknown,\n      counterFactualInfo,\n    )\n    return result.ecdsaSig\n  } catch (error) {\n    // console.log('EcDSASig error try sign WithoutDataStruct')\n    throw error\n  }\n}\n\n//NFT Withdraw\nexport function get_EddsaSig_NFT_Withdraw(request: NFTWithdrawRequestV3, eddsaKey: string) {\n  const onchainDataHash = abi\n    .soliditySHA3(\n      ['uint256', 'address', 'bytes'],\n      [\n        request.minGas,\n        new BN(fm.clearHexPrefix(request.to), 16),\n        new Buffer(request.extraData ?? ''),\n      ],\n    )\n    .slice(0, 20)\n\n  const orderHashStr = fm.addHexPrefix(onchainDataHash.toString('hex'))\n\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.accountId,\n    request.token.tokenId,\n    request.token.amount,\n    request.maxFee.tokenId,\n    request.maxFee.amount,\n    orderHashStr,\n    request.validUntil,\n    request.storageId,\n  ]\n\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport function getNftData(request: NFTMintRequestV3) {\n  const p = field.SNARK_SCALAR_FIELD\n  const poseidonParams = new PoseidonParams(\n    p,\n    7,\n    6,\n    52,\n    'poseidon',\n    BigNumber.from(5),\n    null,\n    null,\n    128,\n  )\n  const idNo0x = fm.clearHexPrefix(request.nftId)\n  let nftIdLo, nftIdHi\n  if (idNo0x.length > 32) {\n    nftIdLo = new BN(idNo0x.substr(idNo0x.length - 32, 32), 16).toString(10)\n    nftIdHi = new BN(idNo0x.substr(0, idNo0x.length - 32), 16).toString(10)\n  } else {\n    nftIdLo = new BN(idNo0x.substr(0, idNo0x.length), 16).toString(10)\n    nftIdHi = 0\n  }\n  myLog('nftIdLo', nftIdLo, 'nftIdHi', nftIdHi)\n\n  const inputs = [\n    request.minterAddress,\n    request.nftType,\n    request.tokenAddress,\n    nftIdLo,\n    nftIdHi,\n    request.royaltyPercentage,\n  ]\n\n  let bigIntInputs: any\n  bigIntInputs = []\n  for (let i = 0; i < inputs.length; i++) {\n    const input = inputs[i]\n    bigIntInputs.push(BigNumber.from(input))\n  }\n  const hash = permunation.poseidon(bigIntInputs, poseidonParams)\n  return hash\n}\n\nexport function getNFTMintTypedData(\n  data: NFTMintRequestV3,\n  chainId: ChainId,\n  web3: Web3,\n): sigUtil.EIP712TypedData {\n  let nftId = data.nftId\n  if (data.nftId.startsWith('0x')) {\n    nftId = web3.utils.hexToNumberString(data.nftId)\n  }\n  const message = {\n    minterAddress: data.minterAddress,\n    toAccountId: data.toAccountId,\n    nftType: data.nftType.toString(),\n    amount: data.amount,\n    nftId: nftId,\n    nftAddress: data.tokenAddress,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.amount,\n    validUntil: data.validUntil,\n    storageID: data.storageId,\n  }\n\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      Mint: [\n        { name: 'minterAddress', type: 'address' },\n        { name: 'toAccountId', type: 'uint32' },\n        { name: 'nftType', type: 'string' },\n        { name: 'amount', type: 'uint96' },\n        { name: 'nftId', type: 'uint256' },\n        { name: 'nftAddress', type: 'address' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'storageID', type: 'uint32' },\n      ],\n    },\n    primaryType: 'Mint',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId: chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n  return typedData\n}\n\nexport function getNFTWithdrawTypedData(\n  data: NFTWithdrawRequestV3,\n  chainId: ChainId,\n): sigUtil.EIP712TypedData {\n  const message = {\n    owner: data.owner,\n    accountID: data.accountId,\n    tokenID: data.token.tokenId,\n    amount: data.token.amount,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.amount,\n    to: data.to,\n    extraData: data.extraData ? data.extraData : '',\n    minGas: data.minGas,\n    validUntil: data.validUntil,\n    storageID: data.storageId,\n  }\n\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      Withdrawal: [\n        { name: 'owner', type: 'address' },\n        { name: 'accountID', type: 'uint32' },\n        { name: 'tokenID', type: 'uint16' },\n        { name: 'amount', type: 'uint96' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'to', type: 'address' },\n        { name: 'extraData', type: 'bytes' },\n        { name: 'minGas', type: 'uint256' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'storageID', type: 'uint32' },\n      ],\n    },\n    primaryType: 'Withdrawal',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId: chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n  return typedData\n}\n\nexport async function withdrawNFTWrap({\n  withdraw,\n  chainId,\n  web3,\n  accountId,\n  isHWAddr,\n  counterFactualInfo,\n}: {\n  withdraw: loopring_defs.NFTWithdrawRequestV3\n  web3: any\n  chainId: ChainId\n  accountId: number\n  isHWAddr: boolean\n  counterFactualInfo?: CounterFactualInfo\n}) {\n  const typedData = getNFTWithdrawTypedData(withdraw, chainId)\n  try {\n    const result = await getEcDSASig(\n      web3,\n      typedData,\n      withdraw.owner,\n      isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n      chainId,\n      accountId,\n      '',\n      ConnectorNames.Unknown,\n      counterFactualInfo,\n    )\n    return result.ecdsaSig\n  } catch (error) {\n    // console.log('EcDSASig error try sign WithoutDataStruct')\n    throw error\n  }\n}\n\n//NFT Mint\nexport function get_EddsaSig_NFT_Mint(request: NFTMintRequestV3, eddsaKey: string) {\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.minterId,\n    request.toAccountId,\n    getNftData(request),\n    request.amount,\n    request.maxFee.tokenId,\n    request.maxFee.amount,\n    request.validUntil,\n    request.storageId,\n  ]\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport function get_Is_Nft_Token(tokenId: number) {\n  return tokenId >= MIN_NFT_TOKENID\n}\n\n// NFT Order\nexport function get_EddsaSig_NFT_Order(request: NFTOrderRequestV3, eddsaKey: string) {\n  let fillAmountBOrS = 0\n  if (request.fillAmountBOrS) {\n    fillAmountBOrS = 1\n  }\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.storageId,\n    request.accountId,\n    request.sellToken?.tokenId !== undefined ? request.sellToken.tokenId : '',\n    (request.buyToken as any)?.nftData\n      ? (request.buyToken as NFTTokenAmountInfo).nftData\n      : request.buyToken.tokenId,\n    request.sellToken?.amount ? request.sellToken.amount : 0,\n    request.buyToken?.amount ? request.buyToken.amount : 0,\n    request.validUntil,\n    request.maxFeeBips,\n    fillAmountBOrS,\n    new BN(ethUtil.toBuffer(request.taker)).toString(),\n  ]\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport function get_EddsaSig_Dual_Order(request: DualOrderRequest, eddsaKey: string) {\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.storageId,\n    request.accountId,\n    request.sellToken.tokenId,\n    request.buyToken.tokenId,\n    request.sellToken.volume,\n    request.buyToken.volume,\n    request.validUntil,\n    request.maxFeeBips,\n    request.fillAmountBOrS ? 1 : 0,\n    0,\n  ]\n\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport async function mintNFTWrap({\n  mint,\n  chainId,\n  web3,\n  accountId,\n  isHWAddr,\n  counterFactualInfo,\n}: {\n  mint: loopring_defs.NFTMintRequestV3\n  chainId: ChainId\n  web3: any\n  accountId: number\n  isHWAddr: boolean\n  counterFactualInfo?: CounterFactualInfo\n}) {\n  const typedData = getNFTMintTypedData(mint, chainId, web3)\n  try {\n    const result = await getEcDSASig(\n      web3,\n      typedData,\n      mint.minterAddress,\n      isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n      chainId,\n      accountId,\n      '',\n      ConnectorNames.Unknown,\n      counterFactualInfo,\n    )\n    return result.ecdsaSig\n  } catch (error) {\n    // console.log('EcDSASig error try sign WithoutDataStruct')\n    throw error\n  }\n}\n\n// transfer\nexport function get_EddsaSig_Transfer(request: OriginTransferRequestV3, eddsaKey: string) {\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.payerId,\n    request.payeeId,\n    request.token.tokenId,\n    request.token.volume,\n    request.maxFee.tokenId,\n    request.maxFee.volume,\n    new BN(ethUtil.toBuffer(request.payeeAddr)).toString(),\n    0,\n    0,\n    request.validUntil,\n    request.storageId,\n  ]\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport function getTransferOldTypedData(\n  data: OriginTransferRequestV3,\n  chainId: ChainId,\n): sigUtil.EIP712TypedData {\n  const message = {\n    from: data.payerAddr,\n    to: data.payeeAddr,\n    tokenID: data.token.tokenId,\n    amount: data.token.volume,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.volume,\n    validUntil: data.validUntil,\n    storageID: data.storageId,\n  }\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      Transfer: [\n        { name: 'from', type: 'address' },\n        { name: 'to', type: 'address' },\n        { name: 'tokenID', type: 'uint16' },\n        { name: 'amount', type: 'uint96' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'storageID', type: 'uint32' },\n      ],\n    },\n    primaryType: 'Transfer',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId: chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n  return typedData\n}\n\nexport function getTransferTypedData(\n  data: OriginTransferRequestV3,\n  chainId: ChainId,\n): sigUtil.EIP712TypedData {\n  const message = {\n    from: data.payerAddr,\n    to: data.payeeAddr,\n    tokenID: data.token.tokenId,\n    amount: data.token.volume,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.volume,\n    validUntil: data.validUntil,\n    storageID: data.storageId,\n  }\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      Transfer: [\n        { name: 'from', type: 'address' },\n        { name: 'to', type: 'address' },\n        { name: 'tokenID', type: 'uint16' },\n        { name: 'amount', type: 'uint96' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'storageID', type: 'uint32' },\n      ],\n    },\n    primaryType: 'Transfer',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId: chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n  return typedData\n}\n\nexport async function transferWrap({\n  transfer,\n  chainId,\n  web3,\n  isHWAddr,\n  accountId,\n  counterFactualInfo,\n}: {\n  transfer: loopring_defs.OriginTransferRequestV3\n  web3: any\n  chainId: ChainId\n  accountId: number\n  isHWAddr: boolean\n  counterFactualInfo?: CounterFactualInfo\n}): Promise<string> {\n  const typedData = getTransferTypedData(transfer, chainId)\n  try {\n    const result = await getEcDSASig(\n      web3,\n      typedData,\n      transfer.payerAddr,\n      isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n      chainId,\n      accountId,\n      '',\n      ConnectorNames.Unknown,\n      counterFactualInfo,\n    )\n    return result.ecdsaSig\n  } catch (error) {\n    // console.log('EcDSASig error try sign WithoutDataStruct')\n    throw error\n  }\n}\n\nexport async function transferNFTWrap({\n  transfer,\n  chainId,\n  web3,\n  isHWAddr,\n  accountId,\n  counterFactualInfo,\n}: {\n  transfer: loopring_defs.OriginNFTTransferRequestV3\n  chainId: ChainId\n  web3: any\n  accountId: number\n  isHWAddr: boolean\n  counterFactualInfo?: CounterFactualInfo\n}): Promise<string> {\n  const typedData = getNFTTransferTypedData(transfer, chainId)\n  try {\n    const result = await getEcDSASig(\n      web3,\n      typedData,\n      transfer.fromAddress,\n      isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n      chainId,\n      accountId,\n      '',\n      ConnectorNames.Unknown,\n      counterFactualInfo,\n    )\n    return result.ecdsaSig\n  } catch (error) {\n    // console.log('EcDSASig error try sign WithoutDataStruct')\n    throw error\n  }\n}\n\nexport function get_EddsaSig_NFT_Transfer(request: OriginNFTTransferRequestV3, eddsaKey: string) {\n  const inputs = [\n    new BN(ethUtil.toBuffer(request.exchange)).toString(),\n    request.fromAccountId,\n    request.toAccountId,\n    request.token.tokenId,\n    request.token.amount,\n    request.maxFee.tokenId,\n    request.maxFee.amount,\n    new BN(ethUtil.toBuffer(request.toAddress)).toString(),\n    0,\n    0,\n    request.validUntil,\n    request.storageId,\n  ]\n  return getEdDSASigWithPoseidon(inputs, eddsaKey)\n}\n\nexport function getNftTradeHash(request: NFTTradeRequestV3) {\n  const p = field.SNARK_SCALAR_FIELD\n  const poseidonParams = new PoseidonParams(\n    p,\n    7,\n    6,\n    52,\n    'poseidon',\n    BigNumber.from(5),\n    null,\n    null,\n    128,\n  )\n\n  const inputs = [\n    request.taker.accountId,\n    request.taker.sellToken.tokenId,\n    request.taker.storageId,\n    request.maker.accountId,\n    request.maker.sellToken.tokenId,\n    request.maker.storageId,\n  ]\n  let bigIntInputs: any\n  bigIntInputs = []\n  for (let i = 0; i < inputs.length; i++) {\n    const input = inputs[i]\n    bigIntInputs.push(BigNumber.from(input))\n  }\n  const hash = permunation.poseidon(bigIntInputs, poseidonParams)\n  let hashInHex = hash.toHexString()\n  return hashInHex\n}\n\nexport function getNFTTransferTypedData(\n  data: OriginNFTTransferRequestV3,\n  chainId: ChainId,\n): sigUtil.EIP712TypedData {\n  const message = {\n    from: data.fromAddress,\n    to: data.toAddress,\n    tokenID: data.token.tokenId,\n    amount: data.token.amount,\n    feeTokenID: data.maxFee.tokenId,\n    maxFee: data.maxFee.amount,\n    validUntil: data.validUntil,\n    storageID: data.storageId,\n  }\n  const typedData: sigUtil.EIP712TypedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      Transfer: [\n        { name: 'from', type: 'address' },\n        { name: 'to', type: 'address' },\n        { name: 'tokenID', type: 'uint16' },\n        { name: 'amount', type: 'uint96' },\n        { name: 'feeTokenID', type: 'uint16' },\n        { name: 'maxFee', type: 'uint96' },\n        { name: 'validUntil', type: 'uint32' },\n        { name: 'storageID', type: 'uint32' },\n      ],\n    },\n    primaryType: 'Transfer',\n    domain: {\n      name: 'Loopring Protocol',\n      version: '3.6.0',\n      chainId: chainId,\n      verifyingContract: data.exchange,\n    },\n    message: message,\n  }\n  return typedData\n}\n\nexport function eddsaSign(typedData: any, eddsaKey: string) {\n  const hash = fm.toHex(sigUtil.TypedDataUtils.sign(typedData))\n  // LOG: for signature\n  // myLog('eddsaSign', hash)\n  const sigHash = fm.toHex(new BigInteger(hash, 16).idiv(8))\n  const signature = EDDSAUtil.sign(eddsaKey, sigHash)\n  return {\n    eddsaSig:\n      fm.formatEddsaKey(fm.toHex(fm.toBig(signature.Rx))) +\n      fm.clearHexPrefix(fm.formatEddsaKey(fm.toHex(fm.toBig(signature.Ry)))) +\n      fm.clearHexPrefix(fm.formatEddsaKey(fm.toHex(fm.toBig(signature.s)))),\n  }\n}\n\nexport function eddsaSignWithDomain(\n  domainHax: string,\n  primaryType: string,\n  message: sigUtil.EIP712Message,\n  types: sigUtil.EIP712Types,\n  eddsaKey: string,\n) {\n  const parts = [Buffer.from('1901', 'hex')]\n  parts.push(Buffer.from(domainHax.slice(2), 'hex'))\n\n  //https://github.com/MetaMask/eth-sig-util/blob/main/CHANGELOG.md\n  parts.push(sigUtil.TypedDataUtils.hashStruct(primaryType, message, types))\n  const hash = fm.toHex(ethUtil.keccak(Buffer.concat(parts))) //5.2.0 - 2018-04-27 keccak  sha3() -> keccak()\n  const sigHash = fm.toHex(new BigInteger(hash, 16).idiv(8))\n  const signature = EDDSAUtil.sign(eddsaKey, sigHash)\n  return {\n    eddsaSig:\n      fm.formatEddsaKey(fm.toHex(fm.toBig(signature.Rx))) +\n      fm.clearHexPrefix(fm.formatEddsaKey(fm.toHex(fm.toBig(signature.Ry)))) +\n      fm.clearHexPrefix(fm.formatEddsaKey(fm.toHex(fm.toBig(signature.s)))),\n  }\n}\n\nexport function getAmmJoinEcdsaTypedData(data: JoinAmmPoolRequest, patch: AmmPoolRequestPatch) {\n  const message = {\n    owner: data.owner,\n    joinAmounts: [data.joinTokens.pooled[0].volume, data.joinTokens.pooled[1].volume],\n    joinStorageIDs: data.storageIds,\n    mintMinAmount: data.joinTokens.minimumLp.volume,\n    fee: data.fee,\n    validUntil: data.validUntil,\n  }\n\n  const typedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      PoolJoin: [\n        { name: 'owner', type: 'address' },\n        { name: 'joinAmounts', type: 'uint96[]' },\n        { name: 'joinStorageIDs', type: 'uint32[]' },\n        { name: 'mintMinAmount', type: 'uint96' },\n        { name: 'fee', type: 'uint96' },\n        { name: 'validUntil', type: 'uint32' },\n      ],\n    },\n    primaryType: 'PoolJoin',\n    domain: {\n      name: patch.ammName,\n      version: '1.0.0',\n      chainId: patch.chainId,\n      verifyingContract: patch.poolAddress,\n    },\n    message: message,\n  }\n  return typedData\n}\n\n// ammpool join\nexport function get_EddsaSig_JoinAmmPool(data: JoinAmmPoolRequest, patch: AmmPoolRequestPatch) {\n  if (data.domainSeparator) {\n    const typedData = getAmmJoinEcdsaTypedData(data, patch)\n    return eddsaSignWithDomain(\n      data.domainSeparator,\n      typedData.primaryType,\n      typedData.message,\n      typedData.types,\n      patch.eddsaKey,\n    )\n  } else {\n    const typedData = getAmmJoinEcdsaTypedData(data, patch)\n    return eddsaSign(typedData, patch.eddsaKey)\n  }\n}\n\nexport function getAmmExitEcdsaTypedData(data: ExitAmmPoolRequest, patch: AmmPoolRequestPatch) {\n  const message: any = {\n    owner: data.owner,\n    burnAmount: data.exitTokens.burned.volume,\n    burnStorageID: data.storageId,\n    exitMinAmounts: [data.exitTokens.unPooled[0].volume, data.exitTokens.unPooled[1].volume],\n    fee: data.maxFee,\n    validUntil: data.validUntil,\n  }\n  const typedData = {\n    types: {\n      EIP712Domain: [\n        { name: 'name', type: 'string' },\n        { name: 'version', type: 'string' },\n        { name: 'chainId', type: 'uint256' },\n        { name: 'verifyingContract', type: 'address' },\n      ],\n      PoolExit: [\n        { name: 'owner', type: 'address' },\n        { name: 'burnAmount', type: 'uint96' },\n        { name: 'burnStorageID', type: 'uint32' },\n        { name: 'exitMinAmounts', type: 'uint96[]' },\n        { name: 'fee', type: 'uint96' },\n        { name: 'validUntil', type: 'uint32' },\n      ],\n    },\n    primaryType: 'PoolExit',\n    domain: {\n      name: patch.ammName,\n      version: '1.0.0',\n      chainId: patch.chainId,\n      verifyingContract: patch.poolAddress,\n    },\n    message: message,\n  }\n  return typedData\n}\n\n// ammpool exit\nexport function get_EddsaSig_ExitAmmPool(data: ExitAmmPoolRequest, patch: AmmPoolRequestPatch) {\n  if (data.domainSeparator) {\n    const typedData = getAmmExitEcdsaTypedData(data, patch)\n    return eddsaSignWithDomain(\n      data.domainSeparator,\n      typedData.primaryType,\n      typedData.message,\n      typedData.types,\n      patch.eddsaKey,\n    )\n  } else {\n    const typedData = getAmmExitEcdsaTypedData(data, patch)\n    return eddsaSign(typedData, patch.eddsaKey)\n  }\n}\n"
  },
  {
    "path": "src/api/user_api.ts",
    "content": "/* eslint-disable camelcase  */\n\nimport { BaseAPI } from './base_api'\nimport * as loopring_defs from '../defs'\nimport * as sign_tools from './sign/sign_tools'\nimport {\n  generateKeyPair,\n  getEcDSASig,\n  GetEcDSASigType,\n  getEdDSASigWithPoseidon,\n  getUpdateAccountEcdsaTypedData,\n  KeyPairParams,\n} from './sign/sign_tools'\nimport BN from 'bn.js'\nimport { RequiredPart, sortObjDictionary } from '../utils'\nimport { AxiosResponse } from 'axios'\n\nexport class UserAPI extends BaseAPI {\n  /*\n   * Change the ApiKey associated with the user's account.\n   * The current ApiKey must be provided as the value of the X-API-KEY HTTP header.\n   */\n  public async updateUserApiKey<R>(\n    request: loopring_defs.UpdateUserApiKeyRequest,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<{ raw_data: R }> {\n    const dataToSig: Map<string, any> = new Map()\n\n    dataToSig.set('accountId', request.accountId)\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.API_KEY_ACTION,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  /*\n   * Fetches the next order id for a given sold token.\n   * If the need arises to repeatedly place orders in a short span of time,\n   * the order id can be initially fetched through the API and then managed locally.\n   * Each new order id can be derived from adding 2 to the last one\n   */\n  public async getNextStorageId<R>(\n    request: loopring_defs.GetNextStorageIdRequest,\n    apiKey: string,\n  ): Promise<{ raw_data: R; orderId: number; offchainId: number }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NEXT_STORAGE_ID,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const { orderId, offchainId } = raw_data\n    return {\n      orderId,\n      offchainId,\n      raw_data,\n    }\n  }\n\n  /*\n   * Get the details of an order based on order hash.\n   */\n  public async getOrderDetails<R>(\n    request: loopring_defs.GetOrderDetailsRequest,\n    apiKey: string,\n  ): Promise<{ raw_data: R; orderDetail: loopring_defs.OrderDetail }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ORDER_ACTION,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      orderDetail: raw_data,\n      raw_data,\n    }\n  }\n\n  public async getOrders<R>(\n    request: loopring_defs.GetOrdersRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    orders: loopring_defs.OrderDetail[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_MULTI_ORDERS,\n      queryParams: {\n        ...request,\n        status: request.status ? request.status.join(',') : '',\n      },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const totalNum: number = raw_data.totalNum\n    const orders: loopring_defs.OrderDetail[] = raw_data.orders\n\n    return {\n      totalNum,\n      orders,\n      raw_data,\n    }\n  }\n\n  /*\n   * Submit an order\n   */\n  public async submitOrder(\n    {\n      extraOrderType = loopring_defs.EXTRAORDER_TYPE.TRADITIONAL_ORDER,\n      ...orderRequest\n    }: loopring_defs.SubmitOrderRequestV3,\n    privateKey: string,\n    apiKey: string,\n  ) {\n    if (!orderRequest.tradeChannel) {\n      orderRequest.tradeChannel = loopring_defs.TradeChannel.MIXED\n    }\n\n    const dataToSig = [\n      orderRequest.exchange,\n      orderRequest.storageId,\n      orderRequest.accountId,\n      orderRequest.sellToken.tokenId,\n      orderRequest.buyToken.tokenId,\n      orderRequest.sellToken.volume,\n      orderRequest.buyToken.volume,\n      orderRequest.validUntil,\n      orderRequest.maxFeeBips,\n      orderRequest.fillAmountBOrS ? 1 : 0,\n      0,\n    ]\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ORDER_ACTION,\n      bodyParams: orderRequest,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG_POSEIDON,\n      sigObj: {\n        dataToSig,\n        sigPatch: loopring_defs.SigPatchField.EddsaSignature,\n        PrivateKey: privateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    return this.returnTxHash(raw_data)\n  }\n\n  public async submitStopOrder(\n    {\n      extraOrderType = loopring_defs.EXTRAORDER_TYPE.STOP_LIMIT,\n      stopSide, // = STOP_SIDE.NO_CONDITION,\n      ...orderRequest\n    }: RequiredPart<\n      loopring_defs.SubmitOrderRequestV3,\n      'extraOrderType' | 'stopSide' | 'stopPrice'\n    >,\n    privateKey: string,\n    apiKey: string,\n  ) {\n    if (!orderRequest.tradeChannel) {\n      orderRequest.tradeChannel = loopring_defs.TradeChannel.MIXED\n    }\n\n    const dataToSig = [\n      orderRequest.exchange,\n      orderRequest.storageId,\n      orderRequest.accountId,\n      orderRequest.sellToken.tokenId,\n      orderRequest.buyToken.tokenId,\n      orderRequest.sellToken.volume,\n      orderRequest.buyToken.volume,\n      orderRequest.validUntil,\n      orderRequest.maxFeeBips,\n      orderRequest.fillAmountBOrS ? 1 : 0,\n      0,\n    ]\n    const eddsaSignature = getEdDSASigWithPoseidon(dataToSig, privateKey).result\n    const bodyParams = {\n      ...orderRequest,\n      extraOrderType,\n      stopSide,\n      eddsaSignature,\n    }\n    const _dataToSig: Map<string, any> = sortObjDictionary(bodyParams)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ORDER_ACTION,\n      bodyParams: bodyParams,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig: _dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Cancel order using order hash or client-side ID.\n   */\n  public async cancelOrder<R>(\n    request: loopring_defs.CancelOrderRequest,\n    PrivateKey: string,\n    apiKey: string,\n  ): Promise<{ raw_data: R }> {\n    const dataToSig: Map<string, any> = new Map()\n\n    dataToSig.set('accountId', request.accountId)\n    if (request.orderHash) dataToSig.set('orderHash', request.orderHash)\n    if (request.clientOrderId) dataToSig.set('clientOrderId', request.clientOrderId)\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ORDER_ACTION,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.DELETE,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  /*\n   * Cancel multiple orders using order hashes\n   */\n  public async cancelMultiOrdersByHash<R>(\n    request: loopring_defs.CancelMultiOrdersByHashRequest,\n    PrivateKey: string,\n    apiKey: string,\n  ): Promise<{ raw_data: R }> {\n    const dataToSig: Map<string, any> = new Map()\n    dataToSig.set('accountId', request.accountId)\n    dataToSig.set('orderHash', request.orderHash)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ORDER_CANCEL_HASH_LIST,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.DELETE,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  /*\n   * Cancel multiple orders using clientOrderIds\n   */\n  public async cancelMultiOrdersByCreditOrderId<R>(\n    request: loopring_defs.CancelMultiOrdersByClientOrderIdRequest,\n    PrivateKey: string,\n    apiKey: string,\n  ): Promise<{ raw_data: R }> {\n    const dataToSig: Map<string, any> = new Map()\n    dataToSig.set('accountId', request.accountId)\n    dataToSig.set('clientOrderId', request.clientOrderId)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ORDER_CANCEL_CLIENT_ORDER_ID_LIST,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.DELETE,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns a list Ethereum transactions from users for exchange account registration.\n   */\n  public async getUserRegTxs<R>(\n    request: loopring_defs.GetUserRegTxsRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userRegTxs: loopring_defs.UserRegTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_REG_TXS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userRegTxs: loopring_defs.UserRegTx[] = raw_data.transactions\n    return {\n      totalNum: raw_data.totalNum,\n      userRegTxs,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns a list Ethereum transactions from users for resetting exchange passwords.\n   */\n  public async getUserPwdResetTxs<R>(\n    request: loopring_defs.GetUserPwdResetTxsRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userPwdResetTxs: loopring_defs.UserPwdResetTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_PWD_RESET_TXS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userPwdResetTxs: loopring_defs.UserPwdResetTx[] = raw_data.transactions\n    return {\n      totalNum: raw_data.totalNum,\n      userPwdResetTxs,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns user's Ether and token balances on exchange.\n   */\n  public async getUserBalances<R>(\n    request: loopring_defs.GetUserBalancesRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    userBalances: loopring_defs.LoopringMap<loopring_defs.UserBalanceInfo>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_EXCHANGE_BALANCES,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userBalances: loopring_defs.LoopringMap<loopring_defs.UserBalanceInfo> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.UserBalanceInfo) => {\n        userBalances[item.tokenId] = item\n      })\n    }\n\n    return {\n      userBalances,\n      raw_data,\n    }\n  }\n\n  public async getAssetLookRecords<R>(\n    request: loopring_defs.GetUserBalancesRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    userBalances: loopring_defs.LoopringMap<loopring_defs.UserBalanceInfo>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_ASSET_LOCK_RECORDS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userBalances: loopring_defs.LoopringMap<loopring_defs.UserBalanceInfo> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.UserBalanceInfo) => {\n        userBalances[item.tokenId] = item\n      })\n    }\n\n    return {\n      userBalances,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns user's deposit records.\n   */\n  public async getUserDepositHistory<R>(\n    request: loopring_defs.GetUserDepositHistoryRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userDepositHistory: loopring_defs.UserDepositHistoryTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_DEPOSITS_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userDepositHistory: raw_data.transactions as loopring_defs.UserDepositHistoryTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user onchain withdrawal history.\n   */\n  public async getUserOnchainWithdrawalHistory<R>(\n    request: loopring_defs.GetUserOnchainWithdrawalHistoryRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userOnchainWithdrawalHistory: loopring_defs.UserOnchainWithdrawalHistoryTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.WITHDRAWALS_ACTION,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userOnchainWithdrawalHistory:\n        raw_data.transactions as loopring_defs.UserOnchainWithdrawalHistoryTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user transfer list.\n   */\n  public async getUserTransferList<R>(\n    request: loopring_defs.GetUserTransferListRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userTransfers: loopring_defs.UserTransferRecord[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_TRANSFERS_LIST,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userTransfers: raw_data.transactions as loopring_defs.UserTransferRecord[],\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user txs\n   */\n  public async getUserTxs<R>(\n    request: loopring_defs.GetUserTxsRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userTxs: loopring_defs.UserTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_TXS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userTxs: loopring_defs.UserTx[] = []\n\n    if (raw_data?.transactions instanceof Array) {\n      raw_data.transactions.forEach((item: loopring_defs.UserTx) => {\n        userTxs.push(item)\n      })\n    }\n\n    return {\n      totalNum: raw_data?.totalNum,\n      userTxs,\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user trade history\n   */\n  public async getUserTrades<R>(\n    request: loopring_defs.GetUserTradesRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userTrades: loopring_defs.UserTrade[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_TRADE_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userTrades: loopring_defs.UserTrade[] = []\n\n    if (raw_data?.trades instanceof Array) {\n      raw_data.trades.forEach((item: any[]) => {\n        userTrades.push({\n          tradeTime: item[0],\n          tradeId: item[1],\n          side: item[2],\n          volume: item[3],\n          price: item[4],\n          market: item[5],\n          fee: item[6],\n          type: item[13],\n        })\n      })\n    }\n\n    return {\n      totalNum: raw_data.totalNum,\n      userTrades,\n      raw_data,\n    }\n  }\n\n  /*\n   * deprecated\n   * Returns the fee rate of users placing orders in specific markets\n   */\n  public async getUserFeeRate<R>(\n    request: loopring_defs.GetUserFeeRateRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    userFreeRateMap: loopring_defs.LoopringMap<loopring_defs.UserFeeRateInfo>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_FEE_RATE,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const userFreeRateMap: loopring_defs.LoopringMap<loopring_defs.UserFeeRateInfo> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item: loopring_defs.UserFeeRateInfo) => {\n        userFreeRateMap[item.symbol] = item\n      })\n    }\n\n    return {\n      userFreeRateMap,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns the user order fee rate of users placing orders in specific markets\n   */\n  public async getUserOrderFeeRate<R>(\n    request: loopring_defs.GetUserOrderFeeRateRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    feeRate: loopring_defs.FeeRateInfo\n    gasPrice: number\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_ORDER_FEE_RATE,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const gasPrice = parseInt(raw_data.gasPrice)\n\n    return {\n      feeRate: raw_data.feeRate as loopring_defs.FeeRateInfo,\n      gasPrice,\n      raw_data,\n    }\n  }\n\n  /*\n   * Query current token minimum amount to place order based on users VIP level and max fee bips\n   */\n  public async getMinimumTokenAmt<R>(\n    request: loopring_defs.GetMinimumTokenAmtRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    amounts: [loopring_defs.TokenAmount, loopring_defs.TokenAmount]\n    amountMap: loopring_defs.LoopringMap<loopring_defs.TokenAmount>\n    gasPrice: number\n    cacheOverdueAt: any\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_MINIMUM_TOKEN_AMT,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const gasPrice = parseInt(raw_data.gasPrice)\n\n    const amounts: [loopring_defs.TokenAmount, loopring_defs.TokenAmount] = raw_data?.amounts\n\n    const amountMap: loopring_defs.LoopringMap<loopring_defs.TokenAmount> = {}\n\n    if (amounts instanceof Array) {\n      amounts.forEach((item: loopring_defs.TokenAmount) => {\n        amountMap[item.tokenSymbol] = item\n      })\n    }\n\n    return {\n      amounts,\n      amountMap,\n      gasPrice,\n      cacheOverdueAt: raw_data.cacheOverdueAt,\n      raw_data,\n    }\n  }\n\n  /*\n   * Query current fee amount\n   */\n  public async getOffchainFeeAmt<R>(\n    request: loopring_defs.GetOffchainFeeAmtRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    fees: loopring_defs.LoopringMap<loopring_defs.OffchainFeeInfo>\n    gasPrice: number\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_OFFCHAIN_FEE_AMT,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const gasPrice = parseInt(raw_data.gasPrice)\n\n    const fees: loopring_defs.LoopringMap<loopring_defs.OffchainFeeInfo> = {}\n\n    if (raw_data?.fees instanceof Array) {\n      raw_data.fees.forEach((item: loopring_defs.OffchainFeeInfo) => {\n        fees[item.token] = item\n      })\n    }\n\n    return {\n      fees,\n      gasPrice,\n      raw_data,\n    }\n  }\n\n  /*\n   * Query current NFTAction fee amount\n   */\n  public async getNFTOffchainFeeAmt<R>(\n    request: loopring_defs.GetNFTOffchainFeeAmtRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    fees: loopring_defs.LoopringMap<loopring_defs.OffchainFeeInfo>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NFT_OFFCHAIN_FEE_AMT,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const fees: loopring_defs.LoopringMap<loopring_defs.OffchainFeeInfo> = {}\n    if (raw_data?.fees instanceof Array) {\n      raw_data.fees.forEach((item: loopring_defs.OffchainFeeInfo) => {\n        fees[item.token] = item\n      })\n    }\n\n    return {\n      fees,\n      raw_data,\n    }\n  }\n\n  /*\n   * Submit NFTAction Validate Order request\n   */\n  public async submitNFTValidateOrder<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginNFTValidateOrderRequestV3WithPatch,\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, eddsaKey, apiKey } = req\n\n    request.eddsaSignature = sign_tools.get_EddsaSig_NFT_Order(request, eddsaKey).result\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_VALIDATE_ORDER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    // myLog(\"NFTAction Validate Order request\", request);\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit NFTAction Trade request\n   */\n  public async submitNFTTrade<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginNFTTradeRequestV3WithPatch,\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, apiKey, eddsaKey } = req\n\n    const dataToSig: Map<string, any> = new Map()\n    dataToSig.set('maker', request.maker)\n    dataToSig.set('makerFeeBips', request.makerFeeBips)\n    dataToSig.set('taker', request.taker)\n    dataToSig.set('takerFeeBips', request.takerFeeBips)\n    // request.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n    //   request,\n    //   eddsaKey\n    // );\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_TRADE,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        // sigPatch: loopring_defs.SigPatchField.EddsaSignature,\n        PrivateKey: eddsaKey,\n      },\n    }\n    // myLog(\"NFTAction Trade request\", request);\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    return this.returnTxHash(raw_data)\n  }\n\n  async getUserOwenCollection<R>(\n    request: loopring_defs.GetUserOwnerCollectionRequest,\n    apiKey: string,\n  ) {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NFT_COLLECTION,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      totalNum: raw_data == null ? void 0 : raw_data.totalNum,\n      collections: raw_data.collections.map(({ collection, ...rest }: any) => {\n        return {\n          ...collection,\n          extends: {\n            ...rest,\n          },\n        }\n      }) as loopring_defs.CollectionMeta & { extends: { [a: string]: any } }[],\n      raw_data,\n    }\n  }\n\n  async getUserLegacyCollection<R>(\n    request: loopring_defs.GetUserLegacyCollectionRequest,\n    apiKey: string,\n  ) {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NFT_LEGACY_COLLECTION,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      totalNum: raw_data == null ? void 0 : raw_data.totalNum,\n      collections: raw_data.collections.map(({ collection, ...rest }: any) => {\n        return {\n          ...collection,\n          extends: {\n            ...rest,\n          },\n        }\n      }) as loopring_defs.CollectionMeta & { extends: { [a: string]: any } }[],\n      raw_data,\n    }\n  }\n\n  async getUserNFTCollection(request: loopring_defs.GetUserNFTCollectionRequest, apiKey: string) {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NFT_COLLECTION_HASNFT,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      totalNum: raw_data == null ? void 0 : raw_data.totalNum,\n      collections: raw_data.collections.map(({ collection, ...rest }: any) => {\n        return {\n          ...collection,\n          extends: {\n            ...rest,\n          },\n        }\n      }) as loopring_defs.CollectionMeta & { extends: { [a: string]: any } }[],\n      raw_data,\n    }\n  }\n\n  async getUserNFTLegacyTokenAddress(request: { accountId: number }, apiKey: string) {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NFT_LEGACY_TOKENADDRESS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      result: raw_data.addresses,\n      raw_data,\n    }\n  }\n\n  /*\n   * Returns User NFTAction deposit records.\n   */\n  public async getUserNFTDepositHistory<R>(\n    request: loopring_defs.GetUserNFTDepositHistoryRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTDepositHistory: loopring_defs.UserNFTDepositHistoryTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_DEPOSIT_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTDepositHistory: raw_data.deposits as loopring_defs.UserNFTDepositHistoryTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   * Get User NFTAction Withdrawal History.\n   */\n  public async getUserNFTWithdrawalHistory<R>(\n    request: loopring_defs.GetUserNFTWithdrawalHistoryRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTWithdrawalHistory: loopring_defs.UserNFTWithdrawalHistoryTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_WITHDRAW_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTWithdrawalHistory: raw_data.withdrawals as loopring_defs.UserNFTWithdrawalHistoryTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user NFTAction transfer list.\n   */\n  public async getUserNFTTransferHistory<R>(\n    request: loopring_defs.GetUserNFTTransferHistoryRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTTransfers: loopring_defs.UserNFTTransferHistoryTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_TRANSFER_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTTransfers: raw_data.transfers as loopring_defs.UserNFTTransferHistoryTx[],\n      raw_data,\n    }\n  }\n\n  /**\n   * Get user NFTAction Mint list.\n   * @param request\n   * @param apiKey\n   */\n  public async getUserNFTMintHistory<R>(\n    request: loopring_defs.GetUserNFTMintHistoryRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTMints: loopring_defs.UserNFTMintHistoryTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_MINT_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTMints: raw_data.transfers as loopring_defs.UserNFTMintHistoryTx[],\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user All NFTAction Transaction list.\n   *\n   */\n  public async getUserNFTTransactionHistory<R>(\n    request: loopring_defs.GetUserNFTTxsRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTTxs: loopring_defs.UserNFTTxsHistory[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_TRANSACTION_HISTORY,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    if (\n      request.metadata === true &&\n      raw_data.transactions.length\n      // raw_data.transactions.metadata &&\n      // raw_data.transactions.metadata.nftId &&\n      // raw_data.transactions.metadata.nftId.startsWith(\"0x\")\n    ) {\n      raw_data.transactions = raw_data.transactions.reduce(\n        (prev: loopring_defs.UserNFTTxsHistory[], item: loopring_defs.UserNFTTxsHistory) => {\n          if (item.metadata && item.metadata.nftId && item.metadata.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.metadata.nftId.replace('0x', ''), 16)\n            item.metadata.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n          }\n\n          return [...prev, item]\n        },\n        [],\n      )\n      // const hashBN = new BN(raw_data.transactions.metadata.nftId.replace(\"0x\", \"\"), 16);\n      // raw_data.transactions.metadata.nftId= \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTTxs: raw_data.transactions as loopring_defs.UserNFTTxsHistory[],\n      raw_data,\n    }\n  }\n\n  public async getUserNFTTradeHistory<R>(\n    request: loopring_defs.GetUserNFTTradeRequest,\n    apiKey: string,\n  ): Promise<\n    | {\n        raw_data: R\n        totalNum: number\n        trades: loopring_defs.UserNFTTradeHistory[]\n      }\n    | loopring_defs.RESULT_INFO\n  > {\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_TRADE_HISTORY,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    let trades = raw_data.trades\n    return {\n      totalNum: raw_data?.totalNum,\n      trades,\n      raw_data,\n    }\n  }\n\n  public async SetReferrer<R>(\n    request: loopring_defs.SetReferrerRequest,\n    eddsaKey: string,\n  ): Promise<{ raw_data: R; result: any }> {\n    const dataToSig: Map<string, any> = new Map()\n\n    dataToSig.set('address', request.address)\n    dataToSig.set('promotionCode', request.promotionCode)\n    dataToSig.set('publicKeyX', request.publicKeyX)\n    dataToSig.set('publicKeyY', request.publicKeyY)\n    dataToSig.set('referrer', request.referrer)\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.SET_REFERRER,\n      bodyParams: request,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      result: raw_data?.result,\n      raw_data,\n    }\n  }\n\n  // Get users NFTAction balance, besides amount, it also includes tokenId and nftData\n\n  public async getUserNFTBalances<R>(\n    request: loopring_defs.GetUserNFTBalancesRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTBalances: loopring_defs.UserNFTBalanceInfo[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_BALANCES,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    if (raw_data.data.length) {\n      raw_data.data = raw_data.data.reduce(\n        (prev: loopring_defs.UserNFTBalanceInfo[], item: loopring_defs.UserNFTBalanceInfo) => {\n          if (item.nftId && item.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.nftId.replace('0x', ''), 16)\n            item.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            if (\n              request.metadata === true &&\n              item.metadata &&\n              item.metadata.nftId &&\n              item.metadata.nftId.startsWith('0x')\n            ) {\n              // const hashBN = new BN(item.metadata.nftId.replace(\"0x\", \"\"), 16);\n              item.metadata.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            }\n          }\n          return [...prev, item]\n        },\n        [],\n      )\n      // const hashBN = new BN(raw_data.transactions.metadata.nftId.replace(\"0x\", \"\"), 16);\n      // raw_data.transactions.metadata.nftId= \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    }\n    // if (raw_data.data.nftId && raw_data.data.nftId.startsWith(\"0x\")) {\n    //   const hashBN = new BN(raw_data.data.nftId.replace(\"0x\", \"\"), 16);\n    //   raw_data.data.nftId = \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    // }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTBalances: raw_data.data as loopring_defs.UserNFTBalanceInfo[],\n      raw_data,\n    }\n  }\n\n  public async getUserNFTBalancesByCollection<R>(\n    request: loopring_defs.GetUserNFTBalancesByCollectionRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTBalances: loopring_defs.UserNFTBalanceInfo[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_NFT_BALANCES_BY_COLLECTION,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    if (raw_data.data.length) {\n      raw_data.data = raw_data.data.reduce(\n        (prev: loopring_defs.UserNFTBalanceInfo[], item: loopring_defs.UserNFTBalanceInfo) => {\n          if (item.nftId && item.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.nftId.replace('0x', ''), 16)\n            item.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            if (\n              request.metadata === true &&\n              item.metadata &&\n              item.metadata.nftId &&\n              item.metadata.nftId.startsWith('0x')\n            ) {\n              // const hashBN = new BN(item.metadata.nftId.replace(\"0x\", \"\"), 16);\n              item.metadata.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            }\n          }\n          return [...prev, item]\n        },\n        [],\n      )\n      // const hashBN = new BN(raw_data.transactions.metadata.nftId.replace(\"0x\", \"\"), 16);\n      // raw_data.transactions.metadata.nftId= \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    }\n    // if (raw_data.data.nftId && raw_data.data.nftId.startsWith(\"0x\")) {\n    //   const hashBN = new BN(raw_data.data.nftId.replace(\"0x\", \"\"), 16);\n    //   raw_data.data.nftId = \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    // }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTBalances: raw_data.data as loopring_defs.UserNFTBalanceInfo[],\n      raw_data,\n    }\n  }\n\n  public async getUserNFTLegacyBalance<R>(\n    request: loopring_defs.GetUserNFTLegacyBalanceRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userNFTBalances: loopring_defs.UserNFTBalanceInfo[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NFT_LEGACY_BALANCE,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    if (raw_data.data.length) {\n      raw_data.data = raw_data.data.reduce(\n        (prev: loopring_defs.UserNFTBalanceInfo[], item: loopring_defs.UserNFTBalanceInfo) => {\n          if (item.nftId && item.nftId.startsWith('0x')) {\n            const hashBN = new BN(item.nftId.replace('0x', ''), 16)\n            item.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            if (\n              request.metadata === true &&\n              item.metadata &&\n              item.metadata.nftId &&\n              item.metadata.nftId.startsWith('0x')\n            ) {\n              // const hashBN = new BN(item.metadata.nftId.replace(\"0x\", \"\"), 16);\n              item.metadata.nftId = '0x' + hashBN.toString('hex').padStart(64, '0')\n            }\n          }\n          return [...prev, item]\n        },\n        [],\n      )\n      // const hashBN = new BN(raw_data.transactions.metadata.nftId.replace(\"0x\", \"\"), 16);\n      // raw_data.transactions.metadata.nftId= \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    }\n    // if (raw_data.data.nftId && raw_data.data.nftId.startsWith(\"0x\")) {\n    //   const hashBN = new BN(raw_data.data.nftId.replace(\"0x\", \"\"), 16);\n    //   raw_data.data.nftId = \"0x\" + hashBN.toString(\"hex\").padStart(64, \"0\");\n    // }\n    return {\n      totalNum: raw_data?.totalNum,\n      userNFTBalances: raw_data.data as loopring_defs.UserNFTBalanceInfo[],\n      raw_data,\n    }\n  }\n\n  public async getUserVIPAssets<R>(\n    request: loopring_defs.getUserVIPAssetsRequest,\n  ): Promise<{ raw_data: { data: R }; vipAsset: R }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_VIP_ASSETS,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      vipAsset: raw_data.data ? raw_data.data : raw_data,\n      raw_data,\n    }\n  }\n\n  public async getUserVIPInfo<R>(\n    request: loopring_defs.GetUserVIPInfoRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    vipInfo: {\n      createdAt: number\n      validTo: string\n      org: any\n      vipTag: any\n    }\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_VIP_INFO,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      apiKey: apiKey,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const vipInfo = {\n      createdAt: raw_data.created_at,\n      validTo: raw_data.valid_to,\n      org: raw_data.org,\n      vipTag: raw_data.vip_tag,\n    }\n\n    return {\n      vipInfo,\n      raw_data,\n    }\n  }\n\n  public async unLockAccount<R>(\n    {\n      keyPair,\n      request,\n    }: {\n      keyPair: KeyPairParams\n      request: loopring_defs.GetUserApiKeyRequest\n    },\n    publicKey: { x: string; y: string } | undefined = undefined,\n  ): Promise<\n    | AxiosResponse\n    | loopring_defs.RESULT_INFO\n    | {\n        raw_data: R\n        eddsaKey: {\n          keyPair: object\n          formatedPx: string\n          formatedPy: string\n          sk: string\n          counterFactualInfo: loopring_defs.CounterFactualInfo\n        }\n        apiKey: string\n      }\n  > {\n    let eddsaKey\n    try {\n      eddsaKey = await generateKeyPair(keyPair, publicKey)\n    } catch (error) {\n      throw error\n    }\n    if (eddsaKey) {\n      const dataToSig: Map<string, any> = sortObjDictionary(request)\n      const reqParams: loopring_defs.ReqParams = {\n        url: loopring_defs.LOOPRING_URLs.API_KEY_ACTION,\n        queryParams: request,\n        bodyParams: request,\n        method: loopring_defs.ReqMethod.GET,\n        sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n        sigObj: {\n          dataToSig,\n          PrivateKey: eddsaKey.sk,\n        },\n      }\n      let raw_data\n      try {\n        raw_data = (await this.makeReq().request(reqParams)).data\n      } catch (error) {\n        throw error as AxiosResponse\n      }\n      if (raw_data?.resultInfo) {\n        throw {\n          ...raw_data?.resultInfo,\n        }\n      } else {\n        return {\n          apiKey: raw_data.apiKey,\n          raw_data,\n          eddsaKey,\n        }\n      }\n    } else {\n      throw {\n        code: loopring_defs.LoopringErrorCode.NO_EDDSA_KEY,\n        message: loopring_defs.ConnectorError.NO_EDDSA_KEY,\n      }\n    }\n  }\n\n  /*\n   * Submit offchain withdraw request\n   */\n  public async submitOffchainWithdraw<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OffChainWithdrawalRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n\n    try {\n      ecdsaSignature = await sign_tools.offchainWithdrawWrap({\n        withdraw: request,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    request.eddsaSignature = sign_tools.get_EddsaSig_OffChainWithdraw(request, eddsaKey).result\n\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.WITHDRAWALS_ACTION,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit Internal Transfer request\n   */\n  public async submitInternalTransfer<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginTransferRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: request as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    request.eddsaSignature = sign_tools.get_EddsaSig_Transfer(request, eddsaKey).result\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_INTERNAL_TRANSFER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature,\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit Force Withdrawals request\n   */\n  public async submitForceWithdrawals<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginForcesWithdrawalsRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    const { transfer } = request\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    transfer.payeeId = 0\n    transfer.memo = `ForceWithdrawalBy${request.requesterAddress}`\n    transfer.maxFee = {\n      volume: '0',\n      tokenId: transfer.token.tokenId,\n    }\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: transfer as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n    if (counterFactualInfo) {\n      transfer.counterFactualInfo = counterFactualInfo\n    }\n    transfer.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n      transfer as loopring_defs.OriginTransferRequestV3,\n      eddsaKey,\n    ).result\n    transfer.ecdsaSignature = ecdsaSignature\n    const dataToSig: Map<string, any> = new Map()\n    dataToSig.set('requesterAddress', request.requesterAddress)\n    dataToSig.set('tokenId', request.tokenId)\n    dataToSig.set('transfer', request.transfer)\n    dataToSig.set('withdrawAddress', request.withdrawAddress)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_FORCE_WITHDRAWALS,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit NFTAction Deploy request\n   */\n  public async submitDeployNFT<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginDeployNFTRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    const { transfer } = request\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    transfer.payeeId = 0\n    transfer.memo = `NFT-DEPLOY-CONTRACT->${request.tokenAddress}`\n    transfer.maxFee = {\n      volume: '0',\n      tokenId: transfer.token.tokenId,\n    }\n\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: transfer as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    if (counterFactualInfo) {\n      transfer.counterFactualInfo = counterFactualInfo\n    }\n    transfer.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n      transfer as loopring_defs.OriginTransferRequestV3,\n      eddsaKey,\n    ).result\n    transfer.ecdsaSignature = ecdsaSignature\n    const dataToSig: Map<string, any> = new Map()\n    dataToSig.set('nftData', request.nftData)\n    dataToSig.set('tokenAddress', request.tokenAddress)\n    dataToSig.set('transfer', request.transfer)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_DEPLOY_TOKEN_ADDRESS,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit NFTAction Transfer request\n   */\n  public async submitNFTInTransfer<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginNFTTransferRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n\n    try {\n      ecdsaSignature = await sign_tools.transferNFTWrap({\n        transfer: request,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    request.eddsaSignature = sign_tools.get_EddsaSig_NFT_Transfer(request, eddsaKey).result\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_INTERNAL_TRANSFER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature,\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit NFTAction Withdraw request\n   */\n  public async submitNFTWithdraw<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginNFTWithdrawRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n\n    try {\n      ecdsaSignature = await sign_tools.withdrawNFTWrap({\n        withdraw: request,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    request.eddsaSignature = sign_tools.get_EddsaSig_NFT_Withdraw(request, eddsaKey).result\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_WITHDRAWALS,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature,\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Submit NFTAction\n   */\n  public async submitNFTMint<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginNFTMINTRequestV3WithPatch,\n    options?: {\n      accountId?: number\n      counterFactualInfo?: any\n      _noEcdsa?: boolean\n    },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    if (request.counterFactualNftInfo === undefined) {\n      request.counterFactualNftInfo = {\n        nftFactory: loopring_defs.NFTFactory[chainId],\n        nftOwner: request.minterAddress,\n        nftBaseUri: '',\n      }\n    }\n\n    request.royaltyPercentage = request.royaltyPercentage ? request.royaltyPercentage : 0\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n\n    // try {\n    //   ecdsaSignature = await sign_tools.mintNFTWrap({\n    //     mint: request,\n    //     chainId,\n    //     web3,\n    //     isHWAddr,\n    //     accountId,\n    //     counterFactualInfo,\n    //   })\n    //   // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    // } catch (error) {\n    //   throw error\n    // }\n\n    request.eddsaSignature = sign_tools.get_EddsaSig_NFT_Mint(request, eddsaKey).result\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_MINT,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      // ecdsaSignature,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  async submitNFTCollection<R>(\n    req: loopring_defs.CollectionBasicMeta,\n    chainId: loopring_defs.ChainId,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<loopring_defs.RESULT_INFO | { raw_data: R; contractAddress: string }> {\n    const _req = req.nftFactory\n      ? req\n      : //@ts-ignore\n        { ...req, nftFactory: loopring_defs.NFTFactory_Collection[chainId] }\n    const dataToSig: Map<string, any> = sortObjDictionary(_req)\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_CREATE_COLLECTION,\n      bodyParams: Object.fromEntries(dataToSig),\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      contractAddress: raw_data == null ? void 0 : raw_data.contractAddress,\n    }\n  }\n\n  async deleteNFTCollection<R>(\n    req: loopring_defs.CollectionDelete,\n    chainId: loopring_defs.ChainId,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<{ raw_data: R }> {\n    const dataToSig: Map<string, any> = sortObjDictionary(req)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.DELETE_NFT_CREATE_COLLECTION,\n      queryParams: req,\n      apiKey,\n      method: loopring_defs.ReqMethod.DELETE,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  async submitNFTLegacyCollection<R>(\n    req: loopring_defs.CollectionLegacyMeta,\n    chainId: loopring_defs.ChainId,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<loopring_defs.RESULT_INFO | { raw_data: R; result: boolean }> {\n    // const _req = req.nftFactory\n    //   ? req\n    //   : { ...req, nftFactory: loopring_defs.NFTFactory_Collection[chainId] };\n    const dataToSig: Map<string, any> = sortObjDictionary(req)\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_CREATE_LEGACY_COLLECTION,\n      bodyParams: Object.fromEntries(dataToSig),\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      result: raw_data.result,\n    }\n  }\n\n  async submitEditNFTCollection<R>(\n    req: Omit<loopring_defs.CollectionBasicMeta, 'nftFactory' | 'owner'> & {\n      collectionId: string\n      accountId: number\n    },\n    chainId: loopring_defs.ChainId,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<loopring_defs.RESULT_INFO | { raw_data: R; contractAddress: string }> {\n    // const _req = req.nftFactory ? req : {...req, nftFactory: loopring_defs.NFTFactory_Collection[ chainId ]}\n    const dataToSig: Map<string, any> = sortObjDictionary(req)\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_EDIT_COLLECTION,\n      bodyParams: Object.fromEntries(dataToSig),\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      contractAddress: raw_data == null ? void 0 : raw_data.contractAddress,\n    }\n  }\n\n  async submitUpdateNFTLegacyCollection<R>(\n    req: loopring_defs.UpdateNFTLegacyCollectionRequest,\n    chainId: loopring_defs.ChainId,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<loopring_defs.RESULT_INFO | { raw_data: R; result: boolean }> {\n    const _req = { ...req, nftHashes: req.nftHashes.join(',') }\n    const dataToSig: Map<string, any> = sortObjDictionary(_req)\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_LEGACY_UPDATE_COLLECTION,\n      bodyParams: Object.fromEntries(dataToSig),\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      result: raw_data.result,\n    }\n  }\n\n  async submitUpdateNFTGroup<R>(\n    req: loopring_defs.UpdateNFTGroupRequest,\n    chainId: loopring_defs.ChainId,\n    apiKey: string,\n    eddsaKey: string,\n  ): Promise<loopring_defs.RESULT_INFO | { raw_data: R; result: boolean }> {\n    const _req = { ...req, nftHashes: req.nftHashes.join(',') }\n    const dataToSig: Map<string, any> = sortObjDictionary(_req)\n    const reqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NFT_UPDATE_NFT_GROUP,\n      bodyParams: Object.fromEntries(dataToSig),\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data != null && raw_data.resultInfo && raw_data != null && raw_data.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      raw_data,\n      result: raw_data.result,\n    }\n  }\n\n  /*\n   * Submit Deploy Collection request\n   */\n  public async submitDeployCollection<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.OriginDeployCollectionRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    const { transfer } = request\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    transfer.payeeId = 0\n    transfer.memo = `NFT-DEPLOY-CONTRACT->${request.tokenAddress}`\n    transfer.maxFee = {\n      volume: '0',\n      tokenId: transfer.token.tokenId,\n    }\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: transfer as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    if (counterFactualInfo) {\n      transfer.counterFactualInfo = counterFactualInfo\n    }\n    transfer.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n      transfer as loopring_defs.OriginTransferRequestV3,\n      eddsaKey,\n    ).result\n    transfer.ecdsaSignature = ecdsaSignature\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_DEPLOY_COLLECTION,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Updates the EDDSA key associated with the specified account, making the previous one invalid in the process.\n   */\n  public async updateAccount<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.UpdateAccountRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request, web3, chainId, walletType, isHWAddr: isHWAddrOld, privateKey } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    const typedData = getUpdateAccountEcdsaTypedData(request, chainId)\n    try {\n      ecdsaSignature = (\n        await getEcDSASig(\n          web3,\n          typedData,\n          request.owner,\n          isHWAddr ? GetEcDSASigType.WithoutDataStruct : GetEcDSASigType.HasDataStruct,\n          chainId,\n          accountId,\n          '',\n          loopring_defs.ConnectorNames.Unknown,\n          counterFactualInfo,\n        )\n      )?.ecdsaSig\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      console.log('EcDSASig error try sign WithoutDataStruct', error)\n      throw error\n    }\n\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const dataToSig = sortObjDictionary({\n      ...request,\n      ecdsaSignature: ecdsaSignature,\n    })\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ACCOUNT_ACTION,\n      bodyParams: request,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature,\n      ...(privateKey && request.recommenderAccountId\n        ? {\n            eddsaSignatureREFER: true,\n            sigObj: {\n              PrivateKey: privateKey,\n              dataToSig: dataToSig,\n            },\n          }\n        : {}),\n    } as unknown as loopring_defs.ReqParams\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  /*\n   * Get the ApiKey associated with the user's account.\n   */\n  public async getUserApiKey<R>(\n    request: loopring_defs.GetUserApiKeyRequest,\n    eddsaKey: string,\n  ): Promise<{ raw_data: R; apiKey: string }> {\n    const dataToSig: Map<string, any> = new Map()\n\n    dataToSig.set('accountId', request.accountId)\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.API_KEY_ACTION,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    if (raw_data?.resultInfo) {\n      throw {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      return {\n        apiKey: raw_data.apiKey,\n        raw_data,\n      }\n    }\n  }\n\n  /*\n   * Get user txs\n   */\n  public async getUserBills<R>(\n    request: loopring_defs.GetUserBillsRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    userTxs: loopring_defs.UserTx[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_BILLS,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userTxs: loopring_defs.UserTx[] = []\n\n    if (raw_data?.transactions instanceof Array) {\n      raw_data.transactions.forEach((item: loopring_defs.UserTx) => {\n        userTxs.push(item)\n      })\n    }\n\n    return {\n      totalNum: raw_data?.totalNum,\n      userTxs,\n      raw_data,\n    }\n  }\n\n  public async getReferDownsides<R>(\n    request: loopring_defs.GetReferDownsides,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    records: loopring_defs.ReferDownsides[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_REFER_DOWNSIDES,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      records: raw_data.records,\n      raw_data,\n    }\n  }\n\n  public async getReferSelf<R>(\n    request: loopring_defs.GetReferSelf,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n    totalNum: number\n    records: loopring_defs.ReferSelf[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_REFER_SELF,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      totalNum: raw_data?.totalNum,\n      records: raw_data.records,\n      raw_data,\n    }\n  }\n\n  public async geReferStatistic<R = loopring_defs.ReferStatistic>(\n    request: loopring_defs.GetReferStatistic,\n    apiKey: string,\n  ): Promise<{ raw_data: R } & R> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_REFER_STATISTIC,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data: raw_data,\n    }\n  }\n\n  /*\n   * Get user txs\n   */\n  public async getUserRewards<R>(\n    request: loopring_defs.GetUserRewardRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_PROTOCOL_REWARDS,\n      queryParams: { ...request, size: request?.size ?? 200 },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user GET_USER_LOCKSUMMAR\n   */\n  public async getUserLockSummary<R = loopring_defs.UserLockSummary>(\n    request: loopring_defs.getUserLockSummaryRequest,\n    apiKey: string,\n  ): Promise<\n    R & {\n      raw_data: R\n    }\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_LOCKSUMMAR,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  public async sendTotalClaim(\n    req: loopring_defs.OriginClaimRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n  ) {\n    const { request, web3, chainId, eddsaKey, apiKey, isHWAddr: isHWAddrOld } = req\n    const { accountId, counterFactualInfo }: any = options ? options : { accountId: 0 }\n    const { transfer } = request\n\n    const isHWAddr = !!isHWAddrOld\n    let ecdsaSignature = undefined\n    transfer.payeeId = 0\n    transfer.memo = `CLAIM—ALL->${request.accountId}`\n\n    try {\n      ecdsaSignature = await sign_tools.transferWrap({\n        transfer: transfer as loopring_defs.OriginTransferRequestV3,\n        chainId,\n        web3,\n        isHWAddr,\n        accountId,\n        counterFactualInfo,\n      })\n      // ecdsaSignature += isHWAddr ? SigSuffix.Suffix03 : SigSuffix.Suffix02\n    } catch (error) {\n      throw error\n    }\n\n    if (counterFactualInfo) {\n      transfer.counterFactualInfo = counterFactualInfo\n    }\n    transfer.eddsaSignature = sign_tools.get_EddsaSig_Transfer(\n      transfer as loopring_defs.OriginTransferRequestV3,\n      eddsaKey,\n    ).result\n    transfer.ecdsaSignature = ecdsaSignature\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_TOTAL_CLAIM,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n      if (raw_data?.resultInfo) {\n        return {\n          ...raw_data?.resultInfo,\n        }\n      }\n      return { raw_data, ...raw_data }\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n\n  public async getUserTotalClaim<R>(\n    request: loopring_defs.GetTotalClaimRequest,\n    apiKey?: string,\n  ): Promise<{\n    raw_data: R\n    accountId: number\n    items: loopring_defs.ClaimItem[]\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TOTAL_CLAIM_INFO,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  public async getNotificationAll<R = loopring_defs.UserNotification>(\n    request: {\n      accountId?: number\n      offset?: number\n      limit?: number\n      network?: loopring_defs.NetworkWallet\n      notRead: boolean | undefined\n    },\n    apiKey?: string,\n  ): Promise<{\n    raw_data: any\n    totalNum: number\n    notifications: R[]\n    notRead: number\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_NOTIFICATION_ALL,\n      queryParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      totalNum: raw_data.totalNum,\n      notRead: raw_data.notRead,\n      notifications: raw_data.notifications,\n      raw_data,\n    }\n  }\n  public async submitNotificationClear<R>(\n    request: {\n      accountId: number\n      network?: loopring_defs.NetworkWallet\n    },\n    privateKey: string,\n    apiKey?: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const dataToSig: Map<string, any> = sortObjDictionary({ ...request })\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NOTIFICATION_CLEAR,\n      bodyParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n  public async submitNotificationReadAll<R>(\n    request: {\n      accountId: number\n      network?: loopring_defs.NetworkWallet\n    },\n    privateKey: string,\n    apiKey?: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const dataToSig: Map<string, any> = sortObjDictionary({ ...request })\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NOTIFICATION_READ_ALL,\n      bodyParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n  public async submitNotificationReadOne<R>(\n    request: {\n      accountId: number\n      id: number\n    },\n    privateKey: string,\n    apiKey?: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const dataToSig: Map<string, any> = sortObjDictionary({ ...request })\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_NOTIFICATION_READ_ONE,\n      bodyParams: { ...request },\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data.resultInfo,\n      }\n    }\n\n    return {\n      ...raw_data,\n      raw_data,\n    }\n  }\n\n  public async checkUpdateAccount<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.UpdateAccountRequestV3WithPatch,\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n    const { request } = req\n    const {ecdsaSignature, ..._request} = request\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.ACCOUNT_ACTION,\n      bodyParams: _request,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      sigObj: {\n        sig: ecdsaSignature,\n      },\n    } as unknown as loopring_defs.ReqParams\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  \n\n  public async submitEncryptedEcdsaKey(\n    req: {\n      accountId: number\n      eddsaEncryptedPrivateKey: string\n      nonce: number\n    },\n    eddsaSignKey: string,\n    apiKey: string,\n  ): Promise<\n    (Omit<any, 'resultInfo'> & { raw_data: Omit<any, 'resultInfo'> }) | loopring_defs.RESULT_INFO\n  > {\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_ENCRYPTED_ECDSA_KEY,\n      bodyParams: req,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      apiKey,\n      sigObj: {\n        PrivateKey: eddsaSignKey,\n        dataToSig: sortObjDictionary(req),\n      },\n    } as loopring_defs.ReqParams\n    \n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data)\n  }\n\n  public async getEncryptedEcdsaKey(\n    req: {\n      owner: string\n      ecdsaSig: string\n      validUntilInMs: number\n    }\n  ): Promise<\n    {data: {nonce: number, encryptedEddsaPrivateKey: string}}\n  > {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_ENCRYPTED_ECDSA_KEY,\n      queryParams: req,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    } as loopring_defs.ReqParams\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return raw_data\n  }\n  \n}\n"
  },
  {
    "path": "src/api/vault_api.ts",
    "content": "import { BaseAPI } from './base_api'\nimport * as loopring_defs from '../defs'\nimport { get_EddsaSig_NFT_Order, getMidPrice, sortObjDictionary } from '../index'\nimport * as sign_tools from './sign/sign_tools'\nimport { AxiosResponse } from 'axios'\n\nexport class VaultAPI extends BaseAPI {\n  public async getVaultTokens<R = loopring_defs.VaultToken[]>(apiVersion?: string): Promise<{\n    raw_data: R\n    tokens: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_TOKENS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, tokens: raw_data }\n  }\n  public async getVaultBalance<R = loopring_defs.UserBalanceInfo>(\n    request: loopring_defs.GetUserBalancesRequest,\n    apiKey: string,\n    apiVersion?: string\n  ): Promise<{\n    raw_data: R[]\n    userBalances: loopring_defs.LoopringMap<R>\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_BALANCE,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const userBalances: loopring_defs.LoopringMap<R> = {}\n\n    if (raw_data instanceof Array) {\n      raw_data.forEach((item) => {\n        userBalances[item.tokenId] = item\n      })\n    }\n\n    return {\n      userBalances,\n      raw_data,\n    }\n  }\n  public async getVaultMarkets<R = loopring_defs.VaultMarket[]>(apiVersion?: string): Promise<{\n    raw_data: R\n    markets: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_MARKETS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, markets: raw_data }\n  }\n  public async getVaultGetAvailableNFT<R = loopring_defs.VaultAvaiableNFT>(\n    request: {\n      accountId: number\n    },\n    apiKey: string,\n    apiVersion?: string\n  ): Promise<{ raw_data: R }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_GETAVAILABLENFT,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n  public async getVaultInfoAndBalance<R = loopring_defs.VaultAccountInfo>(\n    request: {\n      accountId: number\n    },\n    apiKey: string,\n    apiVersion?: string\n  ): Promise<{ raw_data: R } & R> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_ACCOUNT,\n      queryParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async getVaultGetOperationHistory<\n    R = Array<{\n      operation: loopring_defs.VaultOperation\n      order: loopring_defs.VaultOrder\n    }>,\n  >(\n    request: {\n      accountId: number\n      operateTypes: loopring_defs.VaultOperationEnum[] | string //  VaultOperationType seperate by ',',\n      offset: number\n      start?: number\n      end?: number\n      limit: number\n    },\n    apiKey: string,\n    apiVersion?: string\n  ): Promise<{ raw_data: { data: R[]; total: number } } & { list: R[]; totalNum: number }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_GETOPERATIONS,\n      queryParams: {\n        ...request,\n        operateTypes:\n          typeof request.operateTypes === 'string'\n            ? request.operateTypes\n            : request.operateTypes.join(','),\n      },\n      method: loopring_defs.ReqMethod.GET,\n      apiKey,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, list: raw_data.data as R[], totalNum: raw_data.total }\n  }\n  public async getVaultGetOperationByHash<\n    R = {\n      operation: loopring_defs.VaultOperation\n      order: loopring_defs.VaultOrder\n    },\n  >(\n    request: {\n      accountId: string\n      hash: string // OperationHash\n    },\n    apiKey: string,\n    apiVersion?: string\n  ): Promise<R & { raw_data: R }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_GETOPERATIONBY_HASH,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      apiKey,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data, ...raw_data }\n  }\n\n  public async getVaultDepth<R>({\n    request,\n  }: // tokenMap,\n  {\n    request: {\n      market: string\n      level: number\n      limit?: number\n    }\n    tokenMap?: any\n  }, apiVersion?: string): Promise<{\n    depth: loopring_defs.DepthData\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_DEPTH,\n      queryParams: { ...request },\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const symbol = raw_data.market\n    const timestamp = raw_data.timestamp\n\n    const { asks, bids, mid_price } = getMidPrice({\n      _asks: raw_data.asks,\n      _bids: raw_data.bids,\n    })\n\n    const depth: loopring_defs.DepthData = {\n      symbol,\n      // @ts-ignore\n      market: raw_data.market,\n      version: raw_data.version,\n      timestamp,\n      mid_price,\n      bids: bids.ab_arr,\n      bids_prices: bids.ab_prices,\n      bids_amtTotals: bids.ab_amtTotals,\n      bids_volTotals: bids.ab_volTotals,\n      bids_amtTotal: bids.amtTotal.toString(),\n      bids_volTotal: bids.volTotal.toString(),\n      asks: asks.ab_arr,\n      asks_prices: asks.ab_prices,\n      asks_amtTotals: asks.ab_amtTotals,\n      asks_volTotals: asks.ab_volTotals,\n      asks_amtTotal: asks.amtTotal.toString(),\n      asks_volTotal: asks.volTotal.toString(),\n    }\n\n    return {\n      depth,\n      raw_data: raw_data as unknown as R,\n    }\n  }\n  public async submitVaultJoin<R = loopring_defs.VaultOrderResult>({\n    request,\n    eddsaKey,\n    apiKey,\n  }: loopring_defs.VaultOrderNFTRequestV3WithPatch, apiVersion?: string) {\n    const takerOrderEddsaSignature = get_EddsaSig_NFT_Order(request, eddsaKey).result\n    const _request = {\n      ...request,\n      eddsaSignature: takerOrderEddsaSignature,\n    }\n    const dataToSig: Map<string, any> = sortObjDictionary(_request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_VAULT_JOIN,\n      bodyParams: _request,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n      apiKey,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return this.returnTxHash(raw_data)\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n  public async submitVaultOrder<R>({\n    request,\n    privateKey,\n    apiKey,\n  }: {\n    request: loopring_defs.VaultOrderRequest\n    privateKey: string\n    apiKey: string\n  }, apiVersion?: string) {\n    const dataToSig = [\n      request.exchange,\n      request.storageId,\n      request.accountId,\n      request.sellToken.tokenId,\n      request.buyToken.tokenId,\n      request.sellToken.volume,\n      request.buyToken.volume,\n      request.validUntil,\n      request.maxFeeBips,\n      request.fillAmountBOrS ? 1 : 0,\n      0,\n    ]\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_VAULT_ORDER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG_POSEIDON,\n      sigObj: {\n        dataToSig,\n        sigPatch: loopring_defs.SigPatchField.EddsaSignature,\n        PrivateKey: privateKey,\n      },\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return this.returnTxHash(raw_data)\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n  \n  public async submitVaultExit<R>({\n    request,\n    privateKey,\n    apiKey,\n  }: {\n    request: loopring_defs.VaultExitRequest\n    privateKey: string\n    apiKey: string\n  }, apiVersion?: string) {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_VAULT_EXIT,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return this.returnTxHash(raw_data)\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n\n  public async submitVaultTransfer<R>(apiVersion?: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_VAULT_TRANSFER,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data }\n  }\n  public async submitVaultBorrow<R>({\n    request,\n    privateKey,\n    apiKey,\n  }: {\n    request: loopring_defs.VaultBorrowRequest\n    privateKey: string\n    apiKey: string\n  }, apiVersion?: string) {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_VAULT_LOAN,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: privateKey,\n      },\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return this.returnTxHash(raw_data)\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n\n  public async submitVaultRepay<R>(\n    req: loopring_defs.VaultRepayRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n    apiVersion?: string\n  ) {\n    let { request, eddsaKey, apiKey } = req\n    const { counterFactualInfo }: any = options ? options : { accountId: 0 }\n    let eddsaSignature = sign_tools.get_EddsaSig_Transfer(request, eddsaKey)?.result\n    request = {\n      ...request,\n      eddsaSignature,\n    }\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_VAULT_REPAY,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature: undefined,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return this.returnTxHash(raw_data)\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n\n  public async getVaultConfig(apiKey: string, apiVersion?: string): Promise<{ data: {penaltyFeeBips: number} }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_CONFIG,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      apiKey,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { data: raw_data }\n  }\n\n  public async getVaultInfos<R>(): Promise<{ raw_data: R }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_INFOS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data }\n  }\n\n  public async sendVaultResetToken(\n    req: loopring_defs.OriginTransferRequestV3WithPatch,\n    options?: { accountId?: number; counterFactualInfo?: any },\n    apiVersion?: string\n  ) {\n    let { request, eddsaKey, apiKey } = req\n    const { counterFactualInfo }: any = options ? options : { accountId: 0 }\n    let eddsaSignature = sign_tools.get_EddsaSig_Transfer(request, eddsaKey)?.result\n    request = {\n      ...request,\n      eddsaSignature,\n    }\n    if (counterFactualInfo) {\n      request.counterFactualInfo = counterFactualInfo\n    }\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_INTERNAL_TRANSFER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      ecdsaSignature: undefined,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n      if (raw_data?.resultInfo) {\n        return {\n          ...raw_data?.resultInfo,\n        }\n      }\n      return { raw_data, ...raw_data }\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n\n  public async getVaultPrice(request: { tokenIds: string | number[] }, apiVersion?: string) {\n    // let { request, eddsaKey, apiKey } = req\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_PRICE,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      queryParams: {\n        ...request,\n        tokenIds:\n          typeof request.tokenIds === 'string' ? request?.tokenIds : request.tokenIds?.join(','),\n      },\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      return {\n        list: [...raw_data],\n        raw_data,\n      }\n    }\n  }\n\n  public async getCredit(request: { accountId: number }, apiKey: string, apiVersion?: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_CREDIT,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      queryParams: {\n        ...request\n      },\n      apiKey,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      throw {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      return {\n        tokenFactors: raw_data.tokenFactors as {\n          symbol: string\n          factor: string\n        }[],\n        maxLeverage: raw_data.maxLeverage as string\n      }\n    }\n  }\n  public async getCollaterals(request: { accountId: number }, apiKey: string, apiVersion?: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_COLLATERALS,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      queryParams: {\n        ...request\n      },\n      apiKey,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      throw {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      return {\n        collateralTokens: raw_data.data as {\n          orderHash: string\n          collateralTokenId: number\n          collateralTokenAmount: string\n          nftTokenId: number\n          nftData: string\n        }[]\n      }\n    }\n  }\n  public async submitLeverage<R>({\n    request,\n    // privateKey,\n    apiKey,\n  }: {\n    request: {\n      accountId: string\n      leverage: string\n    }\n    apiKey: string\n  }, apiVersion?: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_SUBMIT_LEVERAGE,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return raw_data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n  public async submitDustCollector(\n    req: loopring_defs.VaultDustCollectorRequest, apiVersion?: string\n  ) {\n    let { dustTransfers, eddsaKey, apiKey, accountId } = req\n    const signedDustTransfers = dustTransfers.map(dustTransfer => {\n      const eddsaSignature= sign_tools.get_EddsaSig_Transfer(dustTransfer, eddsaKey)?.result\n      return {\n        ...dustTransfer,\n        eddsaSignature\n      }\n    })\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_SUBMIT_DUST_COLLECTOR,\n      bodyParams: {\n        dustTransfers: signedDustTransfers,\n        accountId\n      },\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return {\n        hash: raw_data.hash as string\n      }\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n  \n  public async getMaxBorrowable(request: { accountId: number, symbol: string }, apiKey: string, apiVersion?: string) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_GEMAX_BORROWABLE,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      queryParams: {\n        ...request\n      },\n      apiKey,\n      extraHeaders: apiVersion\n        ? {\n            'X-API-VERSION': apiVersion,\n          }\n        : undefined,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      throw {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      return raw_data as {\n        accountId: number\n        maxBorrowableOfUsdt: string\n      }\n    }\n  }\n\n  public async closeShort<R>(\n    {\n      request,\n    }: {\n      request: {\n        accountId: number\n        tokenId: number\n        timestamp: number\n      }\n    },\n    apiKey: string,\n    eddsaKey: string,\n  ) {\n    const dataToSig: Map<string, any> = sortObjDictionary(request)\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_VAULT_CLOSE_SHORT,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.EDDSA_SIG,\n      sigObj: {\n        dataToSig,\n        PrivateKey: eddsaKey,\n      },\n    }\n    try {\n      const raw_data = (await this.makeReq().request(reqParams)).data\n      return raw_data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/wallet_api.ts",
    "content": "import { BaseAPI, personalSign } from './base_api'\nimport { sendRawTx } from './contract_api'\nimport * as loopring_defs from '../defs'\nimport { contracts as abi } from './ethereum/contracts'\nimport * as sign_tools from './sign/sign_tools'\nimport { sortObjDictionary, toHex } from '../utils'\nimport { myLog } from '../utils/log_tools'\nimport { AxiosResponse } from 'axios'\nimport { signHebaoApproveWrap } from './config'\n\nexport class WalletAPI extends BaseAPI {\n  /*\n   * Get user assets\n   */\n  public async getUserAssets(request: loopring_defs.GetUserAssetsRequest) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_ASSETS,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n\n    const assetSeries: string[] = []\n    const timestampSeries: number[] = []\n    const dateSeries: string[] = []\n\n    if (raw_data?.data instanceof Array) {\n      raw_data.data.forEach((item: loopring_defs.UserAssetInfo) => {\n        assetSeries.push(item.amount)\n        timestampSeries.push(item.createdAt)\n        dateSeries.push(item.createdAtStr)\n      })\n    }\n\n    return {\n      assetSeries,\n      timestampSeries,\n      dateSeries,\n      userAssets: raw_data.data as loopring_defs.UserAssetInfo[],\n      raw_data,\n    }\n  }\n\n  /**\n   *\n   * @param approveRecordId  request.id\n   */\n  public async rejectHebao(req: loopring_defs.RejectHebaoRequestV3WithPatch) {\n    const { web3, address, request, chainId } = req\n    const dataToSig = sortObjDictionary(request)\n    const { hashRaw } = sign_tools.creatEdDSASigHasH({\n      method: loopring_defs.ReqMethod.POST,\n      basePath: this.baseUrl,\n      api_url: loopring_defs.LOOPRING_URLs.REJECT_APPROVE_SIGNATURE,\n      requestInfo: dataToSig,\n    })\n    myLog('signHash', hashRaw)\n    const result: any = await personalSign(\n      web3,\n      address,\n      '',\n      toHex(hashRaw),\n      loopring_defs.ConnectorNames.Unknown,\n      chainId,\n    )\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.REJECT_APPROVE_SIGNATURE,\n      queryParams: {},\n      method: loopring_defs.ReqMethod.POST,\n      bodyParams: request,\n      apiKey: '',\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      sigObj: {\n        sig: result?.sig.slice(0, 132),\n      },\n    }\n\n    let hash: string | undefined = undefined\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      hash = raw_data.data\n    }\n    return {\n      hash,\n      raw_data,\n    }\n  }\n\n  public async submitApproveSignature<T extends loopring_defs.TX_HASH_API>(\n    req: loopring_defs.SubmitApproveSignatureRequestWithPatch,\n    guardians: string[] = [],\n    isContract1XAddress?: boolean,\n    masterCopy?: string,\n    forwarderModuleAddress: string = '',\n  ): Promise<loopring_defs.TX_HASH_RESULT<T> | loopring_defs.RESULT_INFO> {\n    const {\n      request,\n      web3,\n      chainId,\n      // walletType,\n      guardian,\n      apiKey,\n      isHWAddr: isHWAddrOld,\n    } = req\n    const isHWAddr = !!isHWAddrOld\n    const {\n      signature: ecdsaSignature\n    } = await signHebaoApproveWrap({\n      chainId,\n      web3,\n      owner: request.signer,\n      isHWAddr,\n      wallet: guardian.signedRequest.wallet,\n      validUntil: guardian.signedRequest.validUntil,\n      messageData: guardian?.businessDataJson?.value?.value ?? {},\n      masterCopy: isContract1XAddress ? undefined : masterCopy,\n      forwarderModuleAddress,\n      type: guardian.type,\n      guardian,\n      walletVersion: isContract1XAddress ? 1 : 2,\n    })\n    request.signature = ecdsaSignature?.toString()\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.SUBMIT_APPROVE_SIGNATURE,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    let raw_data\n    try {\n      raw_data = (await this.makeReq().request(reqParams)).data\n    } catch (error) {\n      throw error as AxiosResponse\n    }\n    return this.returnTxHash(raw_data) as loopring_defs.TX_HASH_RESULT<T>\n  }\n\n  public async getAddressByENS<R extends any, T extends string>(\n    request: loopring_defs.GetEnsAddressRequest,\n  ): Promise<{\n    address: string | undefined\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.RESOLVE_ENS,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let address: T | undefined\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      address = raw_data.data as T\n    }\n    return {\n      address,\n      raw_data,\n    }\n  }\n\n  public async getWalletType<T extends any>(\n    request: loopring_defs.GET_WALLET_TYPE,\n  ): Promise<{\n    walletType: loopring_defs.WalletType | undefined\n    raw_data: T\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_WALLET_TYPE,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let walletType: loopring_defs.WalletType | undefined\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      walletType = raw_data.data\n    }\n    return {\n      walletType,\n      raw_data,\n    }\n  }\n\n  public async getContractType<T = loopring_defs.ContractType>(\n    request: loopring_defs.GET_WALLET_TYPE,\n  ): Promise<{\n    contractType: T | undefined\n    raw_data: T\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_WALLET_CONTRACTVERSION,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    let contractType: T | undefined\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      contractType = raw_data.data[0]\n    }\n    return {\n      contractType,\n      raw_data,\n    }\n  }\n\n  public async getWalletModules<T = loopring_defs.ModuleType>(\n    request: loopring_defs.GET_WALLET_TYPE,\n  ): Promise<{\n    walletModule: T | undefined\n    raw_data: T\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_WALLET_MODULES,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    let walletModule: T | undefined\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      walletModule = raw_data.data[0]\n    }\n    return {\n      walletModule,\n      raw_data,\n    }\n  }\n\n  public async getEnsByAddress<R extends any, T extends string>(\n    request: loopring_defs.GetEnsNameRequest,\n  ): Promise<{\n    ensName: string | undefined\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.RESOLVE_NAME,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let ensName: T | undefined\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      ensName = raw_data.data as T\n    }\n    return {\n      ensName,\n      raw_data,\n    }\n  }\n\n  public async lockHebaoWallet({\n    web3,\n    from,\n    contractAddress,\n    gasPrice,\n    gasLimit = '0x' + Number(150000).toString(16),\n    chainId = 1,\n    wallet,\n    nonce,\n    isVersion1,\n  }: // sendByMetaMask = true,\n  loopring_defs.LockHebaoHebaoParam) {\n    if (isVersion1) {\n      const data = abi.Contracts.HeBao.encodeInputs('lock', {\n        wallet,\n      })\n\n      return await sendRawTx(\n        web3,\n        from,\n        contractAddress,\n        0,\n        data,\n        chainId as loopring_defs.ChainId,\n        nonce,\n        gasPrice,\n        gasLimit,\n        true,\n      )\n    } else {\n      return await sendRawTx(\n        web3,\n        from,\n        contractAddress,\n        0,\n        '0xf83d08ba',\n        chainId as loopring_defs.ChainId,\n        nonce,\n        gasPrice,\n        gasLimit,\n        true,\n      )\n    }\n  }\n\n  public async getHebaoConfig(request: { network?: loopring_defs.NetworkWallet }) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_HEBAO_CONFIG,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data: raw_data.data }\n  }\n\n  public async sendMetaTx<R extends any, T extends any>(\n    request: loopring_defs.SendMetaTxRequest,\n    apiKey: string,\n  ): Promise<{\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.SEND_META_TX,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n      bodyParams: request,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return { raw_data }\n  }\n\n  public async getGuardianApproveList<R extends any, T extends loopring_defs.Guardian>(\n    request: loopring_defs.GetGuardianApproveListRequest,\n  ): Promise<{\n    guardiansArray: Array<T>\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_GUARDIAN_APPROVE_LIST,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let guardiansArray: Array<T> = []\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      guardiansArray =\n        raw_data?.data?.guardians?.map((r: any) => ({\n          ens: r.ens ? r.ens : '',\n          address: r.wallet,\n          type: loopring_defs.HEBAO_META_TYPE[r.metaTxType],\n          id: r.approveId,\n          messageHash: r.txAwareHash,\n          businessDataJson: r.businessDataJson,\n          signedRequest: r.signedRequest,\n          ...r,\n        })) ?? []\n    }\n    return {\n      guardiansArray,\n      raw_data,\n    }\n  }\n\n  // /api/appWallet/v3/operationLogs?from=0x189a3c44a39c5ab22712543c0f62a9833bbe8df9&fromTime=0&to=&offset=0&network=ETHEREUM&statues=&hebaoTxType=&limit=20\n\n  /**\n   * getProtectors\n   * @param {GetUserTradesRequest} request\n   * @param apiKey\n   */\n  public async getProtectors<R extends any, T extends loopring_defs.Protector>(\n    request: loopring_defs.GetProtectorRequest,\n    apiKey: string,\n  ): Promise<{\n    protectorArray: Array<T>\n\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_PROTECTORS,\n      apiKey: apiKey,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    let protectorArray: Array<T> = []\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    } else {\n      protectorArray =\n        raw_data?.data?.map((p: any) => ({\n          ens: p.protectEns,\n          address: p.protectAddress,\n          lockStatus: p.walletStatus?.toUpperCase(),\n        })) ?? []\n    }\n    return {\n      protectorArray,\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user trade amount\n   */\n  public async getHebaoOperationLogs<R extends any, T extends loopring_defs.HebaoOperationLog>(\n    request: loopring_defs.HebaoOperationLogs,\n  ): Promise<{\n    operationArray: Array<T>\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_OPERATION_LOGS,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      operationArray: raw_data?.data ?? ([] as T[]),\n      raw_data,\n    }\n  }\n\n  /*\n   * Get user trade amount\n   */\n  public async getUserTradeAmount(request: loopring_defs.GetUserTradeAmount) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_USER_TRADE_AMOUNT,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  /*\n   * Get token prices\n   * e.g. http://api3.loopring.io/api/wallet/v3/tokenPrices?token=0xdac17f958d2ee523a2206206994597c13d831ec7&intervalType=1&limit=30&currency=CNY\n   */\n  public async getTokenPrices(request: loopring_defs.GetTokenPricesRequest) {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_TOKEN_PRICES,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const priceSeries: string[] = []\n    const timestampSeries: number[] = []\n\n    if (raw_data?.data instanceof Array) {\n      raw_data.data.forEach((item: loopring_defs.TokenPriceInfo) => {\n        priceSeries.push(item.price)\n        timestampSeries.push(item.createdAt)\n      })\n    }\n\n    return {\n      tokenPrices: raw_data.data as loopring_defs.TokenPriceInfo[],\n      priceSeries,\n      timestampSeries,\n      raw_data,\n    }\n  }\n\n  /*\n   * Fetches, for all the tokens supported by Loopring, their fiat price.\n   * response: { [key: string]: <price> }  key is token address\n   */\n  public async getLatestTokenPrices(request?: loopring_defs.getLatestTokenPricesRequest) {\n    const reqParams: loopring_defs.ReqParams = {\n      queryParams: request,\n      url: loopring_defs.LOOPRING_URLs.GET_LATEST_TOKEN_PRICES,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const tokenPrices: loopring_defs.LoopringMap<number> = {}\n\n    if (raw_data?.data instanceof Array) {\n      raw_data.data.forEach((item: any) => {\n        tokenPrices[item.token.toLowerCase()] = parseFloat(item.price)\n      })\n    }\n\n    return {\n      tokenPrices,\n      raw_data,\n    }\n  }\n  public async getAccountServices<R>(request: loopring_defs.GetAccountServicesRequest): Promise<{\n    register: any\n    order: any\n    joinAmm: any\n    dAppTrade: any\n    legal: any\n    raw_data: R\n  }> {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_ACCOUNT_SERVICES,\n      queryParams: request,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      ...raw_data,\n      register: raw_data?.register,\n      order: raw_data?.order,\n      joinAmm: raw_data?.joinAmm,\n      dAppTrade: raw_data?.dAppTrade,\n      legal: raw_data?.dAppTrade,\n      raw_data,\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/whitelisted_user_api.ts",
    "content": "import { BaseAPI } from './base_api'\n\nimport * as loopring_defs from '../defs'\n\nimport * as sign_tools from './sign/sign_tools'\n\nexport class WhitelistedUserAPI extends BaseAPI {\n  /*\n   * Submit offchain withdraw request\n   * not supported for now.\n   */\n  private async submitOffchainWithdraw(\n    request: loopring_defs.OffChainWithdrawalRequestV3,\n    eddsaKey: string,\n    apiKey: string,\n  ) {\n    request.eddsaSignature = sign_tools.get_EddsaSig_OffChainWithdraw(request, eddsaKey).result\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.WITHDRAWALS_ACTION,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n\n  /*\n   * Submit offchain withdraw request\n   */\n  public async submitInternalTransfer(\n    request: loopring_defs.OriginTransferRequestV3,\n    eddsaKey: string,\n    apiKey: string,\n  ) {\n    request.eddsaSignature = sign_tools.get_EddsaSig_Transfer(request, eddsaKey).result\n\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.POST_INTERNAL_TRANSFER,\n      bodyParams: request,\n      apiKey,\n      method: loopring_defs.ReqMethod.POST,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo && raw_data?.resultInfo.code) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    return {\n      raw_data,\n    }\n  }\n}\n"
  },
  {
    "path": "src/api/ws_api.ts",
    "content": "import { BaseAPI } from './base_api'\n\nimport * as loopring_defs from '../defs'\n\nexport class WsAPI extends BaseAPI {\n  /*\n   * Get wsApiKey by access REST path \"/v3/ws/key\"\n   */\n  public async getWsKey() {\n    const reqParams: loopring_defs.ReqParams = {\n      url: loopring_defs.LOOPRING_URLs.GET_WS_KEY,\n      method: loopring_defs.ReqMethod.GET,\n      sigFlag: loopring_defs.SIG_FLAG.NO_SIG,\n    }\n\n    const raw_data = (await this.makeReq().request(reqParams)).data\n    if (raw_data?.resultInfo) {\n      return {\n        ...raw_data?.resultInfo,\n      }\n    }\n    const wsKey = raw_data.key\n    return {\n      wsKey,\n      raw_data,\n    }\n  }\n}\n"
  },
  {
    "path": "src/defs/account_defs.ts",
    "content": "import { PublicKey } from './loopring_enums'\n\n/**\n * AccountInfo\n * @property accountId number Account ID\n * @property owner string  Ethereum address\n * @property frozen boolean The frozen state of the account, true stands for frozen, if the account is frozen, the user cant submit order.\n * @property publicKey PublicKey The user's public key\n * @property tags? string Comma separated list of tags such as VIP levels, etc\n * @property nonce number field.DexAccountV3.nonce\n * @property keyNonce number Nonce of users key change request, for backward compatible\n * @property keySeed string KeySeed of users L2 eddsaKey, the L2 key should be generated from this seed, i.e., L2_EDDSA_KEY=eth.sign(keySeed). Otherwise, user may meet error in login loopring DEX\n */\nexport interface AccountInfo {\n  accountId: number\n  owner: string\n  frozen: boolean\n  publicKey: PublicKey\n  tags?: string\n  nonce: number\n  keyNonce: number\n  keySeed: string\n}\n\n/**\n *\n */\nexport interface CounterFactualInfo {\n  accountId: number\n  owner: string\n  walletFactory: string\n  walletSalt: string\n  walletOwner: string\n}\n\nexport interface NFTCounterFactualInfo {\n  nftFactory: string\n  nftOwner: string\n  nftBaseUri: string\n}\n"
  },
  {
    "path": "src/defs/error_codes.ts",
    "content": "import { AxiosResponse } from \"axios\";\n\nexport enum LoopringErrorCode {\n  Unknown_Error = 100000,\n  Invalid_Args = 100001,\n\n  Address_Not_Found = 101001,\n  User_Not_Found = 101002,\n\n  ExchangeId_Incorrect = 102001,\n  Unsupported_TokenId = 102002,\n  Invalid_AccountId = 102003, //dup\n  Invalid_OrderId = 102004,\n  Market_Not_Supported = 102005, //dup\n  Illegal_Rate = 102006,\n  Order_Already_Existed = 102007,\n  Order_Already_Expired = 102008,\n  Order_Missing_Sig = 102010,\n  Invalid_User_Balance = 102011,\n  Order_Amount_Too_Small = 102012,\n  Failed_To_Freeze_Amt = 102014,\n  Exceed_Max_Order_Amt = 102020,\n  Invalid_Nonce = 102021,\n  Invalid_Transfer_Sender = 102022,\n  Invalid_Transfer_Receiver = 102023,\n  Unsuported_Fee_Token = 102024,\n  Transfer_Token_Is_Not_Consistent_With_Fee_Token = 102025,\n\n  Sumbit_Order_Failed = 102027,\n  No_Order_To_Cancel = 102117,\n  Fail_To_Cancel_Order = 102118,\n  Order_Is_Not_Valid = 102120,\n\n  Empty_Apikey = 104001,\n  Invalid_Apikey = 104002,\n  Invalid_AccountID = 104003, //dup\n  No_Sig_Provided = 104004,\n  Wrong_Sig = 104005,\n\n  User_Cannot_Be_Empty = 107001,\n  Orderhash_Cannot_Be_Empty = 107002,\n  Order_Not_Exist = 107003,\n\n  Unsupported_Market = 108000, //dup\n  Unsupported_Depth_Level = 108001,\n  SKD_UNKNOW = 500000,\n  CONTRACTNFT_URI = 500001,\n  CONTRACTNFT_BALANCE = 500002,\n  CONTRACTNFT_IS_APPROVE = 500003,\n  CONTRACTNFT_SET_APPROVE = 500004,\n  NOT_SUPPORT_ERROR = 500005,\n  USER_DENIED = 500006,\n  USER_DENIED_2 = 500007,\n  NO_EDDSA_KEY = 500008,\n  HTTP_ERROR = 500009,\n  BTRADE_NO_DEPTH_ERROR = 500010,\n  BTRADE_NO_PRODUCT = 500011,\n}\n\nexport enum ConnectorError {\n  NOT_SUPPORT_ERROR = \"Not supported on this device\",\n  USER_DENIED = \"User denied message signature\",\n  USER_DENIED_2 = \"personalSign err before Validate\",\n  CONTRACTNFT_URI = \"contract nft uri Error\",\n  CONTRACTNFT_BALANCE = \"contract nft balance error\",\n  CONTRACTNFT_IS_APPROVE = \"ContractNFT is Approve error\",\n  CONTRACTNFT_SET_APPROVE = \"ContractNFT set Approve error\",\n  NO_EDDSA_KEY = \"No EDDSA KEY\",\n  HTTP_ERROR = \"HTTP Request Failed!\",\n  BTRADE_NO_DEPTH_ERROR = \"NO Depth for BTRADE\",\n  BTRADE_NO_PRODUCT = \"NO Market for BTRADE\",\n}\n\nexport interface RESULT_INFO {\n  code?: number;\n  msg?: string;\n  message?: string;\n}\nexport type ERROR_INFO = {\n  resultInfo: RESULT_INFO;\n};\n\nexport const checkErrorInfo = (\n  errorInfo: RESULT_INFO,\n  isFirstTime?: boolean\n) => {\n  const message = errorInfo.message;\n  if (isFirstTime && message === \"NOT_SUPPORT_ERROR\") {\n    return ConnectorError.NOT_SUPPORT_ERROR;\n  } else if (message === \"USER_DENIED\" || message === \"USER_DENIED_2\") {\n    return ConnectorError.USER_DENIED;\n  } else if (\n    message &&\n    (message.startsWith(\"personalSign last\") ||\n      message.indexOf(\"User denied transaction\") > 0)\n  ) {\n    return ConnectorError.USER_DENIED;\n  }\n  return message;\n};\n"
  },
  {
    "path": "src/defs/index.ts",
    "content": "import { getNavigatorSafely, getWindowSafely } from 'utils/window_utils'\n\nexport * from './loopring_enums'\nexport * from './url_defs'\nexport * from './account_defs'\nexport * from './web3_defs'\nexport * from './ws_defs'\nexport * from './loopring_constants'\nexport * from './loopring_defs'\nexport * from './error_codes'\nexport * from './nft_defs'\n\nexport const IsMobile = {\n  Android: function () {\n    return getNavigatorSafely()?.userAgent.match(/Android/i)\n  },\n  BlackBerry: function () {\n    return getNavigatorSafely()?.userAgent.match(/BlackBerry/i)\n  },\n  iOS: function () {\n    return getNavigatorSafely()?.userAgent.match(/iPhone|iPad|iPod/i)\n  },\n  Opera: function () {\n    return getNavigatorSafely()?.userAgent.match(/Opera Mini/i)\n  },\n  Windows: function () {\n    return getNavigatorSafely()?.userAgent.match(/IEMobile/i) || getNavigatorSafely()?.userAgent.match(/WPDesktop/i)\n  },\n  Ethereum: function () {\n    return getWindowSafely()?.ethereum && getWindowSafely()?.ethereum.isImToken\n  },\n\n  any: function () {\n    if (typeof global.navigator === 'undefined' || typeof navigator === 'undefined') {\n      console.log('IsMobile any navigator is undefined')\n      return false\n    }\n    return (\n      IsMobile.Android() ||\n      IsMobile.BlackBerry() ||\n      IsMobile.iOS() ||\n      IsMobile.Opera() ||\n      IsMobile.Windows() ||\n      IsMobile.Ethereum()\n    )\n  },\n}\n\ntype Ethereum = any\ndeclare global {\n  interface Window {\n    ethereum?: Ethereum & { [key: string]: boolean; isLoopring: boolean }\n\n    // socketEventMap: {[key:string]:any\n    // imageConfig:{[key:string]:any}|undefined\n  }\n  interface Global {\n    ethereum?: Ethereum & { [key: string]: boolean; isLoopring: boolean }\n  }\n}\n"
  },
  {
    "path": "src/defs/loopring_constants.ts",
    "content": "export enum HEBAO_LOCK_STATUS {\n  LOCK_FAILED = 'LOCK_FAILED',\n  CREATED = 'CREATED',\n  LOCK_WAITING = 'LOCK_WAITING',\n  UNLOCK_FAILED = 'UNLOCK_FAILED',\n  LOCKED = 'LOCKED',\n  UNLOCK_WAITING = 'UNLOCK_WAITING',\n}\n\nexport enum HEBAO_META_TYPE {\n  recovery = 16,\n  transfer = 18,\n  // add_guardian = 34,\n  approve_token = 23,\n  remove_guardian = 35,\n  unlock_wallet = 37,\n  upgrade_contract = 201,\n  deposit_wallet = 202,\n}\n\nexport const SoursURL = 'https://static.loopring.io/assets/'\n"
  },
  {
    "path": "src/defs/loopring_defs.ts",
    "content": "import { ChainId, ConnectorNames } from './web3_defs'\n\nimport Web3 from 'web3'\n\nimport {\n  AmmPoolActivityStatus,\n  AmmTxType,\n  AssetType,\n  BillType,\n  Currency,\n  IntervalType,\n  MarketStatus,\n  NetworkWallet,\n  OffchainFeeReqType,\n  OffchainNFTFeeReqType,\n  OrderStatus,\n  OrderType,\n  OrderTypeResp,\n  PublicKey,\n  ReqMethod,\n  RuleType,\n  Side,\n  SIG_FLAG,\n  TradeChannel,\n  TradingInterval,\n  TransferType,\n  TxStatus,\n  TxType,\n  UserBillTypes,\n  UserNFTTxTypes,\n  UserTxTypes,\n  WithdrawalTypes,\n} from './loopring_enums'\nimport { RESULT_INFO } from './error_codes'\nimport { HEBAO_LOCK_STATUS, HEBAO_META_TYPE } from './loopring_constants'\nimport { CounterFactualInfo, NFTCounterFactualInfo } from './account_defs'\nimport { NFTType } from '../api'\n\nexport type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never }\nexport type XOR<T, U> = T | U extends { [key: string]: any }\n  ? (Without<T, U> & U) | (Without<U, T> & T)\n  : T | U\n\nexport interface VipFeeRateInfo {\n  symbol: string\n  makerRate: number\n  takerRate: number\n}\n\nexport type VipFeeRateInfoMap = { [key: string]: VipFeeRateInfo }\n\nexport type TX_HASH_RESULT<T> = T & { raw_data: T }\n\nexport interface LoopringMap<T> {\n  [key: string]: T\n}\n\nexport interface ExchangeInfo {\n  ammExitFees: Array<any>[]\n  chainId: number\n  depositAddress: string\n  exchangeAddress: string\n  fastWithdrawalFees: Array<any>[]\n  onchainFees: Array<any>[]\n  openAccountFees: Array<any>[]\n  transferFees: Array<any>[]\n  updateFees: Array<any>[]\n  withdrawalFees: Array<any>[]\n}\n\nexport interface TickerData {\n  symbol: string\n  base: string | undefined\n  quote: string | undefined\n  timestamp: number\n  base_token_volume: string\n  quote_token_volume: string\n  base_fee_amt: string\n  quote_fee_amt: string\n  open: number\n  high: number\n  low: number\n  close: number\n  count: number\n  bid: number\n  ask: number\n  change?: number\n}\n\nexport interface ABInfo {\n  price: number\n  amt: string\n  vol: string\n  amtTotal: string\n  volTotal: string\n}\n\nexport interface DepthData {\n  symbol: string\n\n  version: number\n  timestamp: number\n\n  mid_price: number\n\n  bids: ABInfo[]\n  bids_prices: number[]\n  bids_amtTotals: string[]\n  bids_volTotals: string[]\n  bids_amtTotal: string\n  bids_volTotal: string\n\n  asks: ABInfo[]\n  asks_prices: number[]\n  asks_amtTotals: string[]\n  asks_volTotals: string[]\n  asks_amtTotal: string\n  asks_volTotal: string\n}\n\nexport interface Candlestick {\n  timestamp: number\n  txs: number\n  open: number\n  close: number\n  high: number\n  low: number\n  baseVol: string\n  quoteVol: string\n}\n\nexport interface TradesData {\n  totalNum: number\n  trades: any[][]\n}\n\nexport interface OrdersData {\n  totalNum: number\n  trades: any[][]\n}\n\nexport interface QuotesData {\n  quotes: any[][]\n}\n\nexport interface TokenInfo {\n  type: string\n  tokenId: number\n  symbol: string\n  name: string\n  address: string\n  decimals: number\n  precision: number\n  precisionForOrder: number\n  orderAmounts: {\n    minimum: string\n    maximum: string\n    dust: string\n  }\n  luckyTokenAmounts: {\n    minimum: string\n    maximum: string\n    dust: string\n  }\n  fastWithdrawLimit: string\n  gasAmounts: {\n    distribution: string\n    deposit: string\n  }\n  enabled: boolean\n\n  isLpToken: boolean\n}\n\nexport interface AmmPoolStat {\n  market: string\n  liquidity: string[]\n  lpLiquidity: string\n  liquidityUSD: string\n  ohlc: string[]\n  volume: string[]\n  fees: string[]\n  apyBips: string\n  isRecommended: boolean\n  rewards: TokenVolumeV3[]\n}\n\nexport interface AmmPoolActivityRule {\n  market: string\n  ruleType: RuleType\n  rangeFrom: number\n  rangeTo: number\n  awardRules: TokenVolumeV3[]\n  maxSpread: number\n  topK: number\n\n  status: AmmPoolActivityStatus\n}\n\nexport interface AmmPoolInProgressActivityRule {\n  market: string\n  ruleType: RuleType[]\n  rangeFrom: number\n  rangeTo: number\n  awardRules: TokenVolumeV3[]\n  maxSpread: number\n  topK: number\n\n  status: AmmPoolActivityStatus\n}\n\nexport interface AmmTrade {\n  accountId: number\n  orderHash: string\n  market: string\n  side: string\n  size: string\n  price: number\n  feeAmount: string\n  createdAt: number\n}\n\nexport interface AmmPoolInfoV3 {\n  name: string\n  market: string\n  address: string\n  version: string\n  tokens: {\n    pooled: string[]\n    lp: number\n  }\n  feeBips: number\n  precisions: {\n    price: number\n    amount: number\n  }\n  createdAt: string\n  status: number\n  domainSeparator: string\n}\n\nexport interface TokenRelatedInfo {\n  tokenId: string\n  tokenList: string[]\n}\n\nexport interface AmmPoolConfResponse {\n  ammpools: LoopringMap<AmmPoolInfoV3>\n  pairs: LoopringMap<TokenRelatedInfo>\n  raw_data: any\n}\n\nexport interface PooledMap {\n  [key: number]: TokenVolumeV3\n}\n\nexport interface AmmPoolBalance {\n  poolName: string\n  poolAddress: string\n  pooled: [TokenVolumeV3, TokenVolumeV3]\n  lp: any\n  risky: boolean\n  pooledMap: PooledMap\n}\n\nexport interface AmmPoolBalancesResponse {\n  ammpoolsbalances: LoopringMap<FiatPriceInfo>\n  raw_data: any\n}\n\nexport interface TokensResponse {\n  tokenSymbolMap: LoopringMap<TokenInfo>\n  tokenIdMap: LoopringMap<TokenInfo>\n  tokenAddressMap: LoopringMap<TokenInfo>\n\n  getTokenInfoBySymbol: any\n  getTokenInfoById: any\n\n  tokenSymbolArr: string[]\n  tokenSymbolArrStr: string\n  tokenIdArr: string[]\n  tokenIdArrStr: string\n  tokenAddressArr: string[]\n  tokenAddressArrStr: string\n\n  raw_data: any\n}\n\nexport interface MarketInfo {\n  baseTokenId: number\n  enabled: boolean\n  market: string\n  orderbookAggLevels: number\n  precisionForPrice: number\n  quoteTokenId: number\n  status?: MarketStatus\n  isSwapEnabled?: boolean\n  createdAt?: number\n}\n\nexport enum DefiMarketStatus {\n  hide = 0,\n  show = 1,\n  depositOnly = 3,\n  depositAll = 7,\n  withdrawOnly = 9,\n  depositAllAndWithdraw = 15,\n  withdrawAll = 25,\n  WithdrawAllAndDeposit = 27,\n  depositAndWithdraw = 11,\n  all = 31,\n}\n\nexport interface DefiMarketInfo {\n  type: string\n  market: string\n  apy: string\n  baseTokenId: number\n  quoteTokenId: number\n  precisionForPrice: number\n  orderbookAggLevels: number\n  enabled: boolean\n  currency: string\n  status: DefiMarketStatus\n  accountId: number\n  address: string\n  depositFeeBips: number\n  withdrawFeeBips: number\n  depositPrice: string\n  withdrawPrice: string\n  baseVolume: string\n  quoteVolume: string\n  quoteLimitAmount: string\n  baseLimitAmount: string\n  quoteAlias: string\n  stepLength: string\n  extra: {\n    depositFeeBips: number\n    withdrawFeeBips: number\n    orderbookAggLevels: number\n    isLeverage: number\n    baseAssetSymbol: string\n    quoteAssetSymbol: string\n  }\n}\n\nexport interface MarketsResponse {\n  hasMarket: any\n  getExistedMarket: any\n  markets: LoopringMap<MarketInfo>\n  pairs: LoopringMap<TokenRelatedInfo>\n  tokenArr: string[]\n  tokenArrStr: string\n  marketArr: string[]\n  marketArrStr: string\n  raw_data: any\n}\n\nexport interface TokenVolumeV3 {\n  /**\n   * The Loopring\\'s token identifier.\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  tokenId: string | number\n  /**\n   * The volume of the token\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  volume: string\n}\n\nexport interface TokenVolumeV5 {\n  /**\n   * The Loopring\\'s token identifier.\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  tokenId: string | number\n  /**\n   * The volume of the token\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  amount: string\n}\n\nexport interface TokenVolumeNFT {\n  /**\n   * The Loopring\\'s token identifier.\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  tokenId: string | number\n  /**\n   * The amount of the token\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  amount: string\n  /**\n   * The Loopring's NFTAction token data identifier which is a hash string of NFTAction token address and NFT_ID\n   * @type {string}\n   * @memberof The Loopring's NFTAction token data identifier which is a hash string of NFTAction token address and NFT_ID\n   */\n  nftData: NftData\n}\n\nexport interface AmmPoolJoinTokens {\n  pooled: TokenVolumeV3[]\n  minimumLp: TokenVolumeV3\n}\n\nexport interface AmmPoolExitTokens {\n  unPooled: TokenVolumeV3[]\n  burned: TokenVolumeV3\n}\n\nexport interface GameRankInfo {\n  address: string\n  volume: string\n  rank: number\n  rewards: TokenVolumeV3[]\n}\n\nexport interface SetReferrerRequest {\n  address: string\n  referrer?: number\n  promotionCode?: string\n  publicKeyX: string\n  publicKeyY: string\n}\n\nexport interface GetAmmUserRewardsRequest {\n  owner: number // accountId\n  ammPoolMarkets?: string // pool-name list\n}\n\nexport interface AmmUserReward {\n  market: string\n  feeRewards: string[]\n  extraRewards: TokenVolumeV3[]\n  currentRewards: TokenVolumeV3[]\n}\n\nexport interface AmmUserRewardMap {\n  [key: string]: {\n    current?: AmmUserReward\n    lastDay?: AmmUserReward\n  }\n}\n\nexport interface GetAmmPoolGameRankRequest {\n  ammPoolMarket: string // symbol AMM-LRC-ETH\n}\n\nexport interface GetAmmAssetRequest {\n  poolAddress: string\n  limit?: number\n}\n\nexport interface GetAmmPoolGameUserRankRequest {\n  owner: string // address\n  ammPoolMarket: string // symbol AMM-LRC-ETH\n}\n\nexport interface GetAmmPoolSnapshotRequest {\n  poolAddress: string\n}\n\nexport interface AmmPoolSnapshot {\n  poolName: string\n  poolAddress: string\n  pooled: [TokenVolumeV3, TokenVolumeV3]\n  lp: TokenVolumeV3\n  risky: boolean\n}\n\nexport interface AmmPoolRequestPatch {\n  chainId: ChainId\n  ammName: string\n  poolAddress: string\n  eddsaKey: string\n}\n\nexport interface JoinAmmPoolRequest {\n  owner: string\n  poolAddress: string\n  joinTokens: AmmPoolJoinTokens\n  storageIds: number[]\n  fee: string\n  validUntil?: number\n  eddsaSignature?: string\n  ecdsaSignature?: string\n  domainSeparator?: string\n}\n\nexport interface JoinAmmPoolResult {\n  hash: string\n  status: TxStatus\n  isIdempotent: boolean\n}\n\nexport interface ExitAmmPoolRequest {\n  owner: string\n  poolAddress: string\n  exitTokens: AmmPoolExitTokens\n  storageId: number\n  maxFee: string\n  validUntil?: number\n  eddsaSignature?: string\n  ecdsaSignature?: string\n  domainSeparator?: string\n}\n\nexport interface ExitAmmPoolResult {\n  hash: string\n  status: TxStatus\n  isIdempotent: boolean\n}\n\nexport interface GetAmmPoolTradesRequest {\n  ammPoolAddress: string\n  limit?: number\n  offset?: number\n}\n\nexport interface AmmPoolTrade {\n  accountId: number\n  orderHash: string\n  market: string\n  side: Side\n  size: string\n  price: number\n  feeAmount: string\n  createdAt: number\n}\n\nexport interface GetAmmPoolTxsRequest {\n  poolAddress: string\n  billType?: BillType\n  start?: number\n  end?: number\n  limit?: number\n  offset?: number\n  tokenId?: number\n  income?: boolean\n  transferAddress?: string\n  fromAddress?: string\n}\n\nexport interface AmmPoolTxOld {\n  id: number\n  from: string\n  to: string\n  token: string\n  amount: string\n  tokenF: string\n  amountF: string\n  status: TxStatus\n  txHash: string\n  billType: BillType\n  income: boolean\n  timestamp: number\n  memo: string\n  price: string\n  transferType: TransferType\n  label: string\n}\n\nexport interface TokenVolumeV4 {\n  tokenId: number\n  amount: string\n  actualAmount: string\n  feeAmount: string\n}\n\nexport interface AmmPoolTx {\n  hash: string\n  txType: AmmTxType\n  txStatus: TxStatus\n  ammPoolAddress: string\n  ammLayerType: string\n  poolTokens: [TokenVolumeV4, TokenVolumeV4]\n  lpToken: TokenVolumeV4\n  createdAt: number\n  updatedAt: number\n}\n\nexport enum AMMtxTypes {\n  JOIN = 0,\n  EXIT = 1,\n}\n\nexport interface GetUserAmmPoolTxsRequest {\n  accountId: number\n  start?: number\n  end?: number\n  limit?: number\n  offset?: number\n  txTypes?: AMMtxTypes // combine of AmmTxType\n  txStatus?: TxStatus\n  ammPoolAddress?: string\n}\n\nexport interface PooledToken {\n  tokenId: number\n  amount: string\n  actualAmount: string\n  feeAmount: string\n}\n\nexport interface UserAmmPoolTx {\n  hash: string\n  txType: AmmTxType\n  txStatus: TxStatus\n  ammPoolAddress: string\n  ammLayerType: string\n  poolTokens: [PooledToken, PooledToken]\n  lpToken: PooledToken\n  createdAt: number\n  updatedAt: number\n}\n\nexport interface GetLiquidityMiningRequest {\n  accountId: number\n  market: string\n  size: number\n}\n\nexport interface RewardItem {\n  startAt: number\n  timeInterval: string\n  accountId: number\n  tokenId: number\n  market: string\n  score: number\n  amount: string\n}\n\nexport interface GetLiquidityMiningUserHistoryRequest {\n  accountId: number\n  start?: number\n  end?: number\n}\n\nexport interface UserMiningInfo {\n  account_id: number\n  market: string\n  start: number\n  end: number\n  awards: TokenVolumeV3[]\n}\n\nexport interface GetFiatPriceRequest {\n  legal: string\n}\n\nexport interface FiatPriceInfo {\n  symbol: string\n  price: number\n  updatedAt: number\n}\n\nexport interface GetMarketTradesRequest {\n  market: string\n  limit?: number\n}\n\nexport enum OrderMakerType {\n  taker = 'taker',\n  maker = 'maker',\n}\n\nexport interface MarketTradeInfo {\n  tradeTime: number\n  tradeId: string\n  side: Side\n  volume: string\n  price: string\n  market: string\n  fee: string\n  type: OrderMakerType\n}\n\nexport interface GetWithdrawalAgentsRequest {\n  tokenId: number\n  amount: string\n}\n\nexport interface GetEthBalancesRequest {\n  owner: string\n}\n\nexport type TokenAddress = string\n\nexport interface GetTokenBalancesRequest {\n  owner: string\n  token: TokenAddress[]\n}\n\nexport interface GetALLTokenBalancesRequest {\n  owner: string\n}\n\nexport interface GetAllowancesRequest {\n  owner: string\n  token: TokenAddress[] // tokenAddress\n}\n\nexport interface GetDepthRequest {\n  market: string\n  level?: number\n  limit?: number\n}\n\nexport interface GetTickerRequest {\n  market: string\n}\n\nexport interface GetCandlestickRequest {\n  market: string\n  interval: TradingInterval\n  start?: number\n  end?: number\n  limit?: number\n}\n\nexport type GetAccountRequest =\n  | {\n      owner: string\n    }\n  | {\n      accountId: number\n    }\n\nexport interface GetCounterFactualInfoRequest {\n  accountId: number\n}\n\nexport interface GetAvailableBrokerRequest {\n  type: number\n}\n\nexport interface GetEthNonceRequest {\n  owner: string\n}\n\nexport interface GetUserApiKeyRequest {\n  accountId: number\n}\n\nexport interface UpdateUserApiKeyRequest {\n  accountId: number\n}\n\nexport type GetOffchainFeeAmtRequest =\n  | ({\n      accountId: number\n      amount?: string\n    } & {\n      requestType: Omit<\n        OffchainFeeReqType,\n        | OffchainFeeReqType.OFFCHAIN_WITHDRAWAL\n        | OffchainFeeReqType.AMM_JOIN\n        | OffchainFeeReqType.AMM_EXIT\n        | OffchainFeeReqType.ORDER\n        | OffchainFeeReqType.FAST_OFFCHAIN_WITHDRAWAL\n      >\n    })\n  | {\n      requestType:\n        | OffchainFeeReqType.OFFCHAIN_WITHDRAWAL\n        | OffchainFeeReqType.AMM_JOIN\n        | OffchainFeeReqType.AMM_EXIT\n        | OffchainFeeReqType.ORDER\n      tokenSymbol: string\n    }\n  | {\n      requestType: OffchainFeeReqType.DEFI_EXIT | OffchainFeeReqType.DEFI_JOIN\n      market: string\n    }\n  | {\n      requestType: OffchainFeeReqType.FAST_OFFCHAIN_WITHDRAWAL\n      tokenSymbol: string\n      amount: string\n    }\n  | {\n      requestType: OffchainFeeReqType.RABBIT_OFFCHAIN_WITHDRAWAL\n      tokenSymbol: string\n      amount: string\n    }\n  | { requestType: OffchainFeeReqType.EXTRA_TYPES; extraType: any }\n\n/**\n * @methodOf OffchainNFTFeeReqType.NFT_MINT\n * @requires  tokenAddress\n *\n * @methodOf {} OffchainNFTFeeReqType.NFT_WITHDRAWAL\n * @param deployInWithdraw\n */\nexport type GetNFTOffchainFeeAmtRequest = {\n  accountId: number\n  amount?: string\n} & XOR<\n  {\n    requestType: Omit<\n      OffchainNFTFeeReqType,\n      | OffchainNFTFeeReqType.NFT_MINT\n      | OffchainNFTFeeReqType.NFT_WITHDRAWAL\n      | OffchainNFTFeeReqType.EXTRA_TYPES\n    >\n  },\n  | {\n      requestType: OffchainNFTFeeReqType.NFT_MINT\n      tokenAddress: string\n    }\n  | {\n      requestType: OffchainNFTFeeReqType.NFT_WITHDRAWAL\n      tokenAddress: string\n      deployInWithdraw?: boolean\n    }\n  | { requestType: OffchainNFTFeeReqType.EXTRA_TYPES; extraType: any }\n>\n\nexport interface OrderInfo {\n  minAmount: string\n  makerRate: number\n  takerRate: number\n}\n\nexport interface TokenAmount {\n  tokenSymbol: string\n  discount: number\n  baseOrderInfo: OrderInfo\n  userOrderInfo: OrderInfo\n  tradeCost: string\n}\n\nexport interface GetMinimumTokenAmtRequest {\n  accountId: number\n  market: string\n}\n\nexport interface OffchainFeeInfo {\n  token: string\n  fee: string\n  discount: number\n}\n\nexport interface GetUserBalancesRequest {\n  accountId: number\n  tokens: string\n}\n\n// export interface GetUserBalancesRequest {\n// \taccountId: number;\n// \ttokens: string;\n// \t*accountId\t\t10106\n// \t*tokenId\t\t1\n// \t*status\t\t10106\n// \t*lockTag\t\tDUAL_CURRENCY,DUAL_BASE\n// \toffset\t\t3\n// \tlimit\n// \thash\n// \tdelegatorAccountId\n// \tstart\n// }\n\nexport interface UserBalanceInfo {\n  tokenId: number\n  total: string\n  locked: string\n  pending: {\n    withdraw: string\n    deposit: string\n  }\n}\n\nexport interface GetOrderDetailsRequest {\n  accountId: number\n  orderHash: string\n}\n\nexport interface OrderDetail {\n  hash: string\n  clientOrderId: string\n  side: Side\n  market: string\n  price: string\n  volumes: {\n    baseAmount: string\n    quoteAmount: string\n    baseFilled: string\n    quoteFilled: string\n    fee: string\n  }\n  validity: { start: number; end: number }\n  orderType: OrderTypeResp\n  tradeChannel: TradeChannel\n  status: OrderStatus\n  extraOrderType?: boolean\n  stopPrice?: string\n  stopSide: STOP_SIDE\n}\n\nexport interface GetUserOrderFeeRateRequest {\n  accountId: number\n  market: string\n  tokenB: number\n  amountB: string\n}\n\nexport interface FeeRateInfo {\n  symbol: string\n  makerRate: number\n  takerRate: number\n}\n\nexport interface GetUserFeeRateRequest {\n  accountId: number\n  markets: string\n}\n\nexport interface UserFeeRateInfo {\n  symbol: string\n  makerRate: number\n  takerRate: number\n}\n\nexport interface GetNextStorageIdRequest {\n  accountId: number\n  sellTokenId: number\n}\n\n/**\n *\n * @export\n * @interface OffChainWithdrawalRequestV3\n */\nexport interface OffChainWithdrawalRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  exchange: string\n  /**\n   * account ID\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  accountId: number\n  /**\n   * account owner address\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  owner: string\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  token: TokenVolumeV3\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  maxFee: TokenVolumeV3\n  /**\n   * offchain ID\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  storageId: number\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  validUntil: number\n  /**\n   * min gas for on-chain withdraw, Loopring exchange allocates gas for each distribution,\n   * but people can also assign this min gas,\n   * so Loopring has to allocate higher gas value for this specific distribution.\n   * Normally no need to take care of this value,\n   * 0 means let loopring choose the reasonable gas\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  minGas: number\n  /**\n   * withdraw to address\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  to: string\n  /**\n   * extra data for complex withdraw mode, normally none\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  extraData?: string\n  /**\n   * is fast withdraw mode\n   * @type {boolean}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  fastWithdrawalMode?: boolean\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was already submitted on eth mainnet\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  hashApproved?: string\n  counterFactualInfo?: CounterFactualInfo\n}\n\nexport enum EXTRA_ORDER_TYPES {\n  TRADITIONAL_ORDER = 'TRADITIONAL_ORDER',\n  STOP_LIMIT = 'STOP_LIMIT',\n  TRAILING_STOP = 'TRAILING_STOP',\n  OCO = 'OCO',\n}\n\nexport interface GetOrdersRequest {\n  accountId: number\n  market?: string\n  start?: number\n  end?: number\n  side?: Side[]\n  status?: string[]\n  tradeChannels?: string[]\n  limit?: number\n  offset?: number\n  orderTypes?: OrderType\n  extraOrderTypes?: string\n}\n\nexport interface GetUserRegTxsRequest {\n  accountId: number\n  start?: number\n  end?: number\n  status?: string\n  limit?: number\n  offset?: number\n}\n\nexport interface UserRegTx {\n  id: number\n  hash: string\n  owner: string\n  txHash: string\n  feeTokenSymbol: string\n  feeAmount: number\n  status: TxStatus\n  progress: string\n  timestamp: number\n  blockNum: number\n  updatedAt: number\n}\n\nexport interface GetUserPwdResetTxsRequest {\n  accountId: number\n  start?: number\n  end?: number\n  status?: string\n  limit?: number\n  offset?: number\n}\n\nexport type UserPwdResetTx = UserRegTx\n\nexport interface GetUserDepositHistoryRequest {\n  accountId?: number\n  hashes?: string\n  start?: number\n  end?: number\n  status?: string\n  limit?: number\n  tokenSymbol?: string\n  offset?: number\n}\n\nexport interface UserDepositHistoryTx {\n  id: number\n  hash: string\n  symbol: string\n  amount: string\n  txHash: string\n  status: TxStatus\n  progress: string\n  timestamp: number\n  blockNum: number\n  updatedAt: number\n}\n\nexport interface UserOnchainWithdrawalHistoryTx {\n  id: number\n  txType: WithdrawalTypes\n  hash: string\n  symbol: string\n  amount: string\n  txHash: string\n  feeTokenSymbol: string\n  feeAmount: string\n  status: TxStatus\n  progress: string\n  timestamp: number\n  blockNum: number\n  updatedAt: number\n  distributeHash: string\n  requestId: number\n  fastStatus: string\n}\n\nexport interface GetUserOnchainWithdrawalHistoryRequest {\n  accountId?: number\n  hashes?: string\n  start?: number\n  end?: number\n  status?: string\n  limit?: number\n  tokenSymbol?: string\n  offset?: number\n  withdrawalTypes?: string\n}\n\nexport interface GetUserTransferListRequest {\n  accountId?: number\n  hashes?: string\n  start?: number\n  end?: number\n  status?: string\n  limit?: number\n  tokenSymbol?: string\n  offset?: number\n  transferTypes?: string // transfer, transfer_red\n}\n\nexport interface UserTransferRecord {\n  id: number\n  hash: string\n  txType: TxType\n  symbol: string\n  amount: string\n  senderAddress: string\n  receiver: number\n  receiverAddress: string\n  feeTokenSymbol: string\n  feeAmount: string\n  status: TxStatus\n  progress: string\n  timestamp: number\n  updatedAt: number\n  memo: string\n}\n\nexport interface UserAssetInfo {\n  amount: string\n  createdAt: number\n  createdAtStr: string\n}\n\nexport interface GetUserAssetsRequest {\n  wallet: string\n  assetType?: AssetType\n  currency?: Currency\n  limit?: number\n  offset?: number\n  network?: NetworkWallet\n}\n\nexport interface GetUserTradeAmount {\n  accountId: number\n  markets?: string\n  limit?: number\n}\n\nexport interface TokenPriceInfo {\n  price: string\n  createdAt: number\n}\n\nexport interface GetTokenPricesRequest {\n  token: string\n  intervalType?: IntervalType\n  currency?: Currency\n  limit?: number\n  network?: NetworkWallet\n}\n\nexport interface getLatestTokenPricesRequest {\n  tokens?: string\n  currency?: string\n}\n\nexport interface GetUserTxsRequest {\n  accountId: number\n  tokenSymbol?: string\n  start?: number\n  end?: number\n  offset?: number\n  limit?: number\n  types?: UserTxTypes[] | string\n}\n\nexport interface GetUserBillsRequest {\n  accountId: number\n  fromAddress?: string\n  transferAddress?: string\n  start?: number\n  end?: number\n  offset?: number\n  limit?: number\n  billType?: UserBillTypes[]\n}\n\nexport interface GetReferSelf {\n  accountId: string\n  offset?: number\n  limit?: number\n  start?: number\n  end?: number\n}\n\nexport interface ReferSelf {\n  accountId: string\n  lrcAmount: string\n  startAt: number\n  endAt: number\n}\n\nexport enum GetReferStatisticReason {\n  Recommender = 9,\n  Invited = 1,\n}\n\nexport interface GetReferStatistic {\n  accountId: string\n  reason: GetReferStatisticReason\n}\n\nexport interface ReferStatistic {\n  accountId: number\n  totalProfit: string\n  claimableProfit: string\n  tradeNum: number\n  reason: string\n  createdAt: number\n  updatedAt: number\n  downsidesNum: number\n}\n\nexport interface GetReferDownsides {\n  accountId: string\n  offset?: number\n  limit?: number\n  start?: number\n  end?: number\n}\n\nexport interface ReferDownsides {\n  address: string\n  lrcAmount: string\n  startAt: number\n  endAt: number\n}\n\nexport enum REWARD_TYPE {\n  MakerRewards = 1,\n  ReferralRewards = 2,\n  RefereeRewards = 3,\n}\n\nexport interface GetUserRewardRequest {\n  rewardType: REWARD_TYPE\n  accountId: number\n  size?: number\n}\n\nexport interface GetUserNFTTxsRequest {\n  accountId: number\n  // tokenSymbol?: string;\n  metadata?: boolean\n  start?: number\n  end?: number\n  offset?: number\n  limit?: number\n  types?: UserNFTTxTypes[] | string\n}\n\nexport declare enum NFT_TRADE {\n  SELL = 'SELL',\n  BUY = 'BUY',\n}\n\nexport interface GetUserNFTTradeRequest {\n  accountId: number\n  nftData?: boolean\n  orderHash?: string\n  tradeHash?: string\n  start?: number\n  end?: number\n  side: NFT_TRADE\n  offset?: number\n  limit?: number\n  metadata?: boolean\n}\n\nexport interface UserTx {\n  id: number\n  txType: string\n  hash: string\n  symbol: string\n  amount: string\n  receiver: number\n  txHash: string\n  feeTokenSymbol: string\n  feeAmount: string\n  status: TxStatus\n  progress: string\n  timestamp: number\n  blockNum: number\n  updatedAt: number\n  distributeHash: string\n  receiverAddress: string\n  senderAddress: string\n  memo: string\n  requestId: number\n  fastStatus: string\n  recipient: string\n}\n\n/**\n * @param {string} guardian address\n */\nexport interface SendMetaTxRequest {\n  wallet: string\n  module: string\n  value: string\n  data: string\n  nonce: string\n  validUntil: string\n  gasToken: string\n  gasPrice: string\n  gasLimit: string\n  gasOverhead: string\n  feeRecipient: string\n  signatures: string\n  signers: string\n  metaTxType: 0\n  requestId: string\n  securityId: string\n  guardianType: string\n  network?: NetworkWallet\n}\n\n/**\n * @param {string} guardian address\n */\nexport interface GetGuardianApproveListRequest {\n  guardian: string\n  network?: NetworkWallet\n}\n\n/**\n * @param {string} owner address\n */\nexport interface GetEnsNameRequest {\n  owner: string\n  network?: NetworkWallet\n}\n\nexport interface GET_WALLET_TYPE {\n  wallet: string\n  network?: NetworkWallet\n}\n\n/**\n * @param {string} fullName ENSName\n */\nexport interface GetEnsAddressRequest {\n  fullName: string\n  network?: NetworkWallet\n}\n\nexport interface SubmitApproveSignatureRequestWithPatch {\n  request: ApproveSignatureRequest\n  guardian: Guardian\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\n/**\n * @param {string} approveRecordId\n * @param {string} securityNumber\n * @param {string} txAwareHash\n * @param {string} signer\n * @param {string} wallet\n * @param {string} signature\n */\nexport interface ApproveSignatureRequest {\n  approveRecordId: string\n  txAwareHash?: string //currentRequest.messageHash,\n  securityNumber: string\n  signer: string //address,\n  signature: string\n  network?: NetworkWallet\n}\n\n/**\n * @param {string} guardian address\n * @param {string} protectAddress? address\n */\nexport interface GetProtectorRequest {\n  guardian: string\n  protectAddress?: string\n  network?: NetworkWallet\n}\n\nexport enum TradesFillTypes {\n  dex = 'dex',\n  amm = 'amm',\n}\n\nexport interface GetUserTradesRequest {\n  accountId: number\n  market?: string\n  orderHash?: string\n  offset?: number\n  limit?: number\n  fromId?: number\n  fillTypes?: TradesFillTypes\n}\n\nexport type UserTrade = MarketTradeInfo\n\nexport interface UserTrades {\n  totalNum: number\n  trades: UserTrade[]\n}\n\nexport interface CancelOrderRequest {\n  accountId: number\n  clientOrderId?: string\n  orderHash?: string\n}\n\nexport interface CancelMultiOrdersByHashRequest {\n  accountId: number\n  orderHash: string // comma seprated string\n}\n\nexport interface CancelMultiOrdersByClientOrderIdRequest {\n  accountId: number\n  clientOrderId: string // comma seprated string\n}\n\nexport enum EXTRAORDER_TYPE {\n  TRADITIONAL_ORDER = 'TRADITIONAL_ORDER',\n  STOP_LIMIT = 'STOP_LIMIT',\n}\n\nexport enum STOP_SIDE {\n  NO_CONDITION = 'NO_CONDITION',\n  GREAT_THAN_AND_EQUAL = 'GREAT_THAN_AND_EQUAL',\n  LESS_THAN_AND_EQUAL = 'LESS_THAN_AND_EQUAL',\n}\n\nexport interface SubmitOrderRequestV3 {\n  /**\n   * The adderss of the exchange which has to process this order\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  exchange: string\n  /**\n   * Loopring\\'s account ID\n   * @type {number}\n   * @memberof SubmitOrderRequestV3\n   */\n  accountId: number\n  /**\n   * The unique identifier of the L2 Merkle tree storage slot where the burn made in order to exit the pool will or has been stored.\n   * @type {number}\n   * @memberof SubmitOrderRequestV3\n   */\n  storageId: number\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof SubmitOrderRequestV3\n   */\n  sellToken: TokenVolumeV3\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof SubmitOrderRequestV3\n   */\n  buyToken: TokenVolumeV3\n  /**\n   * Whether the order supports partial fills or not.Currently only supports false as a valid value\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  allOrNone: boolean\n  /**\n   * Fill size by buy token or by sell token\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  fillAmountBOrS: boolean\n  /**\n   * Order expiration time, accuracy is in seconds\n   * @type {number}\n   * @memberof SubmitOrderRequestV3\n   */\n  validUntil: number\n  /**\n   * Maximum order fee that the user can accept, value range (in ten thousandths) 1 ~ 63\n   * @type {number}\n   * @memberof SubmitOrderRequestV3\n   */\n  maxFeeBips: number\n  /**\n   * The orders EdDSA signature. The signature is a hexadecimal string obtained by signing the order itself and concatenating the resulting signature parts (Rx, Ry, and S). Used to authenticate and authorize the operation.\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  eddsaSignature: string\n  /**\n   * An arbitrary, client-set unique order identifier, max length is 120 bytes\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  clientOrderId?: string\n  /**\n   * Order types, can be AMM, LIMIT_ORDER, MAKER_ONLY, TAKER_ONLY\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  orderType?: OrderType\n  /**\n   * Used by the P2P order which user specify the taker, so far its 0x0000000000000000000000000000000000000000\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n\n  tradeChannel?: TradeChannel\n\n  taker?: string\n  /**\n   * The AMM pool address if order type is AMM\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  poolAddress?: string\n  /**\n   * Aux data to mark the order source\n   * @type {string}\n   * @memberof SubmitOrderRequestV3\n   */\n  channelId?: string\n  extraOrderType?: EXTRAORDER_TYPE\n  stopPrice?: string\n  stopSide?: STOP_SIDE\n}\n\n/**\n * Submit internal transfer params\n * @export\n * @interface OriginTransferRequestV3\n */\nexport interface OriginTransferRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  exchange: string\n  /**\n   * payer account ID\n   * @type {number}\n   * @memberof OriginTransferRequestV3\n   */\n  payerId: number\n  /**\n   * payer account address\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  payerAddr: string\n  /**\n   * payee account ID\n   * @type {number}\n   * @memberof OriginTransferRequestV3\n   */\n  payeeId: number\n  /**\n   * payee account address\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  payeeAddr: string\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OriginTransferRequestV3\n   */\n  token: TokenVolumeV3\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OriginTransferRequestV3\n   */\n  maxFee: TokenVolumeV3\n  /**\n   * offchain Id\n   * @type {number}\n   * @memberof OriginTransferRequestV3\n   */\n  storageId: number\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OriginTransferRequestV3\n   */\n  validUntil: number\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was already submitted on eth mainnet\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  hashApproved?: string\n  /**\n   * transfer memo\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  memo?: string\n  /**\n   * A user-defined id\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  clientId?: string\n\n  /**\n   * CounterFactualInfo\n   * @type {CounterFactualInfo}\n   * @memberof OriginTransferRequestV3\n   */\n  counterFactualInfo?: CounterFactualInfo\n\n  /**\n   * If true, let the sender transferring to the receiver pay the receiver's account activation fee\n   * @type {boolean}\n   * @memberof OriginTransferRequestV3\n   */\n  payPayeeUpdateAccount?: boolean\n}\n\n/**\n * Submit Forces Withdrawals params\n * @export\n * @interface OriginForcesWithdrawalsV3\n */\nexport interface OriginForcesWithdrawalsV3 {\n  /**\n   * requesterAddress account address\n   * @type {string}\n   * @memberof OriginForcesWithdrawalsV3\n   */\n  requesterAddress: string\n  /**\n   * requester withdrawls tokenId\n   * @type {number}\n   * @memberof OriginForcesWithdrawalsV3\n   */\n  tokenId: number\n  /**\n   * withdrawAddress account address\n   * @type {string}\n   * @memberof OriginForcesWithdrawalsV3\n   */\n  withdrawAddress: string\n  /**\n   * Transfer Request\n   * @type {OriginTransferRequestV3}\n   * @memberof OriginForcesWithdrawalsV3\n   */\n  transfer: Omit<OriginTransferRequestV3, 'payeeId' | 'maxFee' | 'memo'> & {\n    payeeId?: 0\n    memo?: string\n    maxFee?: {\n      volume: '0'\n      tokenId: number | string\n    }\n  }\n}\n\n/**\n * Submit Deploy NFTAction params\n * @export\n * @interface OriginDeployNFTRequestV3\n */\nexport interface OriginDeployNFTRequestV3 {\n  /**\n   * Transfer\n   * @type {OriginTransferRequestV3}\n   * @memberof OriginDeployNFTRequestV3\n   */\n  transfer: Omit<OriginTransferRequestV3, 'payeeId' | 'maxFee' | 'memo'> & {\n    payeeId?: 0\n    memo?: string\n    maxFee?: {\n      volume: '0'\n      tokenId: number | string\n    }\n  }\n  /**\n   * nftData\n   * @type {string}\n   * @memberof OriginDeployNFTRequestV3\n   */\n  nftData: string\n  /**\n   * NFTAction address\n   * @type {string}\n   * @memberof OriginDeployNFTRequestV3\n   */\n  tokenAddress: string\n  counterFactualInfo?: CounterFactualInfo\n}\n\nexport interface OriginDeployCollectionRequestV3 {\n  /**\n   * Transfer\n   * @type {OriginTransferRequestV3}\n   * @memberof OriginDeployNFTRequestV3\n   */\n  transfer: Omit<OriginTransferRequestV3, 'payeeId' | 'maxFee' | 'memo'> & {\n    payeeId?: 0\n    memo?: string\n    maxFee?: {\n      volume: '0'\n      tokenId: number | string\n    }\n  }\n  /**\n   * nftOwner\n   * @type {string}\n   * @memberof OriginDeployCollectionRequestV3\n   */\n  nftOwner: string\n  /**\n   * nftBaseUri\n   * @type {string}\n   * @memberof OriginDeployCollectionRequestV3\n   */\n  nftBaseUri: string\n  /**\n   * nftFactory\n   * @type {string}\n   * @memberof OriginDeployCollectionRequestV3\n   */\n  nftFactory: string\n  /**\n   * tokenAddress\n   * @type {string}\n   * @memberof OriginDeployCollectionRequestV3\n   */\n  tokenAddress: string\n  counterFactualInfo?: CounterFactualInfo\n}\n\n/**\n * Submit internal transfer params\n * @export\n * @interface OriginNFTTransferRequestV3\n */\nexport interface OriginNFTTransferRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  exchange: string\n  /**\n   * fromAccountId\n   * @type {number}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  fromAccountId: number\n  /**\n   * payer account address\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  fromAddress: string\n  /**\n   * to account ID\n   * @type {number}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  toAccountId: number\n  /**\n   * toAddress address\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  toAddress: string\n  /**\n   *\n   * @type {TokenVolumeNFT}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  token: TokenVolumeNFT\n  /**\n   *\n   * @type { Pick<TokenVolumeV3,'tokenId'> & {amount:string}}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  maxFee: Pick<TokenVolumeV3, 'tokenId'> & { amount: string }\n  /**\n   * offchain Id\n   * @type {number}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  storageId: number\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  validUntil: number\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was already submitted on eth mainnet\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  hashApproved?: string\n  /**\n   * transfer memo\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  memo?: string\n  /**\n   * A user-defined id\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  clientId?: string\n\n  /**\n   * CounterFactualInfo\n   * @type {CounterFactualInfo}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  counterFactualInfo?: CounterFactualInfo\n\n  /**\n   * If true, let the sender transferring to the receiver pay the receiver's account activation fee\n   * @type {boolean}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  payPayeeUpdateAccount?: boolean\n}\n\n/**\n *\n * @export\n * @interface NFTWithdrawRequestV3\n */\nexport interface NFTWithdrawRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  exchange: string\n  /**\n   * account ID\n   * @type {number}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  accountId: number\n  /**\n   * account owner address\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  owner: string\n  /**\n   *\n   * @type {TokenVolumeNFT}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  token: TokenVolumeNFT\n  /**\n   *\n   * @type {Pick<TokenVolumeV3,'tokenId'> & {amount:string}};\n   * @memberof OriginNFTTransferRequestV3\n   */\n  maxFee: Pick<TokenVolumeV3, 'tokenId'> & { amount: string }\n  /**\n   * offchain ID\n   * @type {number}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  storageId: number\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  validUntil: number\n  /**\n   * min gas for on-chain withdraw, Loopring exchange allocates gas for each distribution, but people can also assign this min gas, so Loopring have to allocate higher gas value for this specific distribution. Normally no need to take care of this value, 0 means let loopring choose the reasonable gas\n   * @type {number}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  minGas: number\n  /**\n   * withdraw to address\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  to: string\n  /**\n   * extra data for complex withdraw mode, normally none\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  extraData?: string\n  // /**\n  //  * is fast withdraw mode\n  //  * @type {boolean}\n  //  * @memberof OriginNFTWithdrawRequestV3\n  //  */\n  // fastWithdrawalMode?: boolean;\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was already submitted on eth mainnet\n   * @type {string}\n   * @memberof OriginNFTWithdrawRequestV3\n   */\n  hashApproved?: string\n  counterFactualInfo?: CounterFactualInfo\n}\n\n/**\n *\n * @export\n * @interface NFTMintRequestV3\n */\nexport interface NFTMintRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OriginNFTMintRequestV3\n   */\n  exchange: string\n  /**\n   * account ID\n   * @type {number}\n   * @memberof OriginNFTMintRequestV3\n   */\n  minterId: number\n  /**\n   * account owner address\n   * @type {string}\n   * @memberof OriginNFTMintRequestV3\n   */\n  minterAddress: string\n  /**\n   * The account receive the minted NFTAction token, now should be minter himself.\n   * @type {number}\n   * @memberof OriginNFTMintRequestV3\n   */\n  toAccountId: number\n  /**\n   * The account receive the minted NFTAction token, now should be minter himself.\n   * @type {string}\n   * @memberof OriginNFTMintRequestV3\n   */\n  toAddress?: string\n  /**\n   * nftType: 0 for EIP1155, 1 for EIP712. EIP1155 by default.\n   * @type {number}\n   * @memberof OriginNFTMintRequestV3\n   */\n  nftType: 0 | 1\n  /**\n   * Contract address\n   * @type{string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  tokenAddress: string\n  /**\n   * NFT_ID url_id\n   * @type {string}   toString(16)\n   * @memberof OriginNFTTransferRequestV3\n   */\n  nftId: string\n  /**\n   * The amount of the token\n   * @type {string}\n   * @memberof TokenVolumeV3\n   */\n  amount: string\n\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OriginNFTMintRequestV3\n   */\n  validUntil: number\n  /**\n   * offchain ID\n   * @type {number}\n   * @memberof OriginNFTMintRequestV3\n   */\n  storageId: number\n  /**\n   *\n   * @type { Pick<TokenVolumeV3,'tokenId'> & {amount:string}}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  maxFee: Pick<TokenVolumeV3, 'tokenId'> & { amount: string }\n  /**\n   * 0-50\n   * @type number\n   * @memberof OriginNFTMintRequestV3\n   */\n  royaltyPercentage: number\n  /**\n   * force to mint, regardless the previous mint record\n   * @type {boolean}\n   * @memberof OriginNFTMintRequestV3\n   */\n  forceToMint?: boolean\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OriginNFTMintRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OriginNFTMintRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was already submitted on eth mainnet\n   * @type {string}\n   * @memberof OriginNFTMintRequestV3\n   */\n  hashApproved?: string\n  counterFactualNftInfo?: NFTCounterFactualInfo | null\n  counterFactualInfo?: CounterFactualInfo\n}\n\n// /**\n//  *\n//  * @export\n//  * @interface NFTCollectionCreateRequestV3\n//  */\n// export interface NFTollectionCreateRequestV3 {\n//   /**\n//    * exchange address\n//    * @type {string}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   exchange: string;\n//   /**\n//    * account ID\n//    * @type {number}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   minterId: number;\n//   /**\n//    * account owner address\n//    * @type {string}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   minterAddress: string;\n//   /**\n//    * The account receive the minted NFTAction token, now should be minter himself.\n//    * @type {number}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   toAccountId: number;\n//   /**\n//    * The account receive the minted NFTAction token, now should be minter himself.\n//    * @type {string}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   toAddress?: string;\n//   /**\n//    * nftType: 0 for EIP1155, 1 for EIP712. EIP1155 by default.\n//    * @type {number}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   nftType: 0 | 1;\n//   /**\n//    * Contract address\n//    * @type{string}\n//    * @memberof OriginNFTTransferRequestV3\n//    */\n//   tokenAddress: string;\n//   /**\n//    * NFT_ID url_id\n//    * @type {string}   toString(16)\n//    * @memberof OriginNFTTransferRequestV3\n//    */\n//   nftId: string;\n//   /**\n//    * The amount of the token\n//    * @type {string}\n//    * @memberof TokenVolumeV3\n//    */\n//   amount: string;\n//\n//   /**\n//    * Timestamp for order to become invalid\n//    * @type {number}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   validUntil: number;\n//   /**\n//    * offchain ID\n//    * @type {number}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   storageId: number;\n//   /**\n//    *\n//    * @type { Pick<TokenVolumeV3,'tokenId'> & {amount:string}}\n//    * @memberof OriginNFTTransferRequestV3\n//    */\n//   maxFee: Pick<TokenVolumeV3, \"tokenId\"> & { amount: string };\n//   /**\n//    * 0-50\n//    * @type number\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   royaltyPercentage: number;\n//   /**\n//    * force to mint, regardless the previous mint record\n//    * @type {boolean}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   forceToMint?: boolean;\n//   /**\n//    * eddsa signature\n//    * @type {string}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   eddsaSignature?: string;\n//   /**\n//    * ecdsa signature\n//    * @type {string}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   ecdsaSignature?: string;\n//   /**\n//    * An approved hash string which was already submitted on eth mainnet\n//    * @type {string}\n//    * @memberof OriginNFTMintRequestV3\n//    */\n//   hashApproved?: string;\n//   counterFactualNftInfo?: NFTCounterFactualInfo | null;\n//   counterFactualInfo?: CounterFactualInfo;\n// }\n\n/**\n *\n * @export\n * @interface NFTOrderRequestV3\n */\nexport type NFTOrderRequestV3<R = 'Taker' | 'Maker'> = {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof NFTOrderRequestV3\n   */\n  exchange: string\n  /**\n   * account ID\n   * @type {number}\n   * @memberof NFTOrderRequestV3\n   */\n  accountId: number\n  /**\n   * storage ID\n   * @type {number}\n   * @memberof NFTOrderRequestV3\n   */\n  storageId: number\n\n  /**\n   *\n   * @type {boolean}\n   * @memberof NFTOrderRequestV3\n   */\n  allOrNone: boolean\n  /**\n   *\n   * @type {boolean}\n   * @memberof NFTOrderRequestV3\n   */\n  fillAmountBOrS: boolean\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof NFTOrderRequestV3\n   */\n  validUntil: number\n  /**\n   * max fee bips.\n   * @type {number | 0}\n   * @memberof NFTOrderRequestV3\n   */\n  maxFeeBips?: number | 0\n  /**\n   * eddsa signature.\n   * @type {string}\n   * @memberof NFTOrderRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * client order id.\n   * @type {string}\n   * @memberof NFTOrderRequestV3\n   */\n  clientOrderId?: string\n  /**\n   * order type\n   * @type{string}\n   * @memberof NFTOrderRequestV3\n   */\n  orderType?: string\n  /**\n   * trade channel\n   * @type {string}\n   * @memberof NFTOrderRequestV3\n   */\n  tradeChannel?: string\n  /**\n   * taker address\n   * @type {string}\n   * @memberof NFTOrderRequestV3\n   */\n  taker?: string\n  /**\n   * affiliate account id\n   * @type {string}\n   * @memberof NFTOrderRequestV3\n   */\n  affiliate?: string\n} & XOR<\n  {\n    /**\n     * maker order\n     * sell token info\n     * @type {NFTTokenAmountInfo}\n     * @memberof NFTOrderRequestV3\n     */\n    sellToken: NFTTokenAmountInfo\n    /**\n     * buy token info\n     * @type {TokenVolumeV5}\n     * @memberof NFTOrderRequestV3\n     */\n    buyToken: TokenVolumeV5\n  },\n  {\n    /**\n     * taker order\n     * sell token info\n     * @type {TokenVolumeV5}\n     * @memberof NFTOrderRequestV3\n     */\n    sellToken: TokenVolumeV5\n    /**\n     * maker Order\n     * buy token info\n     * @type {NFTTokenAmountInfo}\n     * @memberof NFTOrderRequestV3\n     */\n    buyToken: NFTTokenAmountInfo\n  }\n>\n\n/**\n *\n * @export\n * @interface NFTTradeRequestV3\n */\nexport interface NFTTradeRequestV3 {\n  /**\n   * maker order\n   * @type {NFTOrderRequestV3}\n   * @memberof NFTTradeRequestV3\n   */\n  maker: NFTOrderRequestV3\n  /**\n   * maker fee bips\n   * @type {number}\n   * @memberof NFTOrderRequestV3\n   */\n  makerFeeBips: number\n  /**\n   * taker order\n   * @type {NFTOrderRequestV3}\n   * @memberof NFTTradeRequestV3\n   */\n  taker: NFTOrderRequestV3\n  /**\n   * taker fee bips\n   * @type {number}\n   * @memberof NFTTradeRequestV3\n   */\n  takerFeeBips: number\n}\n\n/**\n *\n * @export\n * @interface OffChainWithdrawalRequestV3\n */\nexport interface OffChainWithdrawalRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  exchange: string\n  /**\n   * account ID\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  accountId: number\n  /**\n   * account owner address\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  owner: string\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  token: TokenVolumeV3\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  maxFee: TokenVolumeV3\n  /**\n   * offchain ID\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  storageId: number\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  validUntil: number\n  /**\n   * min gas for on-chain withdraw, Loopring exchange allocates gas for each distribution, but people can also assign this min gas, so Loopring have to allocate higher gas value for this specific distribution. Normally no need to take care of this value, 0 means let loopring choose the reasonable gas\n   * @type {number}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  minGas: number\n  /**\n   * withdraw to address\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  to: string\n  /**\n   * extra data for complex withdraw mode, normally none\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  extraData?: string\n  /**\n   * is fast withdraw mode\n   * @type {boolean}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  fastWithdrawalMode?: boolean\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was already submitted on eth mainnet\n   * @type {string}\n   * @memberof OffChainWithdrawalRequestV3\n   */\n  hashApproved?: string\n}\n\n/**\n * Describes the users public key which is a point of the selected eclipse curve.\n * @export\n * @interface PublicKey\n */\n\nexport interface UpdateAccountRequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof UpdateAccountRequestV3\n   */\n  exchange: string\n  /**\n   * owner address\n   * @type {string}\n   * @memberof UpdateAccountRequestV3\n   */\n  owner: string\n  /**\n   * user account ID\n   * @type {number}\n   * @memberof UpdateAccountRequestV3\n   */\n  accountId: number\n  /**\n   *\n   * @type {PublicKey}\n   * @memberof UpdateAccountRequestV3\n   */\n  publicKey: PublicKey\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof UpdateAccountRequestV3\n   */\n  maxFee: TokenVolumeV3\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof UpdateAccountRequestV3\n   */\n  validUntil: number\n  /**\n   * Nonce of users exchange account that used in off-chain requests.\n   * @type {number}\n   * @memberof UpdateAccountRequestV3\n   */\n  nonce: number\n  /**\n   * eddsa signature of this request\n   * @type {string}\n   * @memberof UpdateAccountRequestV3\n   */\n  eddsaSignature?: string\n  /**\n   * ecdsa signature of this request\n   * @type {string}\n   * @memberof UpdateAccountRequestV3\n   */\n  ecdsaSignature?: string\n  /**\n   * An approved hash string which was submitted on eth mainnet\n   * @type {string}\n   * @memberof UpdateAccountRequestV3\n   */\n  hashApproved?: string\n\n  keySeed?: string\n  recommenderAccountId?: number\n  counterFactualInfo?: CounterFactualInfo\n}\n\nexport interface OffChainWithdrawalRequestV3WithPatch {\n  request: OffChainWithdrawalRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginTransferRequestV3WithPatch {\n  request: OriginTransferRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginForcesWithdrawalsRequestV3WithPatch {\n  request: OriginForcesWithdrawalsV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginDeployNFTRequestV3WithPatch {\n  request: OriginDeployNFTRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginDeployCollectionRequestV3WithPatch {\n  request: OriginDeployCollectionRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginNFTTransferRequestV3WithPatch {\n  request: OriginNFTTransferRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginNFTWithdrawRequestV3WithPatch {\n  request: NFTWithdrawRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginNFTMINTRequestV3WithPatch {\n  request: NFTMintRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginNFTCreateCollectionRequestV3WithPatch {\n  // request: NFTMintRequestV3;\n  // web3: Web3;\n  // chainId: ChainId;\n  // walletType: ConnectorNames;\n  // eddsaKey: string;\n  // apiKey: string;\n  // isHWAddr?: boolean;\n}\n\nexport interface OriginNFTValidateOrderRequestV3WithPatch {\n  request: NFTOrderRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginNFTTradeRequestV3WithPatch {\n  request: NFTTradeRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface UpdateAccountRequestV3WithPatch {\n  request: UpdateAccountRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  isHWAddr?: boolean\n  privateKey?: string\n}\n\nexport interface GetAccountServicesRequest {\n  phone?: string\n  email?: string\n  wallet?: string\n}\n\n// NFTAction\n\nexport interface GetUserNFTBalancesRequest {\n  accountId: number\n  nftDatas?: string\n  tokenAddrs?: string\n  tokenIds?: string\n  offset?: number\n  limit?: number\n  nonZero?: boolean\n  metadata?: boolean\n}\n\nexport interface GetUserNFTBalancesByCollectionRequest {\n  accountId: number\n  tokenAddress: string\n  collectionId: number\n  offset?: number\n  limit?: number\n  nonZero?: boolean\n  metadata?: boolean\n  favourite?: boolean\n  hidden?: boolean\n}\n\nexport enum LegacyNFT {\n  inside = 'inside',\n  outside = 'outside',\n  undecided = 'undecided',\n}\n\nexport interface GetUserNFTLegacyBalanceRequest {\n  accountId: number\n  tokenAddress: string\n  collectionId: number\n  filter?: LegacyNFT\n  offset?: number\n  limit?: number\n  metadata?: boolean\n}\n\nexport enum DEPLOYMENT_STATUS {\n  NOT_DEPLOYED = 'NOT_DEPLOYED',\n  DEPLOY_FAILED = 'DEPLOY_FAILED',\n  DEPLOYING = 'DEPLOYING',\n  DEPLOYED = 'DEPLOYED',\n}\n\nexport enum NFT_IMAGE_SIZES {\n  small = '240-240',\n  large = '332-332',\n  original = 'original',\n}\n\nexport type IPFS_METADATA = {\n  uri: string\n  base: {\n    name: string\n    decimals: number\n    description: string\n    image: string\n    properties: string\n    localization: string\n  }\n\n  imageSize: { [P in NFT_IMAGE_SIZES]?: string }\n  extra: {\n    imageData: string\n    externalUrl: string\n    attributes: string\n    backgroundColor: string\n    animationUrl: string\n    youtubeUrl: string\n    minter: string\n  }\n  nftId?: string\n  nftType: NFTType\n  network: 0\n  tokenAddress: string\n  tokenId: string\n}\n\nexport interface UserNFTBalanceInfo<I = NFT_IMAGE_SIZES> extends NFTTokenInfo {\n  accountId: number\n  tokenId: number\n  total?: string\n  locked?: string\n  pending: {\n    withdraw: string\n    deposit: string\n  }\n  preference: {\n    favourite: boolean\n    hide: boolean\n  }\n  collectionInfo: CollectionMeta\n  metadata?: IPFS_METADATA\n  deploymentStatus: DEPLOYMENT_STATUS\n  isCounterFactualNFT: boolean\n}\n\nexport interface GetUserVIPInfoRequest {\n  userAddress: string\n}\n\nexport interface getUserVIPAssetsRequest {\n  address: string\n  currency?: string\n  assetTypes?: string\n  token?: string\n  limit?: number\n}\n\nexport type NftData = string\n\nexport interface NFTTokenInfo {\n  nftData: string\n  minter: string\n  nftType: string\n  tokenAddress: string\n  nftId: string\n  status: boolean\n}\n\nexport interface NFTTokenAmountInfo {\n  tokenId: number\n  nftData?: string\n  amount: string\n}\n\nexport type GetUserNFTTransferHistoryRequest = {\n  accountId: number\n  nftData?: string\n  start?: number\n  end?: number\n  hashes?: string\n  txStatus?: string\n  limit?: number\n  // offset?: number\n  // transferTypes?: string // transfer, transfer_red\n}\n\nexport type GetUserNFTMintHistoryRequest = {\n  accountId: number\n  nftData?: string\n  start?: number\n  startId?: number\n  end?: number\n  hashes?: string\n  txStatus?: string\n  limit?: number\n  // offset?: number\n  // transferTypes?: string // transfer, transfer_red\n}\n\nexport type GetUserNFTDepositHistoryRequest = {\n  accountId: number\n  nftData?: string\n  start?: number\n  end?: number\n  startId?: number\n  hashes?: string\n  txStatus?: string\n  limit?: number\n}\n\nexport type GetUserNFTWithdrawalHistoryRequest = {\n  accountId: number\n  nftData?: string\n  start?: number\n  end?: number\n  startId?: number\n  hashes?: string\n  txStatus?: string\n  limit?: number\n}\n\nexport interface UserNFTDepositHistoryTx {\n  id: number\n  requestId: number\n  nftData: string\n  amount: string\n  hash: string\n  txHash: string\n  accountId: number\n  owner: string\n  status: TxStatus\n  progress: string\n  timestamp: number\n  blockId: number\n  indexInBlock: number\n  createdAt: number\n  updatedAt: number\n  feeTokenSymbol: string\n  feeAmount: string\n  memo?: string\n  depositFrom: string\n  depositFromAccountId: string\n}\n\nexport interface UserNFTWithdrawalHistoryTx {\n  id: number\n  requestId: number\n  hash: string\n  txHash: string\n  accountId: number\n  owner: string\n  status: string\n  nftData?: string\n  amount?: string\n  feeTokenSymbol?: string\n  feeAmount: string\n  createdAt: number\n  updatedAt: number\n  memo?: string\n  recipient: string\n  distributeHash: string\n  fastWithdrawStatus: string\n  isFast: false\n  blockIdInfo: {\n    blockId: number\n    indexInBlock: number\n  }\n  storageInfo: {\n    accountId: number\n    tokenId: number\n    storageId: number\n  }\n}\n\nexport interface UserNFTTransferHistoryTx {\n  id: string\n  requestId: number\n  hash: string\n  txHash: string\n  accountId: number\n  owner: string\n  status: string\n  nftData: string\n  amount: string\n  feeTokenSymbol: string\n  feeAmount: string\n  createdAt: number\n  updatedAt: number\n  memo: string\n  payeeId: number\n  payeeAddress: string\n  blockIdInfo: {\n    blockId: number\n    indexInBlock: number\n  }\n  storageInfo: {\n    accountId: number\n    tokenId: number\n    storageId: number\n  }\n}\n\nexport type UserNFTMintHistoryTx = {\n  id: string\n  requestId: number\n  hash: string\n  txHash: string\n  accountId: number\n  owner: string\n  status: string\n  nftData: string\n  amount: string\n  feeTokenSymbol: string\n  feeAmount: string\n  createdAt: number\n  updatedAt: number\n  memo: string\n  minterId: number\n  minterAddress: string\n  blockIdInfo: {\n    blockId: number\n    indexInBlock: number\n  }\n  storageInfo: {\n    accountId: number\n    tokenId: number\n    storageId: number\n  }\n}\n\nexport interface UserNFTTxsHistory {\n  id: string\n  requestId: number\n  hash: string\n  txHash: string\n  accountId: number\n  owner: string\n  nftData: string\n  amount: string\n  feeTokenSymbol: string\n  feeAmount: string\n  createdAt: number\n  updatedAt: number\n  memo: string\n  payeeId: number\n  payeeAddress: string\n  nftTxType: string\n  symbol: string\n  receiver: number\n  status: TxStatus\n  progress: string\n  timestamp: number\n  blockNum: number\n  distributeHash: string\n  receiverAddress: string\n  senderAddress: string\n  fastStatus: string\n  recipient: string\n  minterInfo: { accountId: number; minter: string; originalMinter: string }\n  nftStatusInfo: {}\n  withdrawalInfo: {\n    distributeHash: string\n    fastStatus: boolean\n    recipient: string\n  }\n  metadata?: IPFS_METADATA\n  storageInfo: {\n    accountId: number\n    tokenId: number\n    storageId: number\n  }\n}\n\nexport declare type NFTOrderInfo = {\n  orderHash: string\n  accountId: number\n  feeAmount: string\n  storageId: number\n  address: string\n}\n\nexport interface UserNFTTradeHistory {\n  fillId: number\n  nftHash: string\n  feeTokenId: number\n  price: string\n  nftAmount: string\n  feeAmount: string\n  feeTokenSymbol: string\n  createdAt: number\n  hash: string\n  blockId: number\n  indexInBlock: number\n  tokenId: number\n  counter: number\n  tokenAddress: number\n  sInfo: NFTOrderInfo\n  bInfo: NFTOrderInfo\n  metadata: IPFS_METADATA\n}\n\nexport type Protector = {\n  ens: string\n  address: string\n  lockStatus: HEBAO_LOCK_STATUS\n}\nexport type HebaoOperationLog = {\n  createdAt: number\n  ens: string\n  from: string\n  hebaoTxType: HEBAO_META_TYPE\n  id: number\n  status: 0 | 1\n  to: string\n}\n\nexport type Guardian = {\n  ens: string\n  address: string\n  type: HEBAO_META_TYPE\n  id: string\n  messageHash: string\n  businessDataJson: any\n  signedRequest: any\n  createAt: number\n}\n\n/**\n *\n * @export\n * @interface ApproveHebaoRequest\n */\nexport type GuardiaContractAddress = string\n\nexport interface ApproveHebaoRequestV3WithPatch {\n  request: Guardian & { code: string }\n  web3: Web3\n  address: string\n  chainId: ChainId\n  guardiaContractAddress: GuardiaContractAddress\n  walletType?: ConnectorNames\n}\n\nexport interface RejectHebaoRequestV3WithPatch {\n  request: { approveRecordId: string; signer: string; network?: NetworkWallet }\n  web3: Web3\n  address: string\n  chainId: ChainId\n  guardiaContractAddress: GuardiaContractAddress\n  walletType?: ConnectorNames\n}\n\nexport interface LockHebaoHebaoParam {\n  web3: Web3\n  from: string\n  wallet: string\n  value?: string | number\n  contractAddress: string\n  gasPrice: string\n  gasLimit: string\n  chainId?: ChainId\n  nonce: number\n  isVersion1: boolean\n  sendByMetaMask?: boolean\n}\n\nexport interface HebaoOperationLogs {\n  from: string\n  fromTime: number\n  to?: string\n  offset?: number\n  statues?: string\n  hebaoTxType?: string\n  limit?: number\n  network?: NetworkWallet\n}\n\nexport interface WalletType {\n  isInCounterFactualStatus: boolean\n  isContract: boolean\n  loopringWalletContractVersion: string\n}\n\nexport interface ContractType {\n  network: string\n  contractVersion: string //V1_x_x\"|V2_x_x\n  masterCopy?: string // V2 only\n  walletFactory?: string // V2 only\n  ens?: string\n  walletStatus: number\n  queueStatus: number\n  walletType: number // HEBAO = 0; EOA = 1;\n  isCounterFactual: boolean //isCounterFactual\n}\n\nexport interface ModuleType {\n  moduleName: string // FORWARDER_MODULE\n  moduleAddress: string\n}\n\n/**\n * DefiOrderRequest\n */\nexport interface DefiOrderRequest {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  exchange: string\n  /**\n   * storageId\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  storageId: number\n  /**\n   * accountId\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  accountId: number\n  /**\n   * sellToken\n   * @type TokenVolumeV3\n   * @memberof DefiOrderRequest\n   */\n  sellToken: TokenVolumeV3\n  /**\n   * buyToken\n   * @type TokenVolumeV3\n   * @memberof DefiOrderRequest\n   */\n  buyToken: TokenVolumeV3\n  /**\n   * Timestamp for order become invalid\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  validUntil: number\n  /**\n   * fee\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  fee: string\n  /**\n   * Maximum order fee that the user can accept, value range (in ten thousandths) 1 ~ 63\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  maxFeeBips: number\n  /**\n   * fillAmountBOrS\n   * @type boolean\n   * @memberof DefiOrderRequest\n   */\n  fillAmountBOrS: boolean\n  /**\n   * taker address\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  taker?: string\n  /**\n   * The orders EdDSA signature. The signature is a hexadecimal string obtained by signing the order itself and concatenating the resulting signature parts (Rx, Ry, and S). Used to authenticate and authorize the operation.\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  eddsaSignature?: string\n  /**\n   * type\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  type: string\n  /**\n   * action\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  action: string\n}\n\nexport interface DefiResult {\n  hash: string\n  clientOrderId: string\n  status: TxStatus\n  isIdempotent: boolean\n}\n\nexport const SEP = ','\n\nexport enum DefiAction {\n  Deposit = 'deposit',\n  Withdraw = 'withdraw',\n}\n\nexport interface UserDefiTxsHistory {\n  id: string\n  txType: string\n  action: DefiAction\n  hash: string\n  market: string\n  sellToken: TokenVolumeV3\n  buyToken: TokenVolumeV3\n  fee: TokenVolumeV3\n  status: TxStatus\n  updatedAt: number\n  storageInfo: {\n    accountId: number\n    tokenId: number\n    storageId: number\n  }\n}\n\nexport interface GetDefiMarketRequest {\n  defiType?: string\n}\n\nexport interface GetUserDefiRewardRequest {\n  accountId: number\n}\n\nexport interface GetUserDefiTxRequest {\n  accountId: number\n  offset: number\n  start?: number\n  end?: number\n  limit: number\n}\n\nexport type CollectionExtendsKey = {\n  thumbnail?: string\n  cid?: string\n  id?: string\n  contractAddress: string\n  collectionAddress: string\n  deployStatus: DEPLOYMENT_STATUS\n  updatedAt: number\n  createdAt: number\n  nftType: string\n  baseUri: string\n  collectionTitle?: string\n  extra: {\n    mintChannel: string\n    properties: {\n      isCounterFactualNFT: boolean\n      isDeletable: boolean\n      isEditable: boolean\n      isLegacy: boolean\n      isMintable: boolean\n      isPublic: boolean\n    }\n  }\n  cached: {\n    avatar: string\n    banner: string\n    thumbnail: string\n    tileUri: string\n  }\n  isCounterFactualNFT?: boolean\n  isDeletable?: boolean\n  isEditable?: boolean\n  isLegacy?: boolean\n  isMintable?: boolean\n  isPublic?: boolean\n}\n\nexport type CollectionBasicMeta = {\n  name: string\n  tileUri: string\n  nftFactory?: string\n  description?: string\n  avatar?: string\n  banner?: string\n  owner: string\n}\nexport type CollectionDelete = {\n  accountId: number\n  collectionId: number\n}\n\nexport type CollectionLegacyMeta = Omit<CollectionBasicMeta, 'owner'> & {\n  accountId: number\n  tokenAddress: string\n}\n\nexport enum NFT_PREFERENCE_TYPE {\n  fav = 'fav',\n  hide = 'hide',\n}\n\nexport type UpdateNFTLegacyCollectionRequest = {\n  accountId: number\n  nftHashes: string[]\n  collectionId?: number\n}\n\nexport type UpdateNFTGroupRequest = {\n  accountId: number\n  nftHashes: string[]\n  collectionId?: number\n  preferenceType: NFT_PREFERENCE_TYPE\n  statusToUpdate: boolean\n}\n/**\n * CollectionMeta\n * @property name string useToCreate Collection\n * @property name string\n * @property tileUri string option\n * @property owner? string option\n * @property nftFactory? string option\n * @property baseUri? string option\n * @property collectionTitle? string option\n * @property description? string option\n * @property avatar? string option\n * @property banner? string option\n * @property thumbnail? string option\n * @property cid? string option\n *\n */\nexport type CollectionMeta = CollectionExtendsKey & CollectionBasicMeta\n\nexport interface GetUserOwnerCollectionRequest {\n  owner: string\n  offset?: number\n  limit?: number\n  tokenAddress?: string\n  isMintable?: boolean\n}\n\nexport interface GetUserLegacyCollectionRequest {\n  accountId: string\n  tokenAddress: string\n  offset?: number\n  limit?: number\n}\n\nexport interface GetCollectionWholeNFTsRequest {\n  id: number\n  metadata?: boolean\n  offset?: number\n  limit?: number\n}\n\nexport interface GetUserNFTCollectionRequest {\n  accountId: string\n  offset?: number\n  limit?: number\n  collectionId?: number\n  tokenAddress?: string\n}\n\nexport enum DUAL_TYPE {\n  DUAL_BASE = 'DUAL_BASE',\n  DUAL_CURRENCY = 'DUAL_CURRENCY',\n}\n\nexport type GetDualInfosRequest = {\n  baseSymbol: string\n  quoteSymbol: string\n  currency: string\n  dualType: DUAL_TYPE\n  minStrike?: string\n  maxStrike?: string\n  startTime?: number\n  timeSpan?: number\n  limit: number\n}\nexport type GetDualPricesRequest = {\n  baseSymbol: string\n  productIds: string\n}\nexport type GetDualRuleRequest = { baseSymbol: string; currency?: string }\n\nexport type DualBid = {\n  baseProfit: string\n  baseQty: string\n}\nexport type DualPrice = {\n  productId: string\n  cacheQty: string\n  priceTime: number\n  dualBid: DualBid[]\n}\nexport type DualIndex = {\n  index: string\n  base: string\n  quote: string\n  indexTime: number\n}\n\nexport type DualProductAndPrice = {\n  productId: string\n  base: string\n  quote: string\n  currency: string\n  createTime: number\n  expireTime: number\n  strike: string\n  expired: boolean\n  dualType: DUAL_TYPE\n  ratio: number\n  profit: string\n  baseSize: string\n}\n\nexport type DualRulesCoinsInfo = {\n  base: string\n  quote: string\n  currency: string\n  basePrecision: number\n  currencyPrecision: number\n  baseMin: string\n  currencyMin: string\n  baseMax: string\n  currencyMax: string\n  granulation: number\n  baseProfitStep: number\n}\nexport type DualBalance = {\n  coin: string\n  free: string\n  frozen: string\n}\n\nexport enum LABEL_INVESTMENT_STATUS {\n  // INVESTMENT_SUCCEEDED = \"INVESTMENT_SUCCEEDED\",\n  // INVESTMENT_FAILED = \"INVESTMENT_FAILED\",\n  // INVESTMENT_RECEIVED = \"INVESTMENT_RECEIVED\",\n  PAID = 'paid',\n  UNSETTLED = 'unsettled',\n  SETTLED = 'settled',\n  REJECTED = 'rejected',\n  SUCCESS = 'success',\n  RECEIVED = 'received',\n  PROCESSED = 'processed',\n  FAILED = 'failed',\n  PROCESSING = 'processing',\n  CANCELLED = 'cancelled',\n}\n\nexport enum SETTLEMENT_STATUS {\n  UNSETTLED = 'UNSETTLED',\n  SETTLED = 'SETTLED',\n  PAID = 'PAID',\n}\n\nexport enum DUAL_RETRY_STATUS {\n  NO_RETRY = 'NO_RETRY',\n  RETRYING = 'RETRYING',\n  RETRY_SUCCESS = 'RETRY_SUCCESS',\n  RETRY_FAILED = 'RETRY_FAILED',\n}\n\nexport interface GetUserDualTxRequest {\n  accountId: number\n  dualTypes: DUAL_TYPE\n  hashes: string\n  investmentStatuses?: LABEL_INVESTMENT_STATUS\n  settlementStatuses?: SETTLEMENT_STATUS\n  offset?: number\n  start?: number\n  end?: number\n  limit: number\n  retryStatuses?: DUAL_RETRY_STATUS[]\n}\n\nexport type DUAL_REINVEST_INFO = {\n  isRecursive: boolean\n  maxDuration: string\n  newStrike: number\n  retryStatus: DUAL_RETRY_STATUS\n}\n\nexport interface UserDualTxsHistory {\n  id: string\n  hash: string\n  productId: string\n  dualType: DUAL_TYPE\n  settleRatio: number\n  filled: string\n  dualFilled: string\n  deliveryPrice: number\n  strike: number\n  market: string\n  tokenInfoOrigin: {\n    base: string\n    quote: string\n    currency: string\n    amountIn: string\n    amountOut: string\n    market: string\n    tokenIn: number\n    tokenOut: number\n  }\n  timeOrigin: {\n    expireTime: number\n    createTime: number\n    updateTime: number\n    settlementTime: number\n  }\n  investmentStatus: LABEL_INVESTMENT_STATUS\n  settlementStatus: SETTLEMENT_STATUS\n  dualReinvestInfo?: DUAL_REINVEST_INFO\n  createdAt: number\n  updatedAt: number\n}\n\n/**\n * DualOrderRequest\n */\nexport interface DualOrderRequest {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  exchange: string\n  /**\n   * storageId\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  storageId: number\n  /**\n   * accountId\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  accountId: number\n  /**\n   * sellToken\n   * @type TokenVolumeV3\n   * @memberof DefiOrderRequest\n   */\n  sellToken: TokenVolumeV3\n  /**\n   * buyToken\n   * @type TokenVolumeV3\n   * @memberof DefiOrderRequest\n   */\n  buyToken: TokenVolumeV3\n  /**\n   * Timestamp for order become invalid\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  validUntil: number\n  /**\n   * fee\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  fee: string\n  /**\n   * Maximum order fee that the user can accept, value range (in ten thousandths) 1 ~ 63\n   * @type {number}\n   * @memberof DefiOrderRequest\n   */\n  maxFeeBips: number\n  /**\n   * fillAmountBOrS\n   * @type boolean\n   * @memberof DefiOrderRequest\n   */\n  fillAmountBOrS: boolean\n  /**\n   * The orders EdDSA signature. The signature is a hexadecimal string obtained by signing the order itself and concatenating the resulting signature parts (Rx, Ry, and S). Used to authenticate and authorize the operation.\n   * @type {string}\n   * @memberof DefiOrderRequest\n   */\n  eddsaSignature?: string\n\n  baseProfit: string\n  clientOrderId: string\n  productId: string\n  settleRatio: string\n  expireTime: number\n  /**\n   * If this dual order is recursive\n   * @memberof DefiOrderRequest\n   * @type {boolean}\n   */\n  isRecursive?: boolean\n  /**\n   * If this dual order is recursive, max expire time of next dual product (1-10days in millieseconds)\n   * @memberof DefiOrderRequest\n   * @type {numbwe}\n   */\n  maxRecurseProductDuration?: number\n}\n\nexport type DualEditRequest = {\n  newOrder?: Omit<DualOrderRequest, 'isRecursive' | 'maxRecurseProductDuration'>\n  currentDualHash: string\n  isRecursive: boolean\n  maxDuration: number\n  newStrike: string\n  accountId: null\n}\n\nexport type CalDualResult = {\n  sellVol: string\n  quota: string\n  lessEarnVol: string\n  lessEarnTokenSymbol: string\n  greaterEarnVol: string\n  greaterEarnTokenSymbol: string\n  maxSellAmount: string\n  miniSellVol: string\n  feeVol: string | undefined\n  feeTokenSymbol?: string\n  maxFeeBips: number\n  sellToken: TokenInfo\n}\n\nexport interface DualUserLockedRequest {\n  accountId: number\n  lockTag: DUAL_TYPE[]\n  status: string\n}\n\nexport enum LuckyTokenItemStatusIndex {\n  SUBMITTING = 0,\n  NOT_EFFECTIVE = 1,\n  PENDING = 2,\n  COMPLETED = 3,\n  OVER_DUE = 4,\n  FAILED = 5,\n}\n\nexport enum LuckyTokenWithdrawStatus {\n  RECEIVED = 0,\n  PROCESSING = 1,\n  PROCESSED = 2,\n  WITHDRAW_FAILED = 3,\n  PREPARE_FAILED = 4,\n}\n\nexport enum LuckyTokenItemStatus {\n  SUBMITTING = 'SUBMITTING',\n  NOT_EFFECTIVE = 'NOT_EFFECTIVE',\n  PENDING = 'PENDING',\n  COMPLETED = 'COMPLETED',\n  OVER_DUE = 'OVER_DUE',\n  FAILED = 'FAILED',\n}\n\nexport enum LuckyTokenAmountType {\n  RANDOM = 0,\n  AVERAGE = 1,\n}\n\nexport enum LuckyTokenViewType {\n  PUBLIC = 0,\n  PRIVATE = 1,\n  TARGET = 2,\n}\n\nexport enum LuckyTokenClaimType {\n  RELAY = 0,\n  COMMON = 1,\n  BLIND_BOX = 2,\n}\n\nexport enum ClaimRecordStatus {\n  WAITING_CLAIM = 'WAITING_CLAIM',\n  CLAIMED = 'CLAIMED',\n  EXPIRED = 'EXPIRED',\n  CLAIMING = 'CLAIMING',\n}\n\nexport enum BlindBoxStatus {\n  NOT_OPENED = 'NOT_OPENED',\n  OPENED = 'OPENED',\n  EXPIRED = 'EXPIRED',\n}\n\nexport type LuckyTokenChampion = {\n  accountId: number\n  address: string\n  ens: string\n  amount: number\n}\nexport type LuckyTokenAmount = {\n  totalCount: number\n  remainCount: number\n  totalAmount: string\n  remainAmount: string\n  claimedBoxCount: number\n  giftCount: number\n}\nexport type LuckyTokenType = {\n  partition: LuckyTokenAmountType\n  scope: LuckyTokenViewType\n  mode: LuckyTokenClaimType\n}\nexport type LuckyTokenInfo = {\n  memo: string\n  signer: string\n  signerUrl: string\n  logoUrl: string\n}\nexport type LuckyTokenSender = {\n  accountId: number\n  address: string\n  ens: string\n}\nexport type LuckyTokenItemForReceive = {\n  hash: string\n  sender: LuckyTokenSender\n  champion: LuckyTokenChampion\n  tokenId: number\n  tokenAmount: LuckyTokenAmount\n  type: LuckyTokenType\n  status: LuckyTokenItemStatus\n  validSince: number\n  validUntil: number\n  info: LuckyTokenInfo\n  templateNo: number\n  createdAt: number\n  nftTokenInfo?: UserNFTBalanceInfo\n  isNft?: boolean\n  isOfficial?: boolean\n  nftExpireTime: number\n  notifyType?: string\n  serialNo?: number \n}\nexport type BlindBoxClaimInfo = {\n  // 盲盒信息\n  id: number\n  hash: string\n  claimer: {\n    accountId: number\n    address: string\n    ens: string\n  }\n  tokenId: number\n  nftHash: string\n  amount: string\n  status: string\n  openTime: string\n  expireTime: string\n  createdAt: number\n  serialNo?: number\n}\nexport type LuckyTokenBlindBoxItemReceive = {\n  luckyToken: LuckyTokenItemForReceive\n  claim: BlindBoxClaimInfo\n}\nexport type LuckTokenClaim = {\n  hash: string\n  claimer: {\n    accountId: number\n    address: string\n    ens: string\n  }\n  referrer: {\n    accountId: number\n    address: number\n    ens: string\n  }\n  helper: {\n    accountId: number\n    address: number\n    ens: number\n  }\n  amount: number\n  createdAt: number\n  claimId: number\n  serialNo?: number\n}\n\nexport type LuckyTokenSignerFlag = 0 | 1\nexport type LuckTokenHistory = {\n  champion: LuckyTokenChampion\n  claimAmount: number\n  claim: {\n    id: number\n  } & LuckTokenClaim\n  tokenId: number\n  hash: string\n  helpers: {\n    accountId: number\n    address: number\n    ens: number\n  }[]\n  luckyToken: {\n    id: number\n  } & LuckyTokenItemForReceive\n}\nexport type LuckTokenClaimDetail = {\n  champion: LuckyTokenChampion\n  claimAmount: number\n  claims: Array<\n    {\n      id: number\n    } & LuckTokenClaim\n  >\n  tokenId: number\n  hash: string\n  helpers: {\n    accountId: number\n    address: number\n    ens: number\n    amount: number\n  }[]\n  luckyToken: {\n    id: number\n  } & LuckyTokenItemForReceive\n  claimStatus: ClaimRecordStatus\n}\n\nexport type LuckTokenWithdraw = {\n  id: number\n  hash: string\n  claimer: {\n    accountId: number\n    address: number\n    ens: string\n  }\n  tokenId: number\n  amount: string\n  feeTokenId: number\n  feeAmount: number\n  status: 0 | 1 | 2 // PENDING:0 SUCCESS:1  FAIL:2\n  createdAt: number\n  updatedAt: number\n  isNft: boolean\n  nftTokenInfo?: UserNFTBalanceInfo\n}\n\nexport type TOKENMAPLIST = {\n  tokensMap: LoopringMap<TokenInfo>\n  coinMap: LoopringMap<{\n    icon?: string\n    name: string\n    simpleName: string\n    description?: string\n    company: string\n  }>\n  totalCoinMap: LoopringMap<{\n    icon?: string\n    name: string\n    simpleName: string\n    description?: string\n    company: string\n  }>\n  idIndex: LoopringMap<string>\n  addressIndex: LoopringMap<TokenAddress>\n}\n\nexport interface OriginLuckTokenWithdrawsRequestV3 {\n  tokenId: number\n  feeTokenId: number\n  amount: string\n  claimer: string\n  transfer: Omit<OriginTransferRequestV3, 'payeeId' | 'maxFee' | 'memo'> & {\n    payeeId?: 0\n    memo?: string\n    maxFee?: {\n      volume: '0'\n      tokenId: number | string\n    }\n  }\n  nftData?: string\n  luckyTokenHash?: string\n  serialNo?: number\n}\n\nexport interface OriginLuckTokenWithdrawsRequestV3WithPatch {\n  request: OriginLuckTokenWithdrawsRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\n/**\n * LuckyTokenItemForSend\n *\n */\nexport type LuckyTokenItemForSendV3 = {\n  type: LuckyTokenType\n  /**\n   * numbers\n   * @type {number}  ERC20 [1,10000], NFT [1,20000]\n   * @memberof LuckyTokenItemForSend\n   */\n  numbers: number // <10000\n  giftNumbers: number // <10000\n  memo: string\n  signerFlag: boolean\n  templateId: number\n  validSince: number\n  validUntil: number\n} & (\n  | {\n      luckyToken: OriginTransfer3RequestV3\n      /**\n       * nftData\n       * @type {string}  NFT required\n       * @memberof LuckyTokenItemForSend\n       */\n      nftData: string\n    }\n  | {\n      luckyToken: OriginTransfer3RequestV3\n    }\n)\n\nexport interface OriginLuckTokenSendRequestV3WithPatch {\n  request: LuckyTokenItemForSendV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface OriginTransfer3RequestV3 {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  exchange: string\n  /**\n   * payer account ID\n   * @type {number}\n   * @memberof OriginTransferRequestV3\n   */\n  payerId: number\n  /**\n   * payer account address\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  payerAddr: string\n  /**\n   * payee account ID\n   * @type {number}\n   * @memberof OriginTransferRequestV3\n   */\n  payeeId: number\n  /**\n   * payee account address\n   * @type {string}\n   * @memberof OriginTransferRequestV3\n   */\n  payeeAddr: string\n  /**\n   *\n   * @type {TokenVolumeV3}\n   * @memberof OriginTransferRequestV3\n   */\n  token: string\n  amount: string\n  /**\n   *\n   * @type { Pick<TokenVolumeV3,'tokenId'> & {amount:string}}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  feeToken: string\n  maxFeeAmount: string //Pick<TokenVolumeV3, \"tokenId\"> & { amount: string };\n  /**\n   * offchain Id\n   * @type {number}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  storageId: number\n  /**\n   * Timestamp for order to become invalid\n   * @type {number}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  validUntil: number\n  /**\n   * transfer memo\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  memo?: string\n  /**\n   * eddsa signature\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  eddsaSig?: string\n  /**\n   * ecdsa signature\n   * @type {string}\n   * @memberof OriginNFTTransferRequestV3\n   */\n  counterFactualInfo?: CounterFactualInfo\n}\n\nexport type STACKING_PRODUCT = {\n  tokenId: number\n  symbol: string\n  address: string\n  decimals: number\n  status: number\n  apr: string\n  precision: number\n  staked: string\n  rewardPeriod: string\n  minAmount: string\n  maxAmount: string\n}\n\nexport enum StakeStatus {\n  received = 'received',\n  locked = 'locked',\n  partial_unlocked = 'partial_unlocked',\n  completely_unlocked = 'completely_unlocked',\n  failed = 'failed',\n}\n\nexport type StakeInfoOrigin = {\n  accountId: number\n  tokenId: number\n  stakeAt: number\n  createdAt: number\n  updatedAt: number\n  claimableTime: number\n  apr: string\n  lastDayPendingRewards: string\n  initialAmount: string\n  remainAmount: string\n  totalRewards: string\n  productId: string\n  hash: string\n  status: StakeStatus\n}\nexport type STACKING_SUMMARY = {\n  totalStaked: string\n  totalLastDayPendingRewards: string\n  totalStakedRewards: string\n  totalClaimableRewards: string\n  staking: StakeInfoOrigin[]\n}\n\nexport enum StakeTransactionType {\n  subscribe = 'subscribe',\n  redeem = 'redeem',\n  claim = 'claim',\n}\n\nexport type STACKING_TRANSACTIONS = {\n  accountId: number\n  tokenId: number\n  amount: string\n  productId: string\n  hash: string\n  type: StakeTransactionType\n  createdAt: number\n  updatedAt: number\n}\n\nexport interface OriginClaimRequestV3 {\n  accountId: number\n  token: TokenVolumeV3\n  transfer: Omit<OriginTransferRequestV3, 'payeeId' | 'memo'> & {\n    payeeId?: 0\n    memo?: string\n  }\n}\n\nexport type OriginStakeClaimRequestV3 = OriginClaimRequestV3\n\nexport interface OriginClaimRequestV3WithPatch {\n  request: OriginClaimRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport type OriginStakeClaimRequestV3WithPatch = Omit<OriginClaimRequestV3WithPatch, 'request'> & {\n  request: OriginStakeClaimRequestV3\n}\n\nexport interface GetContactsRequest {\n  isHebao: boolean\n  accountId: number\n  limit?: number\n  offset?: number\n}\n\nexport const AddressType = {\n  UNKNOWN_ADDRESS: 0,\n  LOOPRING_HEBAO_CF: 100,\n  // hebao\n  LOOPRING_HEBAO_CONTRACT_1_1_6: 2000,\n  LOOPRING_HEBAO_CONTRACT_1_2_0: 2001,\n  LOOPRING_HEBAO_CONTRACT_2_0_0: 2002,\n  LOOPRING_HEBAO_CONTRACT_2_1_0: 2003,\n  LOOPRING_HEBAO_CONTRACT_2_2_0: 2004,\n  LOOPRING_HEBAO_CONTRACT_3_0_0: 2005,\n  LOOPRING_DEX_EOA: 300,\n  //exchange\n  EXCHANGE_OTHER: 4000,\n  EXCHANGE_BINANCE: 4001,\n  EXCHANGE_OKX: 4002,\n  EXCHANGE_HUOBI: 4003,\n  EXCHANGE_COINBASE: 4004,\n\n  EOA: 5000,\n  EOA_METAMASK: 5001,\n  EOA_COINBASE: 5002,\n  EOA_LEDGER: 5003,\n\n  CONTRACT: 600,\n  OFFICIAL: 200,\n}\nexport type AddressTypeKeys = keyof typeof AddressType\n\nexport interface GetContactsResponse {\n  contacts: {\n    addressType: (typeof AddressType)[AddressTypeKeys]\n    contactAddress: string\n    contactMemo: string\n    contactName: string\n    isFavourite: boolean\n    network: string\n    ownerAccountId: number\n  }[]\n  total: number\n}\n\nexport interface CreateContactRequest {\n  accountId: number\n  isHebao: boolean\n  contactAddress: string\n  contactName: string\n  contactMemo?: string\n  network?: string\n  addressType?: (typeof AddressType)[AddressTypeKeys]\n}\n\nexport interface UpdateContactRequest {\n  contactAddress: string\n  isHebao: boolean\n  accountId: number\n  contactName?: string\n  contactMemo?: string\n  addressType?: (typeof AddressType)[AddressTypeKeys]\n}\n\nexport interface DeleteContactRequest {\n  contactAddress: string\n  isHebao: boolean\n  accountId: number\n  contactName?: string\n  contactMemo?: string\n}\n\nexport type BTRADE_MARKET = {\n  market: string //`LRC-USDT`;\n  baseTokenId: number\n  quoteTokenId: number\n  precisionForPrice: number\n  orderbookAggLevels: number\n  precisionForAmount: number\n  precisionForTotal: number\n  enabled: boolean\n  feeBips: number\n  minAmount: {\n    base: string | ''\n    quote: string | ''\n  }\n  btradeAmount: {\n    base: string | ''\n    quote: string | ''\n  }\n  l2Amount: {\n    base: string | ''\n    quote: string | ''\n  }\n  btradeMarket: string //`${BTRADENAME}LRC-USDT`;\n}\n\nexport interface OriginBTRADEV3OrderRequest {\n  /**\n   * exchange address\n   * @type {string}\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  exchange: string\n  /**\n   * storageId\n   * @type {number}\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  storageId: number\n  /**\n   * accountId\n   * @type {number}\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  accountId: number\n  /**\n   * sellToken\n   * @type TokenVolumeV3\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  sellToken: TokenVolumeV3\n  /**\n   * buyToken\n   * @type TokenVolumeV3\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  buyToken: TokenVolumeV3\n  /**\n   * allOrNone\n   * @description Whether the order supports partial fills or not.Currently only supports false as a valid value\n   * @type boolean\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  allOrNone: Boolean\n  /**\n   * fillAmountBOrS\n   * @type boolean\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  fillAmountBOrS: boolean\n  /**\n   * Timestamp for order become invalid\n   * @type {number}\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  validUntil: number\n  /**\n   * fee\n   * @type {string}\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  maxFeeBips: number\n  /**\n   * The orders EdDSA signature. The signature is a hexadecimal string obtained by signing the order itself and concatenating the resulting signature parts (Rx, Ry, and S). Used to authenticate and authorize the operation.\n   * @type {string}\n   * @memberof OriginBTRADEV3OrderRequest\n   */\n  eddsaSignature?: string\n  clientOrderId: string\n  orderType: OrderTypeResp\n  fastMode: boolean\n}\n\nexport type BtradeResult<R> = {\n  exceedDepth: boolean\n  isAtoB: boolean\n  isReverse: boolean\n  feeBips: string\n  /**\n   *  with decimals\n   */\n  amountS: string | undefined\n  amountBSlipped:\n    | {\n        minReceived: string\n        minReceivedVal: string\n        minimumDecimal: number\n      }\n    | undefined\n  // amountBMiniReceiveCutFee: string | undefined;\n\n  /**\n   *  with decimals\n   */\n  amountB: string | undefined\n  info: R\n  // view\n  sellVol: string | undefined\n  // view\n  buyVol: string | undefined\n}\n\nexport const BTRADENAME = 'BTRADE-'\n\nexport enum LOCK_TYPE {\n  DUAL_CURRENCY = 'DUAL_CURRENCY',\n  DUAL_BASE = 'DUAL_BASE',\n  BTRADE = 'BTRADE',\n  L2STAKING = 'L2STAKING',\n  STOP_LIMIT = 'STOP_LIMIT',\n  VAULT_COLLATERAL = 'VAULT_COLLATERAL',\n  TAIKO_FARMING = 'TAIKO_FARMING',\n}\n\nexport type getUserLockSummaryRequest = {\n  accountId: number\n  tokenId: number\n  lockTags: LOCK_TYPE[]\n}\n\nexport type UserLockSummary = {\n  lockRecord: {\n    amount: string\n    lockTag: string\n    tokenId: number\n  }[]\n}\n\nexport interface GetTotalClaimRequest {\n  accountId: number\n}\n\nexport interface GetUserCrossChainFeeRequest {\n  receiveFeeNetwork: string,\n  calFeeNetwork: string,\n  requestType: number,\n  tokenSymbol?: string,\n  amount?: string,\n  market?: string\n}\n\nexport enum CLAIM_TYPE {\n  PROTOCOL_FEE = 'PROTOCOL_FEE',\n  RECOMMENDER_FEE = 'RECOMMENDER_FEE',\n  REFERER_FEE = 'REFERER_FEE',\n  REBATE_FEE = 'REBATE_FEE',\n  LRC_STAKING = 'LRC_STAKING',\n}\n\nexport type ClaimItem = {\n  tokenId: number\n  claimableInfo: Array<{\n    amount: string\n    claimType: CLAIM_TYPE\n  }>\n}\nexport const VTokenPrefix = 'VAULT'\nexport const VMarketPrefix = 'VAULT-'\n\nexport type VaultToken = Omit<TokenInfo, 'type'> & {\n  type: 'Vault'\n  interestRate: string\n  /**\n   VaultToken Token ID\n   * @type number\n   * @memberof VaultToken\n   */\n  vaultTokenId: number\n  /**\n   *  ERC20 Token ID\n   * @type number\n   * @memberof VaultToken\n   */\n  gasAmounts: any\n  vaultTokenAmounts: {\n    maxAmount: string\n    minAmount: string\n    qtyStepScale: number\n    minLoanAmount: string\n    // bit1:show\n    // bit2:join\n    // bit3:exit\n    // bit4:loan\n    // bit5:repay\n    status: number\n  }\n}\n\nexport type VaultMarket = {\n  market: string\n  wsMarket: string\n  baseTokenId: number\n  quoteTokenId: number\n  precisionForPrice: number\n  orderbookAggLevels: number\n  precisionForAmount: number\n  precisionForTotal: number\n  enabled: true\n  accountId: number\n  address: string\n  feeBips: number\n  minAmount: {\n    base: string\n    quote: string\n  }\n  maxAmount: {\n    base: string\n    quote: string\n  }\n  l2Amount: {\n    base: string\n    quote: string\n  }\n  minTradeAmount: {\n    base: string\n    quote: string\n  }\n  minTradePromptAmount: {\n    base: string\n    quote: string\n  }\n  upSlippageFeeBips: {\n    base: string\n    quote: string\n  }\n  // cefiMarket: LRCUSDT,\n  riskThreshold: number\n  interestThreshold: number\n  priceTolerance: number\n  qtyStepScale: number\n}\n\nexport type VaultAvaiableNFT = {\n  nftTokenInfo: NFTTokenInfo\n  accountId: null\n  tokenId: null\n  nftData: string\n  broker: string\n  brokerId: null\n}\n\nexport type VaultBalance = {\n  accountId: null\n  tokenId: null\n  symbol: string\n  total: string\n  borrowed: string\n  netAsset: string\n  interest: string\n  creditLimit: string\n}\nexport type CollateralInfo = {\n  nftHash: string\n  orderHash: string\n  collateralTokenId: number\n  collateralTokenAmount: string\n  openDate: number\n  nftTokenId: number\n  nftData: string\n}\nexport enum VaultAccountStatus {\n  FREE = 'FREE',\n  IN_STAKING = 'IN_STAKING',\n  IN_REDEEM = 'IN_REDEEM',\n  UNDEFINED = 'UNDEFINED',\n}\nexport type VaultAccountInfo = {\n  accountStatus: VaultAccountStatus\n  marginLevel: string\n  totalBalanceOfUsdt: string\n  totalDebtOfUsdt: string\n  totalEquityOfUsdt: string\n  totalCollateralOfUsdt: string\n  collateralInfo: CollateralInfo\n  maxBorrowableOfUsdt: string\n  userAssets: VaultBalance[]\n  openDate: number\n  leverage: string\n  totalInterestOfUsdt: string\n  totalBorrowedOfUsdt: string\n}\n\nexport enum VaultOperationType {\n  VAULT_OPEN_POSITION = 'VAULT_OPEN_POSITION',\n  VAULT_MARGIN_CALL = 'VAULT_MARGIN_CALL',\n  VAULT_BORROW = 'VAULT_BORROW',\n  VAULT_REPAY = 'VAULT_REPAY',\n  VAULT_TRADE = 'VAULT_TRADE',\n  VAULT_CLOSE_OUT = 'VAULT_CLOSE_OUT',\n  VAULT_CONVERT = 'VAULT_CONVERT',\n  VAULT_JOIN_REDEEM = 'VAULT_JOIN_REDEEM',\n  VAULT_CLOSE_SHORT = 'VAULT_CLOSE_SHORT',\n}\nexport enum VaultOperationEnum {\n  VAULT_OPEN_POSITION,\n  VAULT_MARGIN_CALL,\n  VAULT_BORROW,\n  VAULT_REPAY,\n  VAULT_TRADE,\n  VAULT_CLOSE_OUT,\n}\nexport enum VaultOperationStatus {\n  VAULT_STATUS_EARNING = 'VAULT_STATUS_EARNING',\n  VAULT_STATUS_RECEIVED = 'VAULT_STATUS_RECEIVED',\n  VAULT_STATUS_PROCESSING = 'VAULT_STATUS_PROCESSING',\n  VAULT_STATUS_SUCCEED = 'VAULT_STATUS_SUCCEED',\n  VAULT_STATUS_FAILED = 'VAULT_STATUS_FAILED',\n  VAULT_STATUS_PENDING = 'VAULT_STATUS_PENDING',\n}\n\nexport type VaultOperation = {\n  hash: string\n  operateType: string\n  operateSubType: VaultOperationType\n  status: VaultOperationStatus\n  tokenIn: number\n  amountIn: string\n  tokenOut: number\n  amountOut: string\n  totalBalance: string\n  Collateral: string\n  totalDebt: string\n  totalEquity: string\n  createdAt: number\n  updatedAt: number\n}\nexport type VaultOrder = {\n  hash: string\n  clientOrderId: string\n  status: string\n  tokenS: number\n  amountS: string\n  fillAmountS: string\n  tokenB: number\n  amountB: string\n  fillAmountB: string\n  price: string\n  fee: string\n  createdAt: number\n  updatedAt: number\n}\n\n//Taker order\nexport type VaultJoinRequest = NFTOrderRequestV3 & { joinHash: string }\n//Maker order\nexport type VaultExitRequest = {\n  accountId: number\n  joinHash: string\n  timestamp: number\n}\n\nexport type VaultOrderRequest = OriginBTRADEV3OrderRequest\n\nexport interface VaultOrderResult {\n  hash: string\n  clientOrderId: string\n  status: TxStatus\n  isIdempotent: boolean\n  accountId: number\n  storageId: number\n  tokens: any[]\n}\n\nexport interface VaultOrderNFTRequestV3WithPatch {\n  request: VaultJoinRequest\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface VaultBorrowRequest {\n  accountId: number\n  token: {\n    tokenId: number\n    volume: string\n  }\n  timestamp: number\n}\n\nexport interface VaultRepayRequestV3WithPatch {\n  request: OriginTransferRequestV3\n  web3: Web3\n  chainId: ChainId\n  walletType: ConnectorNames\n  eddsaKey: string\n  apiKey: string\n  isHWAddr?: boolean\n}\n\nexport interface VaultDustCollectorRequest {\n  dustTransfers: {\n    exchange: string\n    payerId: number\n    payerAddr: string\n    payeeId: number\n    payeeAddr: string\n    token: {\n      tokenId: number\n      volume: string\n    }\n    maxFee: {\n      tokenId: number\n      volume: string\n    }\n    storageId: number\n    validUntil: number\n    memo: string\n  }[]\n  eddsaKey: string\n  apiKey: string\n  accountId: number\n}\n\nexport interface DatacenterTokenQuote {\n  price: string\n  volume24H: string\n  volumeChange24H: string\n  percentChange1H: string\n  percentChange24H: string\n  percentChange7D: string\n  percentChange30D: string\n  marketCap: string\n  fullyDilutedMarketCap: string\n}\n\nexport interface GetDatacenterTokenInfoRequest {\n  cmcTokenIds?: number[] | string\n  currency: 'USD'\n}\nexport interface DatacenterTokenInfoSimple {\n  tokenAddress: string\n  symbol: string\n  price: string\n  marketCap: string\n  volume24H: string\n  volumeChange24H: string\n  percentChange24H: string\n  percentChange7D: string\n  tokenId: number\n  cmcRank: number\n  timestamp: number\n}\nexport interface DatacenterTokenInfo {\n  tokenId: number\n  tokenAddress: string\n  name: string\n  symbol: string\n  description: string\n  slug: string\n  logo: string\n  cmcRank: number\n  website: string\n  explorer: string\n  platform: string\n  dateAdded: string\n  dateLaunched: string\n  selfReportedCirculatingSupply: string\n  selfReportedMarketCap: string\n  infiniteSupply: boolean\n  circulatingSupply: string\n  totalSupply: string\n  maxSupply: string\n  quote: DatacenterTokenQuote\n  timestamp: number\n}\nexport enum DatacenterRange {\n  RANGE_ONE_HOUR = 'RANGE_ONE_HOUR',\n  RANGE_ONE_DAY = 'RANGE_ONE_DAY',\n  RANGE_ONE_WEEK = 'RANGE_ONE_WEEK',\n  RANGE_ONE_MONTH = 'RANGE_ONE_MONTH',\n}\nexport enum OHLCVDatacenterRange {\n  OHLCV_RANGE_ONE_DAY = 'OHLCV_RANGE_ONE_DAY',\n  OHLCV_RANGE_ONE_WEEK = 'OHLCV_RANGE_ONE_WEEK',\n  OHLCV_RANGE_ONE_MONTH = 'OHLCV_RANGE_ONE_MONTH',\n  OHLCV_RANGE_ONE_YEAR = 'OHLCV_RANGE_ONE_YEAR',\n  OHLCV_RANGE_ALL = 'OHLCV_RANGE_ALL',\n}\n\nexport interface GetDatacenterTokenQuoteTrendRequest {\n  token?: string\n  cmcTokenId?: number\n  range?: DatacenterRange\n  currency: 'USD'\n}\n\nexport interface GetCmcTokenRelationsRequest {\n  tokenAddresses?: string[] | string\n  cmcTokenIds?: string[] | string\n}\nexport interface GetDatacenterTokenOhlcvQuoteTrendRequest {\n  token?: string\n  cmcTokenId?: number\n  range?: OHLCVDatacenterRange\n  currency: 'USD'\n}\nexport enum GetDatacenterTokenQuoteTrend {\n  timestamp,\n  price,\n  volume24H,\n  volumeChange24H,\n  percentChange1H,\n  percentChange24H,\n  percentChange7D,\n  percentChange30D,\n  marketCap,\n}\nexport enum NotificationMessageType {\n  L1_CREATED = 0, //noweb\n  L2_CREATED = 1,\n  L1_RECEIVE = 2,\n  L1_SEND = 3,\n  L2_RECEIVE = 4,\n  L2_SEND = 5,\n  DEPOSIT = 6,\n  WITHDRAW = 7,\n  GUARDIAN_RECEIVE_PENDING_REQUEST = 8,\n  REQUEST_UPDATED = 9,\n  GUARDIAN_ADDITION = 10,\n  EVENT = 11,\n  L1_CREATING = 12,\n  GUARDIAN_COMMON = 13,\n  PROTECTED_ADD_GUARDIAN_SUCCESS = 14,\n  PROTECTED_ADD_GUARDIAN_REJECTED = 15,\n  PROTECTED_ADD_GUARDIAN_NONCE_FAILED = 16,\n  PROTECTED_REQUEST_APPROVED = 17,\n  PROTECTED_REQUEST_REJECTED = 18,\n  QUOTA_CHANGED_ON_CHAIN_SUCCESS = 19,\n  PROTECTED_REMOVE_GUARDIAN_SUCCESS = 20,\n  ADD_TRUST_ON_CHAIN_SUCCESS = 30,\n  REMOVE_TRUST_ON_CHAIN_SUCCESS = 31,\n  WALLET_LOCKED = 32,\n  WALLET_UNLOCKED = 33,\n  DEAD_LOCK_GUARDIAN = 34,\n  GUARDIAN_SAFETY_CHECK_NOTIFICATION = 35,\n  TAIKO_A3_CREATE = 36,\n  FACING_FORCED_SETTLEMENT = 40,\n  DUAL_SETTLED = 50,\n  DUAL_RECURES_ORDER_SWAP = 51,\n  DUAL_RECURES_RETRY_FAILED = 52,\n  DUAL_RECURES_RETRY_SUCCESS = 53,\n  DUAL_PRICE_ALERT = 54,\n}\nexport type UserNotification = {\n  id: number\n  walletAddress: string\n  network: NetworkWallet\n  messageType: NotificationMessageType | number\n  message: string\n  read: boolean\n  createAt: number\n  redirectionContext: string\n}\nexport type TaikoFarmingAvaiableNFT = {\n  nftTokenInfo: NFTTokenInfo\n  accountId: number\n  tokenId: number\n  nftData: string\n  broker: string\n  brokerId: number\n}\n\nexport interface RabbitWithdrawRequest {\n  fromNetwork: string;\n  toNetwork: string;\n  toAddress: string;\n  transfer: OriginTransferRequestV3\n}\n//\nexport type TaikoFarmingSubmitRequest = NFTOrderRequestV3 & { preOrderHash?: string }\nexport interface TaikoFarmingSubmitOrderNFTRequestV3WithPatch {\n  request: TaikoFarmingSubmitRequest\n  eddsaKey: string\n  apiKey: string\n}"
  },
  {
    "path": "src/defs/loopring_enums.ts",
    "content": "import { RESULT_INFO } from './error_codes'\n\nexport enum ReqMethod {\n  GET = 'GET',\n  POST = 'POST',\n  DELETE = 'DELETE',\n}\n\nexport enum SigPatchField {\n  EddsaSignature = 'eddsaSignature',\n}\n\nexport enum MarketStatus {\n  AMM = 1,\n  ORDER_BOOK = 2,\n  ALL = 3,\n}\n\nexport enum VipCatergory {\n  ORDERBOOK_TRADING_FEES_STABLECOIN = 'ORDERBOOK_TRADING_FEES_STABLECOIN',\n  ORDERBOOK_TRADING_FEES = 'ORDERBOOK_TRADING_FEES',\n  AMM_TRADING_FEES = 'AMM_TRADING_FEES',\n  OTHER_FEES = 'OTHER_FEES',\n}\n\nexport enum TradeChannel {\n  BLANK = '',\n  ORDER_BOOK = 'ORDER_BOOK', // 0\n  AMM_POOL = 'AMM_POOL', // 1\n  MIXED = 'MIXED', // 2\n}\n\nexport enum OrderType {\n  LimitOrder = 'LIMIT_ORDER',\n  TakerOnly = 'TAKER_ONLY',\n  MakerOnly = 'MAKER_ONLY',\n  ClassAmm = 'AMM',\n}\n\nexport enum OrderTypeResp {\n  LimitOrder = 'LIMIT_ORDER',\n  TakerOnly = 'TAKER_ONLY',\n  MakerOnly = 'MAKER_ONLY',\n  ClassAmm = 'CLASS_AMM',\n}\n\nexport enum Currency {\n  usd = 'usd',\n  cny = 'cny',\n}\n\nexport enum OffchainFeeReqType {\n  ORDER = 0,\n  OFFCHAIN_WITHDRAWAL = 1,\n  UPDATE_ACCOUNT = 2,\n  TRANSFER = 3,\n  FAST_OFFCHAIN_WITHDRAWAL = 4,\n  OPEN_ACCOUNT = 5,\n  AMM_EXIT = 6,\n  DEPOSIT = 7,\n  AMM_JOIN = 8,\n  TRANSFER_AND_UPDATE_ACCOUNT = 15,\n  DEFI_JOIN = 21,\n  DEFI_EXIT = 22,\n  FORCE_WITHDRAWAL = 23,\n  EXTRA_TYPES = 24,\n  RABBIT_OFFCHAIN_WITHDRAWAL = 25,\n}\nexport enum OffchainNFTFeeReqType {\n  NFT_MINT = 9,\n  NFT_WITHDRAWAL = 10,\n  NFT_TRANSFER = 11,\n  NFT_DEPLOY = 13,\n  NFT_TRANSFER_AND_UPDATE_ACCOUNT = 19,\n  EXTRA_TYPES = 24,\n}\n\nexport enum TradingInterval {\n  min1 = '1min',\n  min5 = '5min',\n  min15 = '15min',\n  min30 = '30min',\n  hr1 = '1hr',\n  hr2 = '2hr',\n  hr4 = '4hr',\n  hr12 = '12hr',\n  d1 = '1d',\n  w1 = '1w',\n}\n\nexport enum TxStatus {\n  processing = 'processing',\n  processed = 'processed',\n  received = 'received',\n  failed = 'failed',\n}\n\nexport enum OrderStatus {\n  processing = 'processing',\n  processed = 'processed',\n  failed = 'failed',\n  cancelled = 'cancelled',\n  cancelling = 'cancelling',\n  expired = 'expired',\n}\n\nexport enum Side {\n  Buy = 'BUY',\n  Sell = 'SELL',\n}\n\nexport enum WithdrawalTypes {\n  OFFCHAIN_WITHDRAWAL = 'OFFCHAIN_WITHDRAWAL',\n  ONCHAIN_WITHDRAWAL = 'ONCHAIN_WITHDRAWAL',\n  FORCE_WITHDRAWAL = 'FORCE_WITHDRAWAL',\n}\n\nexport enum UserTxTypes {\n  DEPOSIT = 'deposit',\n  TRANSFER = 'transfer',\n  OFFCHAIN_WITHDRAWAL = 'offchain_withdrawal',\n  FORCE_WITHDRAWAL = 'force_withdrawal',\n  DELEGATED_FORCE_WITHDRAW = 'delegated_force_withdraw',\n  SEND_LUCKY_TOKEN = 'send_lucky_token',\n  WITHDRAW_LUCKY_TOKEN = 'withdraw_lucky_token',\n  WITHDRAW = 'onchain_withdrawal',\n  SEND_BACK_LUCKY_TOKEN = 'send_back_lucky_token',\n  DUAL_INVESTMENT = 'dual_investment',\n  L2_STAKING = 'l2_staking',\n  UNIFIED_CLAIM = 'unified_claim',\n  CHANGE_PWD = 'change_pwd',\n}\n\nexport enum UserBillTypes {\n  DEPOSIT = 0,\n  ONCHAIN_WITHDRAWAL = 1,\n  TRANSFER = 2,\n}\n\nexport enum UserNFTTxTypes {\n  DEPOSIT = 'deposit',\n  TRANSFER = 'transfer',\n  WITHDRAW = 'onchain_withdrawal',\n  MINT = 'mint',\n}\n\nexport enum TransferType {\n  transfer = 'transfer',\n  transfer_red = 'transfer_red',\n}\n\nexport enum BillType {\n  ORDER = 'order',\n  DEPOSIT = 'deposit',\n  ONCHAIN_WITHDRAWAL = 'onchain_withdrawal',\n  OFFCHAIN_WITHDRAWAL = 'offchain_withdrawal',\n  TRANSFER = 'transfer',\n  TRANSFER_RED = 'transfer_red',\n}\n\nexport enum FilledType {\n  dex = 'dex',\n  amm = 'amm',\n}\n\nexport enum TxType {\n  TRANSFER = 'TRANSFER',\n  DEPOSIT = 'DEPOSIT',\n  OFFCHAIN_WITHDRAWAL = 'OFFCHAIN_WITHDRAWAL',\n}\n\nexport enum TxNFTType {\n  TRANSFER = 'TRANSFER',\n  DEPOSIT = 'DEPOSIT',\n  WITHDRAW = 'WITHDRAW',\n  ALL = 'ALL',\n  MINT = 'MINT',\n  SEND_LUCKY_TOKEN = 'SEND_LUCKY_TOKEN',\n  WITHDRAW_LUCKY_TOKEN = 'WITHDRAW_LUCKY_TOKEN',\n  SEND_BACK_LUCKY_TOKEN = 'SEND_BACK_LUCKY_TOKEN',\n}\n\nexport enum AmmTxType {\n  JOIN = 'AMM_JOIN',\n  EXIT = 'AMM_EXIT',\n}\n\nexport enum SortOrder {\n  ASC = 0,\n  DESC = 1,\n}\n\nexport enum RuleType {\n  AMM_MINING = 'AMM_MINING',\n  SWAP_VOLUME_RANKING = 'SWAP_VOLUME_RANKING',\n  ORDERBOOK_MINING = 'ORDERBOOK_MINING',\n}\n\nexport enum AmmPoolActivityStatus {\n  NotStarted = 'NotStarted',\n  InProgress = 'InProgress',\n  EndOfGame = 'EndOfGame',\n}\n\nexport enum SIG_FLAG {\n  NO_SIG,\n  EDDSA_SIG,\n  EDDSA_SIG_POSEIDON,\n}\n\nexport enum AssetType {\n  LEVEL_ONE = 0,\n  DEX = 1,\n}\n\nexport enum IntervalType {\n  HOUR = 0,\n  DAY = 1,\n}\n\nexport interface ReqOptions {\n  baseUrl?: string\n  apiKey?: string\n  signature?: string\n\n  url?: string\n}\nexport type TX_HASH_API = { hash?: string; resultInfo?: RESULT_INFO }\nexport interface ReqParams {\n  url: string\n  method: ReqMethod\n  sigFlag: SIG_FLAG\n\n  queryParams?: any\n  bodyParams?: any\n\n  apiKey?: string\n\n  sigObj?: {\n    dataToSig?: any\n    sig?: string\n    sigPatch?: string\n\n    PrivateKey?: string\n\n    owner?: string\n    pwd?: string\n    web3?: any\n    hasDataStruct?: boolean\n  }\n  eddsaSignature?: string\n  ecdsaSignature?: string\n  eddsaSignatureREFER?: boolean\n  extraHeaders?: Record<string, string>\n}\nexport interface PublicKey {\n  /**\n   * The public keys x part.\n   * @type {string}\n   * @memberof PublicKey\n   */\n  x: string\n  /**\n   * The public keys y part.\n   * @type {string}\n   * @memberof PublicKey\n   */\n  y: string\n}\nexport enum NetworkWallet {\n  ETHEREUM = 'ETHEREUM',\n  ARBITRUM = 'ARBITRUM',\n  GOERLI = 'GOERLI',\n  TAIKO = 'TAIKO',\n  SEPOLIA = 'SEPOLIA',\n  TAIKOHEKLA = 'TAIKOHEKLA',\n  BASE = 'BASE',\n  BASESEPOLIA = 'BASESEPOLIA',\n}\n"
  },
  {
    "path": "src/defs/nft_defs.ts",
    "content": "import Web3 from \"web3\";\nimport { ChainId } from \"./web3_defs\";\nimport { NFT_TYPE_STRING, NFTType } from \"../api\";\n\n/**\n *  @interface DepositNFTParam\n *  @description an NFTAction to the specified account.\n *  @property web3\n *  @property DepositParam\n *  @property from The address that deposits the funds to the exchange\n *  @property to The account owner's address receiving the funds\n *  @property nftType The type of NFTAction contract address (ERC721/ERC1155/...)\n *  @property tokenAddress The address of the token\n *  @property nftId The token type 'id`.\n *  @property amount The amount of tokens to deposit.\n *  @property nonce: number,\n *  @property gasPrice: number,\n *  @property gasLimit: number,\n *  @property extraData Optional extra data used by the deposit contract.\n *  @property chainId  0|5\n *  @property sendByMetaMask boolean\n */\nexport interface DepositNFTParam {\n  web3: Web3;\n  from: string;\n  exchangeAddress: string;\n  nftType?: NFTType;\n  tokenAddress: string;\n  nftId: string;\n  amount: number;\n  gasPrice: number;\n  gasLimit: number | undefined;\n  chainId?: ChainId;\n  nonce: number;\n  extraData?: any;\n  sendByMetaMask?: boolean;\n}\n\n/**\n * isApprovedForAll\n * @property web3\n * @property from The address that deposits the funds to the exchange\n * @property exchangeAddress loopring exchange address\n * @property nftType  NFTType\n * @property tokenAddress  The address of NFTAction token\n */\nexport interface IsApproveParam {\n  web3: Web3;\n  from: string;\n  exchangeAddress: string;\n  nftType: NFTType;\n  tokenAddress: string;\n}\n\n/**\n * approveNFT\n * @property web3\n * @property from string address that deposits the funds to the exchange\n * @property to string address  deposits to\n * @property loopringAddress string loopring exchange Address\n * @property nftId  ntId\n * @property chainId number\n * @property nftType number The type of NFTAction contract address (ERC721/ERC1155)\n * @property nonce number\n * @property gasPrice\n * @property gasLimit\n * @property sendByMetaMask\n */\nexport interface ApproveParam {\n  web3: Web3;\n  from: string;\n  depositAddress: string;\n  tokenAddress: string;\n  nftId?: string;\n  nftType: NFTType;\n  gasPrice: number;\n  gasLimit: number | undefined;\n  chainId: ChainId;\n  nonce: number;\n  approved?: boolean;\n  sendByMetaMask?: boolean;\n}\n\nexport type ContractNFTParam = {\n  web3: any;\n  tokenAddress: string;\n  nftId: string;\n  nftType?: NFTType;\n};\nexport type ContractNFTMetaParam = ContractNFTParam & { _id?: string };\n\nexport type UserNFTBalanceParam = ContractNFTParam & { account: string };\n\n\nexport type CallRefreshNFT = {\n  network: \"ETHEREUM\",\n  tokenAddress: string,\n  nftId: string,\n  nftType: NFT_TYPE_STRING\n};\n\n"
  },
  {
    "path": "src/defs/url_defs.ts",
    "content": "export enum LOOPRING_URLs {\n  GET_AVAILABLE_BROKER = '/api/v3/getAvailableBroker',\n  GET_RELAYER_CURRENT_TIME = '/api/v3/timestamp',\n  API_KEY_ACTION = '/api/v3/apiKey', // get update\n  GET_NEXT_STORAGE_ID = '/api/v3/storageId',\n  ORDER_ACTION = '/api/v3/order', // get submit cancel\n  ORDER_CANCEL_HASH_LIST = '/api/v3/orders/byHash', // cancel multiple orders by hashs\n  ORDER_CANCEL_CLIENT_ORDER_ID_LIST = '/api/v3/orders/byClientOrderId', // cancel multiple orders by clientOrderids\n  GET_MULTI_ORDERS = '/api/v3/orders',\n  GET_MARKETS = '/api/v3/exchange/markets',\n  GET_TOKENS = '/api/v3/exchange/tokens',\n  GET_EXCHANGE_INFO = '/api/v3/exchange/info',\n  GET_WITHDRAWAL_AGENTS = '/api/v3/exchange/withdrawalAgents',\n  GET_EXCHANGE_FEEINFO = '/api/v3/exchange/feeInfo',\n  GET_IGNORE_WITHDRAW = '/api/v3/exchange/notWithdrawContractTokens',\n\n  GET_MIX_MARKETS = '/api/v3/mix/markets',\n  GET_DEPTH = '/api/v3/depth',\n  GET_MIX_DEPTH = '/api/v3/mix/depth',\n  GET_TICKER = '/api/v3/ticker',\n  GET_MIX_TICKER = '/api/v3/mix/ticker',\n  GET_CANDLESTICK = '/api/v3/candlestick',\n  GET_MIX_CANDLESTICK = '/api/v3/mix/candlestick',\n  GET_FIAT_PRICE = '/api/v3/price',\n  GET_TRADES = '/api/v3/trade',\n  POST_INTERNAL_TRANSFER = '/api/v3/transfer',\n  ACCOUNT_ACTION = '/api/v3/account', // get or update\n  COUNTER_FACTUAL_INFO = '/api/v3/counterFactualInfo',\n  GET_USER_REG_TXS = '/api/v3/user/createInfo',\n  GET_PWD_RESET_TXS = '/api/v3/user/updateInfo',\n  GET_USER_EXCHANGE_BALANCES = '/api/v3/user/balances',\n  GET_USER_DEPOSITS_HISTORY = '/api/v3/user/deposits',\n  WITHDRAWALS_ACTION = '/api/v3/user/withdrawals', // post get\n  POST_FORCE_WITHDRAWALS = '/api/v3/user/forceWithdrawals',\n\n  GET_USER_TRANSFERS_LIST = '/api/v3/user/transfers',\n  GET_USER_TRADE_HISTORY = '/api/v3/user/trades',\n  GET_USER_TXS = '/api/v3/user/transactions',\n  GET_USER_FEE_RATE = '/api/v3/user/feeRates', // deprecated\n  GET_USER_ORDER_FEE_RATE = '/api/v3/user/orderFee',\n  GET_MINIMAL_ORDER_AMT = '/api/v3/user/orderAmount', // IGNORE for now.\n  GET_MINIMUM_TOKEN_AMT = '/api/v3/user/orderUserRateAmount',\n  GET_OFFCHAIN_FEE_AMT = '/api/v3/user/offchainFee',\n  GET_USER_BILLS = '/api/v3/user/bills',\n  GET_CROSSCHAIN_OFFCHAIN_FEE_AMT = '/api/v3/user/crosschain/offchainFee',\n  GET_ENCRYPTED_ECDSA_KEY = '/api/v3/account/ecdsa/enctypted',\n  POST_ENCRYPTED_ECDSA_KEY = '/api/v3/account/ecdsa/enctypted',\n\n  // Contacts\n  GET_CONTACTS = '/api/v3/user/contact',\n  CREATE_CONTACT = '/api/v3/user/contact/add',\n  UPDATE_CONTACT = '/api/v3/user/contact/update',\n  DELETE_CONTACT = '/api/v3/user/contact',\n\n  // Refer\n  GET_REFER_DOWNSIDES = '/api/v3/user/refer/profit/downsides',\n  GET_REFER_SELF = '/api/v3/user/refer/profit/self',\n  GET_REFER_STATISTIC = '/api/v3/user/refer/statistic',\n\n  // Notification\n  GET_NOTIFICATION_ALL = '/api/v3/user/notification',\n  POST_NOTIFICATION_CLEAR = '/api/v3/user/notification/clearAll',\n  POST_NOTIFICATION_READ_ALL = '/api/v3/user/notification/readAll',\n  POST_NOTIFICATION_READ_ONE = '/api/v3/user/notification/read',\n\n  GET_ALLOWANCES = '/api/v3/eth/allowances',\n  GET_ETH_NONCE = '/api/v3/eth/nonce',\n  GET_ETH_BALANCES = '/api/v3/eth/balances',\n  GET_TOKEN_BALANCES = '/api/v3/eth/tokenBalances',\n  GET_AKK_TOKEN_BALANCES = '/api/v3/eth/tokenBalances/all',\n\n  GET_GAS_PRICE = '/api/v3/eth/recommendedGasPrice',\n  GET_GAS_PRICE_RANGE = '/api/v3/eth/recommendedGasPriceRange',\n\n  GET_RECOMENDED_MARKETS = '/api/v3/exchange/recommended',\n\n  GET_AMM_POOLS_CONF = '/api/v3/amm/pools',\n  GET_AMM_POOLS_SNAPSHOT = '/api/v3/amm/balance',\n  GET_AMM_POOLS_BALANCES = '/api/v3/amm/balances',\n  GET_AMM_POOL_STATS = '/api/v3/amm/poolsStats',\n  POST_JOIN_AMM_POOL = '/api/v3/amm/join',\n  POST_EXIT_AMM_POOL = '/api/v3/amm/exit',\n  GET_AMM_POOL_TXS = '/api/v3/amm/transactions',\n  GET_USER_AMM_POOL_TXS = '/api/v3/amm/user/transactions',\n  GET_AMM_POOL_TRADE_TXS = '/api/v3/amm/trades',\n  GET_AMM_ACTIVITY_RULES = '/api/v3/sidecar/activityRules',\n  GET_AMMPOOL_USER_REWARDS = '/api/v3/amm/user/rewards',\n  GET_AMMPOOL_REWARDS = '/api/v3/amm/rewards',\n  GET_AMMPOOL_GAME_RANK = '/api/v3/game/rank',\n  GET_AMMPOOL_GAME_USER_RANK = '/api/v3/game/user/rank',\n  GET_LIQUIDITY_MINING = '/api/v3/sidecar/liquidityMining',\n  GET_DELEGATE_GET_CODE = '/api/v3/delegator/getCode',\n  GET_DELEGATE_GET_IPFS = '/api/v3/delegator/ipfs',\n  GET_LIQUIDITY_MINING_USER_HISTORY = '/api/v3/sidecar/liquidityMiningUserHistory',\n  GET_PROTOCOL_PORTRAIT = '/api/v3/sidecar/ProtocolPortrait',\n  GET_PROTOCOL_REWARDS = '/api/v3/sidecar/commissionReward',\n  GET_AMM_ASSET_HISTORY = '/api/v3/amm/assets',\n  GET_ASSET_LOCK_RECORDS = '/api/v3/user/lockRecords',\n\n  GET_DEFI_TOKENS = '/api/v3/defi/tokens',\n  GET_DEFI_MARKETS = '/api/v3/defi/markets',\n  POST_DEFI_ORDER = '/api/v3/defi/order',\n  GET_DEFI_REWARDS = '/api/v3/defi/rewards',\n  GET_DEFI_TRANSACTIONS = '/api/v3/defi/transactions',\n\n  SET_REFERRER = '/api/v3/refer',\n\n  GET_WS_KEY = '/v3/ws/key',\n  GET_LATEST_TOKEN_PRICES = '/api/v3/datacenter/getLatestTokenPrices',\n  GET_USER_TRADE_AMOUNT = '/api/v3/datacenter/getUserTradeAmount',\n  GET_SUPPORT_TOKENS = '/api/v3/datacenter/getSupportTokens',\n  GET_QUOTE_TREND = '/api/v3/datacenter/getTokenQuoteTrend',\n  GET_QUOTE_TOKEN_INFO = '/api/v3/datacenter/getTokenInfo',\n  GET_QUOTE_TOKEN_OHLCV_TREND = '/api/v3/datacenter/getTokenOHLCVTrend',\n  GET_QUOTE_TOKEN_GETCMCTOKENRELATIONS = '/api/v3/datacenter/getCmcTokenRelations',\n\n  GET_USER_ASSETS = '/api/wallet/v3/userAssets',\n  GET_TOKEN_PRICES = '/api/wallet/v3/tokenPrices',\n  GET_GUARDIAN_APPROVE_LIST = '/api/wallet/v3/getGuardianApproveList',\n  GET_PROTECTORS = '/api/wallet/v3/getProtects',\n  GET_OPERATION_LOGS = '/api/wallet/v3/operationLogs',\n  GET_HEBAO_CONFIG = '/api/wallet/v3/getAppConfigs',\n  GET_WALLET_TYPE = '/api/wallet/v3/wallet/type',\n  GET_WALLET_MODULES = '/api/wallet/v3/walletModules',\n  GET_WALLET_CONTRACTVERSION = '/api/wallet/v3/contractVersion',\n  RESOLVE_ENS = '/api/wallet/v3/resolveEns',\n  RESOLVE_NAME = '/api/wallet/v3/resolveName',\n  //\n  SUBMIT_APPROVE_SIGNATURE = '/api/wallet/v3/submitApproveSignature',\n  REJECT_APPROVE_SIGNATURE = '/api/wallet/v3/rejectApproveSignature',\n  // OFFICIAL_LOCK_OR_UNLOCK = \"/api/wallet/v3/officialLockOrUnlock\",\n  SEND_META_TX = '/api/wallet/v3/sendMetaTx',\n\n  GET_ACCOUNT_SERVICES = '/api/v3/spi/getAccountServices',\n  // VIP\n  GET_USER_VIP_INFO = '/api/v3/user/vipInfo',\n  GET_USER_VIP_ASSETS = '/api/v3/datacenter/getUserAssets',\n  GET_USER_NFT_BALANCES = '/api/v3/user/nft/balances',\n  GET_USER_NFT_BALANCES_BY_COLLECTION = '/api/v3/user/nft/collection/balances',\n  GET_NFT_OFFCHAIN_FEE_AMT = '/api/v3/user/nft/offchainFee',\n  POST_NFT_INTERNAL_TRANSFER = '/api/v3/nft/transfer',\n  POST_NFT_WITHDRAWALS = '/api/v3/nft/withdrawal',\n  POST_NFT_MINT = '/api/v3/nft/mint',\n  POST_NFT_TRADE = '/api/v3/nft/trade',\n  POST_NFT_VALIDATE_ORDER = '/api/v3/nft/validateOrder', // post get\n  POST_NFT_EDIT_COLLECTION = '/api/v3/nft/collection/edit',\n  POST_NFT_CREATE_LEGACY_COLLECTION = '/api/v3/nft/collection/legacy/tokenAddress',\n  POST_NFT_VALIDATE_REFRESH_NFT = '/api/v3/nft/image/refresh',\n  POST_DEPLOY_COLLECTION = '/api/v3/collection/deployTokenAddress',\n  POST_NFT_LEGACY_UPDATE_COLLECTION = '/api/v3/nft/collection/legacy/updateNftCollection',\n  POST_NFT_UPDATE_NFT_GROUP = '/api/v3/user/nft/updateNftPreference',\n  GET_NFT_COLLECTION = '/api/v3/nft/collection',\n  POST_NFT_CREATE_COLLECTION = '/api/v3/nft/collection',\n  DELETE_NFT_CREATE_COLLECTION = '/api/v3/nft/collection',\n  GET_COLLECTION_WHOLE_NFTS = '/api/v3/nft/public/collection/items',\n  GET_NFT_COLLECTION_PUBLISH = '/api/v3/nft/public/collection',\n  GET_NFT_COLLECTION_HASNFT = '/api/v3/user/collection/details',\n  GET_NFT_LEGACY_COLLECTION = '/api/v3/nft/collection/legacy',\n  GET_NFT_LEGACY_TOKENADDRESS = '/api/v3/nft/collection/legacy/tokenAddress',\n  GET_NFT_LEGACY_BALANCE = '/api/v3/nft/collection/legacy/balance',\n  GET_USER_LOCKSUMMAR = '/api/v3/user/lockSummary',\n  GET_USER_HAD_UNKNOWN_COLLECTION = '/api/v3/nft/collection/unknown',\n\n  GET_NFTs_INFO = '/api/v3/nft/info/nfts',\n  GET_USER_NFT_TRANSFER_HISTORY = '/api/v3/user/nft/transfers',\n  GET_USER_NFT_DEPOSIT_HISTORY = '/api/v3/user/nft/deposits',\n  GET_USER_NFT_WITHDRAW_HISTORY = '/api/v3/user/nft/withdrawals',\n  GET_USER_NFT_TRANSACTION_HISTORY = '/api/v3/user/nft/transactions',\n  GET_USER_NFT_TRADE_HISTORY_OLD = '/api/v3/user/nft/trades',\n  GET_USER_NFT_TRADE_HISTORY = '/api/v3/new/user/nft/trades',\n  GET_USER_NFT_MINT_HISTORY = '/api/v3/user/nft/mints',\n  GET_USER_NFT_BURN_ADDRESS = '/api/v3/datacenter/getNftBurnAddress',\n\n  GET_DEPLOY_TOKEN_ADDRESS = '/api/v3/nft/deployTokenAddress',\n  IPFS_META_URL = 'https://ipfs.loopring.io/ipfs/',\n\n  GET_DUAL_INDEX = '/api/v3/dual/index',\n  GET_DUAL_PRICES = '/api/v3/dual/prices',\n  GET_DUAL_INFOS = '/api/v3/dual/infos',\n  GET_DUAL_TRANSACTIONS = '/api/v3/dual/transactions',\n  GET_DUAL_BALANCE = '/api/v3/dual/balance',\n  GET_DUAL_RULE = '/api/v3/dual/rules',\n  POST_DUAL_ORDER = '/api/v3/dual/order',\n  GET_DUAL_USER_LOCKED = '/api/v3/dual/lockRecordAmount',\n  POST_DUAL_EDIT = '/api/v3/dual/order/reinvest',\n\n  GET_LUCK_TOKEN_AGENTS = '/api/v3/luckyToken/agents',\n  GET_LUCK_TOKEN_AUTHORIZEDSIGNERS = '/api/v3/luckyToken/authorizedSigners',\n  GET_LUCK_TOKEN_CLAIMHISTORY = '/api/v3/luckyToken/user/claimHistory',\n  GET_LUCK_TOKEN_LUCKYTOKENS = '/api/v3/luckyToken/user/luckyTokens',\n  GET_LUCK_TOKEN_LUCKYTOKENDETAIL = '/api/v3/luckyToken/user/luckyTokenDetail',\n  GET_LUCK_TOKEN_BLINDBOXDETAIL = '/api/v3/luckyToken/user/blindBoxDetail',\n  GET_LUCK_TOKEN_WITHDRAWALS = '/api/v3/luckyToken/user/withdraws ',\n  GET_LUCK_TOKEN_BALANCES = '/api/v3/luckyToken/user/balances',\n  GET_LUCK_TOKEN_CLAIMEDLUCKYTOKENS = '/api/v3/luckyToken/user/claimedLuckyTokens',\n  GET_LUCK_TOKEN_CLAIMEDBLINDBOX = '/api/v3/luckyToken/user/claimBlindBoxHistory',\n  GET_LUCK_TOKEN_SUMMARY = '/api/v3/luckyToken/user/summary',\n  GET_LUCK_TOKEN_NFTBALANCES = '/api/v3/luckyToken/user/nftBalances',\n  POST_LUCK_TOKEN_SENDLUCKYTOKEN = '/api/v3/luckyToken/sendLuckyToken',\n  POST_LUCK_TOKEN_CLAIMLUCKYTOKEN = '/api/v3/luckyToken/claimLuckyToken',\n  POST_LUCK_TOKEN_CLAIMBLINDBOX = '/api/v3/luckyToken/claimBlindBox',\n  POST_LUCK_TOKEN_WITHDRAWALS = '/api/v3/luckyToken/user/withdrawals',\n  POST_LUCK_TOKEN_UNCLAIMNFTANDBLINDCNT = '/api/v3/luckyToken/user/unclaimNftAndBlindCnt',\n  GET_LUCK_TOKEN_LUCKYTOKENTARGETS = '/api/v3/luckyToken/user/luckyTokenTargets',\n  POST_LUCK_TOKEN_SUBMITADDTARGET = '/api/v3/luckyToken/submitAddTarget',\n\n  GET_BANXA_API_KEY = '/api/v3/hmacAuthentication',\n  GET_STAKE_PRODUCTS = '/api/v3/stake/products',\n  POST_STAKE_CLAIM = '/api/v3/stake/claim',\n  POST_STAKE = '/api/v3/stake/stake',\n  POST_STAKE_REDEEM = '/api/v3/stake/redeem',\n  GET_STAKE_SUMMARY = '/api/v3/stake/user/summary',\n  GET_STAKE_TRANSACTIONS = '/api/v3/stake/user/transactions',\n\n  // CEFI_MARKETS\n  GET_BTRATE_MARKETS = '/api/v3/btrade/markets',\n  GET_BTRATE_DEPTH = '/api/v3/btrade/depth',\n  GET_BTRATE_ORDERS = '/api/v3/btrade/orders',\n  POST_BTRATE_ORDER = '/api/v3/btrade/order',\n\n  GET_TOTAL_CLAIM_INFO = '/api/v3/claim/totalClaimInfo',\n  POST_TOTAL_CLAIM = '/api/v3/claim/claim',\n  GET_VAULT_TOKENS = '/api/v3/vault/tokens',\n  GET_VAULT_MARKETS = '/api/v3/vault/markets',\n  GET_VAULT_GETAVAILABLENFT = '/api/v3/vault/getAvailableNft',\n  GET_VAULT_ACCOUNT = '/api/v3/vault/account',\n  GET_VAULT_GETOPERATIONS = '/api/v3/vault/getOperations',\n  GET_VAULT_GETOPERATIONBY_HASH = '/api/v3/vault/getOperationByHash',\n  GET_VAULT_INFOS = '/api/v3/vault/infos',\n  GET_VAULT_DEPTH = '/api/v3/vault/depth',\n  GET_VAULT_BALANCE = '/api/v3/vault/balances',\n  POST_VAULT_JOIN = '/api/v3/vault/join',\n  POST_VAULT_ORDER = '/api/v3/vault/order',\n  POST_VAULT_EXIT = '/api/v3/vault/exit',\n  POST_VAULT_TRANSFER = '/api/v3/vault/transfer',\n  POST_VAULT_LOAN = '/api/v3/vault/loan',\n  POST_VAULT_REPAY = '/api/v3/vault/repay',\n  GET_VAULT_PRICE = '/api/v3/vault/tokenPrice',\n  GET_VAULT_CREDIT = '/api/v3/vault/getCredit',\n  GET_VAULT_COLLATERALS = '/api/v3/vault/getCollaterals',\n  GET_VAULT_SUBMIT_LEVERAGE = '/api/v3/vault/submitLeverage',\n  GET_VAULT_SUBMIT_DUST_COLLECTOR = '/api/v3/vault/submitDustCollector',\n  GET_VAULT_GEMAX_BORROWABLE = '/api/v3/vault/getMaxBorrowable',\n  GET_VAULT_CLOSE_SHORT = '/api/v3/vault/closeShort',\n  GET_VAULT_CONFIG = '/api/v3/vault/getConfig',\n\n  GET_DEFI_APYS = '/api/v3/datacenter/getDefiApys',\n  GET_DEFI_STAKE_TRANSACTIONS = '/api/v3/defi/stake/transactions',\n\n  GET_TAIKO_FARMING_POSITION_INFO = '/api/v3/taiko/farming/getPositionInfo',\n  GET_TAIKO_FARMING_TRANSACTIONS = '/api/v3/taiko/farming/transactions',\n  GET_TAIKO_FARMING_USER_SUMMARY = '/api/v3/taiko/farming/user/summary',\n  GET_TAIKO_FARMING_AVAILABLE_NFT = '/api/v3/taiko/farming/getAvailableNft',\n  GET_TAIKO_FARMING_TRANSACTION_BY_HASH = '/api/v3/taiko/farming/getTaikoFarmingTransactionByHash',\n  GET_TAIKO_FARMING_DEPOSIT_DURATION_LIST = '/api/v3/taiko/farming/getDepositDurationList',\n  GET_TAIKO_FARMING_GET_REDEEM ='api/v3/taiko/farming/getRedeem',\n  POST_TAIKO_FARMING_SUMBIT_CLAIM = '/api/v3/taiko/farming/sumbitClaim',\n  \n  GET_RABBIT_WITHDRAW_CONFIG = '/api/v3/rabbitWithdraw/config',\n  GET_NETWORK_WITHDRAWAL_AGENTS = '/api/v3/exchange/networkWithdrawalAgents',\n  POST_RABBIT_WITHDRAW = '/api/v3/rabbitWithdraw',\n}\n"
  },
  {
    "path": "src/defs/web3_defs.ts",
    "content": "export enum ChainId {\n  MAINNET = 1,\n  GOERLI = 5,\n  SEPOLIA = 11155111,\n  TAIKO = 167000,\n  TAIKOHEKLA = 167009,\n  BASE = 8453,\n  BASESEPOLIA = 84532,\n}\n\nexport const NetworkContextName = 'NETWORK'\n\nexport enum ConnectorNames {\n  Unknown = 'Unknown',\n  MetaMask = 'MetaMask',\n  Network = 'Network',\n  WalletConnect = 'WalletConnect',\n  Gamestop = 'Gamestop',\n  OtherExtension = 'OtherExtension',\n  Coinbase = 'Coinbase',\n  Ledger = 'Ledger',\n  Trezor = 'Trezor',\n  Authereum = 'Authereum',\n}\n\nexport enum SigSuffix {\n  Suffix02 = '02',\n  Suffix03 = '03',\n}\n\nexport const NFTFactory = {\n  [ChainId.MAINNET]: '0xc852aC7aAe4b0f0a0Deb9e8A391ebA2047d80026',\n  [ChainId.GOERLI]: '0x355E9941C5e301033ecfD37184E78443c5241035',\n  [ChainId.SEPOLIA]: '0x8cC68c28c7E3d8Eeb1D74434164a1e91aCdA088D',\n  [ChainId.TAIKOHEKLA]: '',\n  [ChainId.TAIKO]: '',\n  [ChainId.BASE]: '',\n  [ChainId.BASESEPOLIA]: '',\n}\n\nexport const NFTFactory_Collection = {\n  [ChainId.MAINNET]: '0x97BE94250AEF1Df307749aFAeD27f9bc8aB911db',\n  [ChainId.GOERLI]: '0x355E9941C5e301033ecfD37184E78443c5241035',\n  [ChainId.SEPOLIA]: '0x8cC68c28c7E3d8Eeb1D74434164a1e91aCdA088D', \n  [ChainId.BASE]: '', \n  [ChainId.BASESEPOLIA]: '',\n}\n"
  },
  {
    "path": "src/defs/ws_defs.ts",
    "content": "import { OrderStatus, Side, NetworkWallet } from './'\n\nexport interface WsProps {\n  topics: any[]\n  needApiKey: boolean\n  apikey?: string\n}\n\nexport enum WsOps {\n  Sub = 'sub',\n  Unsub = 'unSub',\n}\n\nexport enum WsTopicType {\n  account = 'account',\n  order = 'order',\n  trade = 'trade',\n  mixtrade = 'mixtrade',\n  ticker = 'ticker',\n  candlestick = 'candlestick',\n  ammpool = 'ammpool',\n  orderbook = 'orderbook',\n  mixorder = 'mixorder',\n  btradedepth = 'btradedepth',\n  crawlTokenPrices = 'crawltokenprices',\n  notification = 'notification',\n  vaultAccount = 'vaultAccount',\n  l2Common = 'l2Common',\n}\n\nexport const getCrawlTokenPrices = ({\n  topic = WsTopicType.crawlTokenPrices,\n  currency = 'USD',\n}: {\n  topic?: WsTopicType.crawlTokenPrices\n} & Omit<{ currency?: 'USD' }, 'topic'>) => {\n  return { topic, currency }\n}\n\nexport const getAccountArg = () => {\n  return {\n    topic: WsTopicType.account,\n  }\n}\n\nexport interface WsAccount {\n  accountId: number\n  totalAmount: string\n  tokenId: number\n  amountLocked: string\n}\n\nexport const getOrderArg = (market: string) => {\n  return {\n    topic: WsTopicType.order,\n    market,\n  }\n}\n\nexport interface WsOrder {\n  hash: string\n  clientOrderId: string\n  size: string\n  volume: string\n  price: string\n  filledSize: string\n  filledVolume: string\n  filledFee: string\n  status: OrderStatus\n  createdAt: string\n  validSince: string\n  validUntil: string\n  side: Side\n  market: string\n}\n\nexport type OrderWsRequest = {\n  topic?: WsTopicType.orderbook | WsTopicType.mixorder | WsTopicType.btradedepth\n  market: string\n  level: number\n  count?: number\n  snapshot?: boolean\n  showOverlap?: boolean\n}\nexport const getOrderBookArg = ({\n  topic = WsTopicType.orderbook,\n  market,\n  level,\n  count,\n  snapshot,\n  showOverlap,\n}: OrderWsRequest) => {\n  const obj: any = {\n    topic,\n    market,\n    level,\n    count,\n    snapshot,\n    showOverlap,\n  }\n  Object.keys(obj).forEach((key) => (obj[key] === undefined ? delete obj[key] : {}))\n  return obj\n}\n\nexport const getMixOrderArg = ({\n  topic = WsTopicType.mixorder,\n  ...orderWsRequest\n}: { topic?: WsTopicType.mixorder } & Omit<OrderWsRequest, 'topic'>) => {\n  return getOrderBookArg({\n    topic,\n    ...orderWsRequest,\n  })\n}\n\nexport const getBtradeOrderBook = ({\n  topic = WsTopicType.btradedepth,\n  ...orderWsRequest\n}: { topic?: WsTopicType.btradedepth } & Omit<OrderWsRequest, 'topic'>) => {\n  return getOrderBookArg({\n    topic,\n    ...orderWsRequest,\n  })\n}\n\nexport const getTradeArg = (market: string) => {\n  return {\n    topic: WsTopicType.trade,\n    market,\n  }\n}\n\nexport const getMixTradeArg = (market: string) => {\n  return {\n    topic: WsTopicType.mixtrade,\n    market,\n  }\n}\n\nexport const getTickerArg = (market: string) => {\n  return {\n    topic: WsTopicType.ticker,\n    market,\n  }\n}\n\nexport const getCandlestickArg = (market: string) => {\n  return {\n    topic: WsTopicType.candlestick,\n    market,\n  }\n}\n\nexport const getAmmpoolArg = (poolAddress: string) => {\n  return {\n    topic: WsTopicType.ammpool,\n    snapshot: true,\n    poolAddress,\n  }\n}\n\nexport const getNotificationArg = ({\n  address,\n  network,\n}: {\n  address: string\n  network: NetworkWallet\n}) => {\n  return {\n    topic: WsTopicType.notification,\n    address,\n    network,\n  }\n}\n\nexport const getL2Common = ({ address, network }: { address: string; network: NetworkWallet }) => {\n  return {\n    topic: WsTopicType.l2Common,\n    address,\n    network,\n  }\n}\n\nexport enum WS_ACTIONT_YPE {\n  VAULT_ACCOUNT_UPDATE = 'VAULT_ACCOUNT_UPDATE',\n}\nexport interface WsL2Common {\n  accountId: number\n  address: string\n  isUpdated: true\n}\n"
  },
  {
    "path": "src/index.ts",
    "content": "export * from './utils'\nexport * from './defs'\nexport * from './api'\n"
  },
  {
    "path": "src/tests/.eslintrc",
    "content": "{\n  \"root\": true,\n  \"parser\": \"@typescript-eslint/parser\",\n  \"plugins\": [\n    \"@typescript-eslint\"\n  ],\n  \"extends\": [\n    \"plugin:@typescript-eslint/eslint-recommended\",\n    \"plugin:@typescript-eslint/recommended\"\n  ],\n  \"rules\": {\n    \"no-console\": 1 ,\n    // Remember, this means error!\n    \"camelcase\": [\"warn\"],\n    \"@typescript-eslint/no-var-requires\": \"off\",\n    \"no-case-declarations\": \"warn\"\n  }\n}"
  },
  {
    "path": "src/tests/.gitignore",
    "content": "output\n"
  },
  {
    "path": "src/tests/MockData.ts",
    "content": "import {\n  AmmpoolAPI,\n  ExchangeAPI,\n  UserAPI,\n  WalletAPI,\n  WsAPI,\n  NFTAPI,\n  DelegateAPI,\n  GlobalAPI,\n  WhitelistedUserAPI,\n  DefiAPI,\n} from '../api'\nimport Web3 from 'web3'\nimport * as sdk from '../index'\nimport { providers } from 'ethers'\n// import * as PrivateKeyProvider from 'truffle-privatekey-provider'\nconst PrivateKeyProvider = require('truffle-privatekey-provider')\n/***\n * LoopringAPIClass\n */\n// export class LoopringAPIClass {\n//   public static userAPI: UserAPI;\n//   public static exchangeAPI: ExchangeAPI;\n//   public static ammpoolAPI: AmmpoolAPI;\n//   public static walletAPI: WalletAPI;\n//   public static wsAPI: WsAPI;\n//   public static nftAPI: NFTAPI;\n//   public static delegate: DelegateAPI;\n//   public static globalAPI: GlobalAPI;\n//   public static WhitelistedUserAPI: WhitelistedUserAPI;\n//   public static contractAPI: typeof ContractAPI;\n//   public static __chainId__: sdk.ChainId;\n//   public static InitApi = (chainId: sdk.ChainId) => {\n//     LoopringAPI.userAPI = new UserAPI({ chainId });\n//     LoopringAPI.exchangeAPI = new ExchangeAPI({ chainId });\n//     LoopringAPI.globalAPI = new GlobalAPI({ chainId });\n//     LoopringAPI.ammpoolAPI = new AmmpoolAPI({ chainId });\n//     LoopringAPI.walletAPI = new WalletAPI({ chainId });\n//     LoopringAPI.wsAPI = new WsAPI({ chainId });\n//     LoopringAPI.WhitelistedUserAPI = new WhitelistedUserAPI({ chainId });\n//     LoopringAPI.nftAPI = new NFTAPI({ chainId });\n//     LoopringAPI.delegate = new DelegateAPI({ chainId });\n//     LoopringAPI.__chainId__ = chainId;\n//     LoopringAPI.contractAPI = ContractAPI;\n//   };\n// }\n// LoopringAPIClass.InitApi({sdk.ChainId.GOERLI})\n\nexport const DEFAULT_TIMEOUT = 30000\n// @ts-ignore\nglobal.ethereum = {}\nconst chainId = sdk.ChainId.GOERLI\nconst baseUrl = 'https://dev.loopring.io' // 'uat2.loopring.io'\nexport const LoopringAPI = {\n  // second params is http request timeout default is 6000\n  userAPI: new UserAPI({ chainId, baseUrl }, 6000),\n  exchangeAPI: new ExchangeAPI({ chainId, baseUrl }),\n  globalAPI: new GlobalAPI({ chainId, baseUrl }),\n  ammpoolAPI: new AmmpoolAPI({ chainId, baseUrl }),\n  walletAPI: new WalletAPI({ chainId, baseUrl }),\n  wsAPI: new WsAPI({ chainId, baseUrl }),\n  whitelistedUserAPI: new WhitelistedUserAPI({ chainId, baseUrl }),\n  nftAPI: new NFTAPI({ chainId, baseUrl }),\n  defiAPI: new DefiAPI({ chainId, baseUrl }),\n  delegate: new DelegateAPI({ chainId, baseUrl }),\n  __chainId__: chainId,\n}\nexport const LOOPRING_EXPORTED_ACCOUNT = {\n  uatNFTFactory: '0x355E9941C5e301033ecfD37184E78443c5241035',\n  devNFTFactory: '0x85829dD619f11129e8ea08764F0E1A021aD579B9',\n  address: '0x727e0fa09389156fc803eaf9c7017338efd76e7f',\n  privateKey: '491aecdb1d5f6400a6b62fd12a41a86715bbab675c37a4060ba115fecf94083c',\n  accountId: 10149, //UAT   10037,\n  address2: '0xb6d8c39D5528357dBCe6BEd82aC71c74e9D19079',\n  privateKey2: 'e020ed769032ba95d9a5207687a663d6198fe2f5cedf28a250f7cbd8c81a5263',\n  accountId2: 10395,\n  addressCF: '0x23dE4Da688c94a66E8bbE9BCc95CB03b4e209C15',\n  accountIdCF: 11632,\n  addressContractWallet: '0xD4BD7c71B6d4A09217ccc713f740d6ed8f4EA0cd',\n  depositAddress: '0x4E8e6a86762546cCfCBaa8A259c7d442383c5127',\n  exchangeAddress: '0xC7CcB943782aBC702C014EfA9F99cF84FaDE6Cb9', //UAT '0x12b7cccF30ba360e5041C6Ce239C9a188B709b2B',\n  whitelistedAddress: '0x35405E1349658BcA12810d0f879Bf6c5d89B512C',\n  whitelistedEddkey: '0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33',\n  // const eddkeyWhitelisted =\n  //   \"0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\";\n  //   apiKey: \"2PYgTOZwXHkPXtJMlOMG06ZX1QKJInpoky6iYIbtMgmkbfdL4PvxyEOj0LPOfgYX\",\n  chainId: 5,\n  nftTokenAddress: '0x202a3057310f33d9ae4d2b0c650e93d2b2172d6b',\n  nftTokenId: 32768,\n  nftId: '0x8590625e520c6da9a84b261332ce4c9ccc46955f3eb0f5e5fd5a5973efa4c7d1',\n  nftData: '0x249df421b4b2f3ec2efb3f16614c04695217509ef442e54c87b7dd065b7f1955',\n  testNotOx: '60412713752920209836220633720062444896781011774580807407425243696918755067857n',\n  // nftTokenAddress: '0x1e29fd62ee556ee6bb9494faab32b6f269ebb4bf',\n  // nftTokenId: 32768,\n  // nftId: '0xfed3c4c4e2e1471c3f457a7ee9780ae3c77ee7e05ac77bf573ccd5145db7c674',     //UAT\n  // nftData: '0x0e5542cc682fae472f0f9909573244551e56ad25da62a82a1e18f28d0f392147',\n  // testNotOx: '727e0fa09389156fc803eaf9c7017338efd76e7f',\n  tradeLRCValue: 80000000000000,\n  tradeETHValue: 0.0001, //same as UI\n  gasPrice: 20, // for test\n  gasLimit: 200000, // for test\n  validUntil: Math.round(Date.now() / 1000) + 30 * 86400,\n}\n\nconst provider = new PrivateKeyProvider(\n  LOOPRING_EXPORTED_ACCOUNT.privateKey,\n  'https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3',\n)\nconst provider2 = new PrivateKeyProvider(\n  LOOPRING_EXPORTED_ACCOUNT.privateKey2,\n  'https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3',\n)\n// const providerWhiteList = new PrivateKeyProvider(\n//   LOOPRING_EXPORTED_ACCOUNT.whitelistedEddkey,\n//   \"https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3\"\n// );\nexport const web3 = new Web3(provider)\nexport const web3_2 = new Web3(provider2)\n\nexport const CUSTOMER_KEY_SEED = 'XXXXXX' + ' with key nonce: ' + '${nonce}'\n\n// LoopringAPI.exchangeAPI.getTokens()\n// const {markets:marketMap} LoopringAPI.exchangeAPI?.getMixMarkets()\nexport let TOKEN_INFO = {\n  addressIndex: {\n    '0x0000000000000000000000000000000000000000': 'ETH',\n    '0xfc28028d9b1f6966fe74710653232972f50673be': 'LRC',\n    '0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a': 'USDT',\n    '0xfeb069407df0e1e4b365c10992f1bc16c078e34b': 'LP-LRC-ETH',\n    '0x049a02fa9bc6bd54a2937e67d174cc69a9194f8e': 'LP-ETH-USDT',\n    '0xcd2c81b322a5b530b5fa3432e57da6803b0317f7': 'DAI',\n    '0x47525e6a5def04c9a56706e93f54cc70c2e8f165': 'USDC',\n    '0xf37cf4ced77b985708d591acc6bfd08586ab3409': 'LP-USDC-ETH',\n  },\n  tokenMap: {\n    ETH: {\n      type: 'ETH',\n      tokenId: 0,\n      symbol: 'ETH',\n      name: 'Ethereum',\n      address: '0x0000000000000000000000000000000000000000',\n      decimals: 18,\n      precision: 7,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '5000000000000000',\n        maximum: '1000000000000000000000',\n        dust: '200000000000000',\n      },\n      luckyTokenAmounts: {\n        minimum: '50000000000000',\n        maximum: '1000000000000000000000',\n        dust: '50000000000000',\n      },\n      fastWithdrawLimit: '100000000000000000000',\n      gasAmounts: {\n        distribution: '85000',\n        deposit: '100000',\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: ['LRC', 'USDT', 'USDC'],\n    },\n    LRC: {\n      type: 'erc20Trade',\n      tokenId: 1,\n      symbol: 'LRC',\n      name: 'Loopring',\n      address: '0xfc28028d9b1f6966fe74710653232972f50673be',\n      decimals: 18,\n      precision: 3,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '5000000000000000000',\n        maximum: '5000000000000000000000000',\n        dust: '5000000000000000000',\n      },\n      luckyTokenAmounts: {\n        minimum: '50000000000000000',\n        maximum: '5000000000000000000000000',\n        dust: '50000000000000000',\n      },\n      fastWithdrawLimit: '750000000000000000000000',\n      gasAmounts: {\n        distribution: '101827',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: ['ETH'],\n    },\n    USDT: {\n      type: 'erc20Trade',\n      tokenId: 2,\n      symbol: 'USDT',\n      name: 'USDT',\n      address: '0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a',\n      decimals: 6,\n      precision: 2,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '5000000',\n        maximum: '2000000000000',\n        dust: '250000',\n      },\n      luckyTokenAmounts: {\n        minimum: '50000',\n        maximum: '200000000000',\n        dust: '50000',\n      },\n      fastWithdrawLimit: '250000000000',\n      gasAmounts: {\n        distribution: '106233',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: ['ETH', 'DAI'],\n    },\n    'LP-LRC-ETH': {\n      type: 'erc20Trade',\n      tokenId: 4,\n      symbol: 'LP-LRC-ETH',\n      name: 'AMM-LRC-ETH',\n      address: '0xfeb069407df0e1e4b365c10992f1bc16c078e34b',\n      decimals: 8,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '100000000',\n        maximum: '10000000000000000000',\n        dust: '100000000',\n      },\n      luckyTokenAmounts: {\n        minimum: '100000000',\n        maximum: '10000000000000000000',\n        dust: '100000000',\n      },\n      fastWithdrawLimit: '20000000000',\n      gasAmounts: {\n        distribution: '150000',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n    'LP-ETH-USDT': {\n      type: 'erc20Trade',\n      tokenId: 7,\n      symbol: 'LP-ETH-USDT',\n      name: 'LP-ETH-USDT',\n      address: '0x049a02fa9bc6bd54a2937e67d174cc69a9194f8e',\n      decimals: 8,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '100000000',\n        maximum: '10000000000000',\n        dust: '100000000',\n      },\n      luckyTokenAmounts: {\n        minimum: '100000000',\n        maximum: '10000000000000',\n        dust: '100000000',\n      },\n      fastWithdrawLimit: '20000000000',\n      gasAmounts: {\n        distribution: '150000',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n    DAI: {\n      type: 'erc20Trade',\n      tokenId: 6,\n      symbol: 'DAI',\n      name: 'dai',\n      address: '0xcd2c81b322a5b530b5fa3432e57da6803b0317f7',\n      decimals: 18,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '10000000000000000000',\n        maximum: '100000000000000000000000',\n        dust: '10000000000000000',\n      },\n      luckyTokenAmounts: {\n        minimum: '10000000000000000000',\n        maximum: '100000000000000000000000',\n        dust: '10000000000000000000',\n      },\n      fastWithdrawLimit: '10000000000000000000000',\n      gasAmounts: {\n        distribution: '150000',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: ['USDT'],\n    },\n    USDC: {\n      type: 'USDC',\n      tokenId: 8,\n      symbol: 'USDC',\n      name: 'USDC',\n      address: '0x47525e6a5def04c9a56706e93f54cc70c2e8f165',\n      decimals: 6,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '1000',\n        maximum: '10000000000000000000',\n        dust: '100',\n      },\n      luckyTokenAmounts: {\n        minimum: '1000000',\n        maximum: '10000000000',\n        dust: '1000000',\n      },\n      fastWithdrawLimit: '20000000000000000000',\n      gasAmounts: {\n        distribution: '150000',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: ['ETH'],\n    },\n    'LP-USDC-ETH': {\n      type: 'LP-USDC-ETH',\n      tokenId: 9,\n      symbol: 'LP-USDC-ETH',\n      name: 'LP-USDC-ETH',\n      address: '0xf37cf4ced77b985708d591acc6bfd08586ab3409',\n      decimals: 8,\n      precision: 7,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: '100000',\n        maximum: '1000000000000000000000000000000000000000',\n        dust: '10000',\n      },\n      luckyTokenAmounts: {\n        minimum: '1000000000000000',\n        maximum: '10000000000000000000',\n        dust: '1000000000000000',\n      },\n      fastWithdrawLimit: '20000000000000000000',\n      gasAmounts: {\n        distribution: '150000',\n        deposit: '200000',\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n  },\n  idIndex: {\n    '0': 'ETH',\n    '1': 'LRC',\n    '2': 'USDT',\n    '4': 'LP-LRC-ETH',\n    '6': 'DAI',\n    '7': 'LP-ETH-USDT',\n    '8': 'USDC',\n    '9': 'LP-USDC-ETH',\n  },\n  marketMap: {\n    'LRC-ETH': {\n      baseTokenId: 1,\n      enabled: true,\n      market: 'LRC-ETH',\n      orderbookAggLevels: 5,\n      precisionForPrice: 6,\n      quoteTokenId: 0,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1617967800000,\n    },\n    'ETH-USDT': {\n      baseTokenId: 0,\n      enabled: true,\n      market: 'ETH-USDT',\n      orderbookAggLevels: 3,\n      precisionForPrice: 3,\n      quoteTokenId: 2,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1617972300000,\n    },\n    'DAI-USDT': {\n      baseTokenId: 6,\n      enabled: true,\n      market: 'DAI-USDT',\n      orderbookAggLevels: 2,\n      precisionForPrice: 4,\n      quoteTokenId: 2,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 0,\n    },\n    'USDC-ETH': {\n      baseTokenId: 8,\n      enabled: true,\n      market: 'USDC-ETH',\n      orderbookAggLevels: 3,\n      precisionForPrice: 3,\n      quoteTokenId: 0,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1636974420000,\n    },\n  },\n}\n\n// const {} = LoopringAPI.ammpoolAPI?.getAmmPoolConf())\nexport let AMM_MAP = {\n  'AMM-LRC-ETH': {\n    name: 'LRCETH-Pool',\n    market: 'AMM-LRC-ETH',\n    address: '0xfEB069407df0e1e4B365C10992F1bc16c078E34b',\n    version: '1.0.0',\n    tokens: { pooled: [1, 0], lp: 4 },\n    feeBips: 20,\n    precisions: { price: 6, amount: 5 },\n    createdAt: '1617967800000',\n    status: 31,\n  },\n  'AMM-ETH-USDT': {\n    name: 'AMM-ETH-USDT',\n    market: 'AMM-ETH-USDT',\n    address: '0x049a02FA9bc6bd54a2937E67D174cc69a9194f8e',\n    version: '1.0.0',\n    tokens: { pooled: [0, 2], lp: 7 },\n    feeBips: 20,\n    precisions: { price: 3, amount: 3 },\n    createdAt: '1617972300000',\n    status: 31,\n  },\n  'AMM-USDC-ETH': {\n    name: 'AMM-USDC-ETH',\n    market: 'AMM-USDC-ETH',\n    address: '0xf37cf4CEd77b985708D591AcC6BfD08586Ab3409',\n    version: '1.0.0',\n    tokens: {\n      pooled: [8, 0],\n      lp: 9,\n    },\n    feeBips: 20,\n    precisions: {\n      price: 3,\n      amount: 4,\n    },\n    createdAt: '1636974420000',\n    status: 0,\n  },\n}\n\nexport const testTypedData = {\n  types: {\n    EIP712Domain: [\n      { name: 'name', type: 'string' },\n      { name: 'version', type: 'string' },\n      { name: 'chainId', type: 'uint256' },\n      { name: 'verifyingContract', type: 'address' },\n    ],\n    TestTypedData: [\n      { name: 'from', type: 'address' },\n      { name: 'to', type: 'address' },\n      { name: 'tokenID', type: 'uint16' },\n    ],\n  },\n  primaryType: 'TestTypedData',\n  domain: {\n    name: 'Loopring Protocol',\n    version: '3.6.0',\n    chainId: sdk.ChainId.GOERLI,\n    verifyingContract: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  },\n  message: {\n    from: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address2,\n    tokenID: TOKEN_INFO.tokenMap.LRC.tokenId,\n  },\n}\n\nexport async function signatureKeyPairMock(accInfo: sdk.AccountInfo, _web3: Web3 = web3) {\n  //@ts-ignore\n  global.ethereum = providers?.EtherscanProvider\n  // console.log('accInfo', accInfo)\n  //@ts-ignore\n  const eddsaKey = await sdk.generateKeyPair({\n    web3: _web3,\n    address: accInfo.owner,\n    keySeed:\n      !accInfo.keySeed && accInfo.keySeed == ''\n        ? sdk.GlobalAPI.KEY_MESSAGE.replace(\n            '${exchangeAddress}',\n            LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          ).replace('${nonce}', (accInfo.nonce - 1).toString())\n        : accInfo.keySeed,\n    walletType: sdk.ConnectorNames.MetaMask,\n    chainId: sdk.ChainId.GOERLI,\n  })\n  return eddsaKey\n}\n"
  },
  {
    "path": "src/tests/MockSwapData.ts",
    "content": "//Default config value from getTokens & getMixMarkets\nimport * as sdk from \"../index\";\n\nexport const marketArray = [\"LRC-ETH\"];\nexport const marketMap = {\n  \"LRC-ETH\": {\n    baseTokenId: 1,\n    enabled: true,\n    market: \"LRC-ETH\",\n    orderbookAggLevels: 5,\n    precisionForPrice: 6,\n    quoteTokenId: 0,\n    status: 3,\n    isSwapEnabled: true,\n    createdAt: 1617967800000,\n  },\n};\n//v3/mix/depth?level=0&limit=50&market=LRC-ETH\nexport const deepMock = {\n  symbol: \"LRC-ETH\",\n  version: 23249677,\n  timestamp: 1655719492365,\n  mid_price: 0.00033248,\n  bids: [\n    {\n      price: 0.00030689,\n      amt: \"12041160324514792497908\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"618450503644320209925641\",\n      volTotal: \"198539605794234049017\",\n    },\n    {\n      price: 0.00030752,\n      amt: \"12016302126785109160251\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"606409343319805417427733\",\n      volTotal: \"194844233461662963807\",\n    },\n    {\n      price: 0.00030816,\n      amt: \"11991520826895479525387\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"594393041193020308267482\",\n      volTotal: \"191148861129091878597\",\n    },\n    {\n      price: 0.00030881,\n      amt: \"12329062048917727073625\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"582401520366124828742095\",\n      volTotal: \"187453488796520793387\",\n    },\n    {\n      price: 0.00030945,\n      amt: \"11941442525358097768419\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"570072458317207101668470\",\n      volTotal: \"183646135484174826807\",\n    },\n    {\n      price: 0.0003102,\n      amt: \"3223726000000000000000\",\n      vol: \"999999805200000000\",\n      amtTotal: \"558131015791849003900051\",\n      volTotal: \"179950763151603741597\",\n    },\n    {\n      price: 0.0003104,\n      amt: \"11904963012947201084062\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"554907289791849003900051\",\n      volTotal: \"178950763346403741597\",\n    },\n    {\n      price: 0.00031072,\n      amt: \"11892800074855146120151\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"543002326778901802815989\",\n      volTotal: \"175255391013832656387\",\n    },\n    {\n      price: 0.00031137,\n      amt: \"12227667622887455762012\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"531109526704046656695838\",\n      volTotal: \"171560018681261571177\",\n    },\n    {\n      price: 0.00031202,\n      amt: \"11843337524732768607817\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"518881859081159200933826\",\n      volTotal: \"167752665368915604597\",\n    },\n    {\n      price: 0.00031266,\n      amt: \"11819088718260537718160\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"507038521556426432326009\",\n      volTotal: \"164057293036344519387\",\n    },\n    {\n      price: 0.0003133,\n      amt: \"11794914308461194855590\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"495219432838165894607849\",\n      volTotal: \"160361920703773434177\",\n    },\n    {\n      price: 0.00031395,\n      amt: \"12127129883064173669497\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"483424518529704699752259\",\n      volTotal: \"156666548371202348967\",\n    },\n    {\n      price: 0.0003146,\n      amt: \"11746060536480763829870\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"471297388646640526082762\",\n      volTotal: \"152859195058856382387\",\n    },\n    {\n      price: 0.00031524,\n      amt: \"11722109721002274877424\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"459551328110159762252892\",\n      volTotal: \"149163822726285297177\",\n    },\n    {\n      price: 0.0003159,\n      amt: \"12052351993023897680738\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"447829218389157487375468\",\n      volTotal: \"145468450393714211967\",\n    },\n    {\n      price: 0.00031655,\n      amt: \"11673707113082743010268\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"435776866396133589694730\",\n      volTotal: \"141661097081368245387\",\n    },\n    {\n      price: 0.00031699,\n      amt: \"615000000000000000000\",\n      vol: \"194954999999999949\",\n      amtTotal: \"424103159283050846684462\",\n      volTotal: \"137965724748797160177\",\n    },\n    {\n      price: 0.00031719,\n      amt: \"11649977142974837964110\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"423488159283050846684462\",\n      volTotal: \"137770769748797160228\",\n    },\n    {\n      price: 0.00031784,\n      amt: \"11626319455782556517212\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"411838182140076008720352\",\n      volTotal: \"134075397416226075018\",\n    },\n    {\n      price: 0.0003185,\n      amt: \"11953964321007990024755\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"400211862684293452203140\",\n      volTotal: \"130380025083654989808\",\n    },\n    {\n      price: 0.00031934,\n      amt: \"11571837200722111826863\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"388257898363285462178385\",\n      volTotal: \"126572671771309023228\",\n    },\n    {\n      price: 0.00031979,\n      amt: \"11555429099390519988949\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"376686061162563350351522\",\n      volTotal: \"122877299438737938018\",\n    },\n    {\n      price: 0.00032,\n      amt: \"300000000000000000000\",\n      vol: \"96000000000000000\",\n      amtTotal: \"365130632063172830362573\",\n      volTotal: \"119181927106166852808\",\n    },\n    {\n      price: 0.00032044,\n      amt: \"11532058329906875386268\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"364830632063172830362573\",\n      volTotal: \"119085927106166852808\",\n    },\n    {\n      price: 0.0003211,\n      amt: \"11857145662584872212009\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"353298573733265954976305\",\n      volTotal: \"115390554773595767598\",\n    },\n    {\n      price: 0.00032176,\n      amt: \"11484826169666631095087\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"341441428070681082764296\",\n      volTotal: \"111583201461249801018\",\n    },\n    {\n      price: 0.00032241,\n      amt: \"11461669156035188891431\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"329956601901014451669209\",\n      volTotal: \"107887829128678715808\",\n    },\n    {\n      price: 0.00032294,\n      amt: \"22266286128259997368320\",\n      vol: \"7190674442260284416\",\n      amtTotal: \"318494932744979262777778\",\n      volTotal: \"104192456796107630598\",\n    },\n    {\n      price: 0.00032307,\n      amt: \"11784846142950476791130\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"296228646616719265409458\",\n      volTotal: \"97001782353847346182\",\n    },\n    {\n      price: 0.00032333,\n      amt: \"31042151210389998665728\",\n      vol: \"10037169172367501312\",\n      amtTotal: \"284443800473768788618328\",\n      volTotal: \"93194429041501379602\",\n    },\n    {\n      price: 0.00032354,\n      amt: \"19082720347089998446592\",\n      vol: \"6174214168300968960\",\n      amtTotal: \"253401649263378789952600\",\n      volTotal: \"83157259869133878290\",\n    },\n    {\n      price: 0.00032373,\n      amt: \"11414868337793698506576\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"234318928916288791506008\",\n      volTotal: \"76983045700832909330\",\n    },\n    {\n      price: 0.00032438,\n      amt: \"11391922481177051106050\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"222904060578495092999432\",\n      volTotal: \"73287673368261824120\",\n    },\n    {\n      price: 0.00032503,\n      amt: \"11369045742792164433715\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"211512138097318041893382\",\n      volTotal: \"69592301035690738910\",\n    },\n    {\n      price: 0.00032512,\n      amt: \"7101984539779999465472\",\n      vol: \"2308997213573273600\",\n      amtTotal: \"200143092354525877459667\",\n      volTotal: \"65896928703119653700\",\n    },\n    {\n      price: 0.0003257,\n      amt: \"11689707913498419991686\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"193041107814745877994195\",\n      volTotal: \"63587931489546380100\",\n    },\n    {\n      price: 0.00032636,\n      amt: \"11322810509578528739940\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"181351399901247458002509\",\n      volTotal: \"59780578177200413520\",\n    },\n    {\n      price: 0.00032702,\n      amt: \"11300141532643741902081\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"170028589391668929262569\",\n      volTotal: \"56085205844629328310\",\n    },\n    {\n      price: 0.00032709,\n      amt: \"1511898000000000000000\",\n      vol: \"494541835799999898\",\n      amtTotal: \"158728447859025187360488\",\n      volTotal: \"52389833512058243100\",\n    },\n    {\n      price: 0.00032767,\n      amt: \"11277540564700637960582\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"157216549859025187360488\",\n      volTotal: \"51895291676258243202\",\n    },\n    {\n      price: 0.00032838,\n      amt: \"11594014901713773553177\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"145939009294324549399906\",\n      volTotal: \"48199919343687157992\",\n    },\n    {\n      price: 0.00032899,\n      amt: \"11232203228917728004878\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"134344994392610775846729\",\n      volTotal: \"44392566031341191412\",\n    },\n    {\n      price: 0.00032959,\n      amt: \"31100749000000000753664\",\n      vol: \"10250806870400000000\",\n      amtTotal: \"123112791163693047841851\",\n      volTotal: \"40697193698770106202\",\n    },\n    {\n      price: 0.00032965,\n      amt: \"11209805337410429375102\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"92012042163693047088187\",\n      volTotal: \"30446386828370106202\",\n    },\n    {\n      price: 0.00033031,\n      amt: \"11187474373893810850495\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"80802236826282617713085\",\n      volTotal: \"26751014495799020992\",\n    },\n    {\n      price: 0.00033098,\n      amt: \"11503202913004006553102\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"69614762452388806862590\",\n      volTotal: \"23055642163227935782\",\n    },\n    {\n      price: 0.00033099,\n      amt: \"26515451000000002129920\",\n      vol: \"8776614281000000512\",\n      amtTotal: \"58111559539384800309488\",\n      volTotal: \"19248288850881969202\",\n    },\n    {\n      price: 0.0003313,\n      amt: \"20499506300000000802816\",\n      vol: \"6791486437190000640\",\n      amtTotal: \"31596108539384798179568\",\n      volTotal: \"10471674569881968690\",\n    },\n    {\n      price: 0.00033165,\n      amt: \"11096602239384797376752\",\n      vol: \"3680188132691968050\",\n      amtTotal: \"11096602239384797376752\",\n      volTotal: \"3680188132691968050\",\n    },\n  ],\n  bids_prices: [\n    0.00030689, 0.00030752, 0.00030816, 0.00030881, 0.00030945, 0.0003102,\n    0.0003104, 0.00031072, 0.00031137, 0.00031202, 0.00031266, 0.0003133,\n    0.00031395, 0.0003146, 0.00031524, 0.0003159, 0.00031655, 0.00031699,\n    0.00031719, 0.00031784, 0.0003185, 0.00031934, 0.00031979, 0.00032,\n    0.00032044, 0.0003211, 0.00032176, 0.00032241, 0.00032294, 0.00032307,\n    0.00032333, 0.00032354, 0.00032373, 0.00032438, 0.00032503, 0.00032512,\n    0.0003257, 0.00032636, 0.00032702, 0.00032709, 0.00032767, 0.00032838,\n    0.00032899, 0.00032959, 0.00032965, 0.00033031, 0.00033098, 0.00033099,\n    0.0003313, 0.00033165,\n  ],\n  bids_amtTotals: [\n    \"618450503644320209925641\",\n    \"606409343319805417427733\",\n    \"594393041193020308267482\",\n    \"582401520366124828742095\",\n    \"570072458317207101668470\",\n    \"558131015791849003900051\",\n    \"554907289791849003900051\",\n    \"543002326778901802815989\",\n    \"531109526704046656695838\",\n    \"518881859081159200933826\",\n    \"507038521556426432326009\",\n    \"495219432838165894607849\",\n    \"483424518529704699752259\",\n    \"471297388646640526082762\",\n    \"459551328110159762252892\",\n    \"447829218389157487375468\",\n    \"435776866396133589694730\",\n    \"424103159283050846684462\",\n    \"423488159283050846684462\",\n    \"411838182140076008720352\",\n    \"400211862684293452203140\",\n    \"388257898363285462178385\",\n    \"376686061162563350351522\",\n    \"365130632063172830362573\",\n    \"364830632063172830362573\",\n    \"353298573733265954976305\",\n    \"341441428070681082764296\",\n    \"329956601901014451669209\",\n    \"318494932744979262777778\",\n    \"296228646616719265409458\",\n    \"284443800473768788618328\",\n    \"253401649263378789952600\",\n    \"234318928916288791506008\",\n    \"222904060578495092999432\",\n    \"211512138097318041893382\",\n    \"200143092354525877459667\",\n    \"193041107814745877994195\",\n    \"181351399901247458002509\",\n    \"170028589391668929262569\",\n    \"158728447859025187360488\",\n    \"157216549859025187360488\",\n    \"145939009294324549399906\",\n    \"134344994392610775846729\",\n    \"123112791163693047841851\",\n    \"92012042163693047088187\",\n    \"80802236826282617713085\",\n    \"69614762452388806862590\",\n    \"58111559539384800309488\",\n    \"31596108539384798179568\",\n    \"11096602239384797376752\",\n  ],\n  bids_volTotals: [\n    \"198539605794234049017\",\n    \"194844233461662963807\",\n    \"191148861129091878597\",\n    \"187453488796520793387\",\n    \"183646135484174826807\",\n    \"179950763151603741597\",\n    \"178950763346403741597\",\n    \"175255391013832656387\",\n    \"171560018681261571177\",\n    \"167752665368915604597\",\n    \"164057293036344519387\",\n    \"160361920703773434177\",\n    \"156666548371202348967\",\n    \"152859195058856382387\",\n    \"149163822726285297177\",\n    \"145468450393714211967\",\n    \"141661097081368245387\",\n    \"137965724748797160177\",\n    \"137770769748797160228\",\n    \"134075397416226075018\",\n    \"130380025083654989808\",\n    \"126572671771309023228\",\n    \"122877299438737938018\",\n    \"119181927106166852808\",\n    \"119085927106166852808\",\n    \"115390554773595767598\",\n    \"111583201461249801018\",\n    \"107887829128678715808\",\n    \"104192456796107630598\",\n    \"97001782353847346182\",\n    \"93194429041501379602\",\n    \"83157259869133878290\",\n    \"76983045700832909330\",\n    \"73287673368261824120\",\n    \"69592301035690738910\",\n    \"65896928703119653700\",\n    \"63587931489546380100\",\n    \"59780578177200413520\",\n    \"56085205844629328310\",\n    \"52389833512058243100\",\n    \"51895291676258243202\",\n    \"48199919343687157992\",\n    \"44392566031341191412\",\n    \"40697193698770106202\",\n    \"30446386828370106202\",\n    \"26751014495799020992\",\n    \"23055642163227935782\",\n    \"19248288850881969202\",\n    \"10471674569881968690\",\n    \"3680188132691968050\",\n  ],\n  bids_amtTotal: \"618450503644320209925641\",\n  bids_volTotal: \"198539605794234049017\",\n  asks: [\n    {\n      price: 0.00033331,\n      amt: \"26466599999999999737856\",\n      vol: \"8821317780000000000\",\n      amtTotal: \"26466599999999999737856\",\n      volTotal: \"8821317780000000000\",\n    },\n    {\n      price: 0.0003336,\n      amt: \"33880800000000001048576\",\n      vol: \"11302634880000000000\",\n      amtTotal: \"60347400000000000786432\",\n      volTotal: \"20123952660000000000\",\n    },\n    {\n      price: 0.00033371,\n      amt: \"11142477800817399987988\",\n      vol: \"3718356266910774549\",\n      amtTotal: \"71489877800817400774420\",\n      volTotal: \"23842308926910774549\",\n    },\n    {\n      price: 0.00033439,\n      amt: \"11410124103475892197402\",\n      vol: \"3815340399218399705\",\n      amtTotal: \"82900001904293292971822\",\n      volTotal: \"27657649326129174254\",\n    },\n    {\n      price: 0.00033501,\n      amt: \"39334199999999992922112\",\n      vol: \"13176957000000000000\",\n      amtTotal: \"122234201904293285893934\",\n      volTotal: \"40834606326129174254\",\n    },\n    {\n      price: 0.00033506,\n      amt: \"11052295534472154230337\",\n      vol: \"3703108939445215718\",\n      amtTotal: \"133286497438765440124271\",\n      volTotal: \"44537715265574389972\",\n    },\n    {\n      price: 0.00033572,\n      amt: \"11030456322913363709718\",\n      vol: \"3703093651997124565\",\n      amtTotal: \"144316953761678803833989\",\n      volTotal: \"48240808917571514537\",\n    },\n    {\n      price: 0.00033638,\n      amt: \"11008681778518069039476\",\n      vol: \"3703078409816047858\",\n      amtTotal: \"155325635540196872873465\",\n      volTotal: \"51943887327387562395\",\n    },\n    {\n      price: 0.000337,\n      amt: \"7188173683760000139264\",\n      vol: \"2422342649690282496\",\n      amtTotal: \"162513809223956873012729\",\n      volTotal: \"54366229977077844891\",\n    },\n    {\n      price: 0.00033706,\n      amt: \"11319571950108460741855\",\n      vol: \"3815277012711042502\",\n      amtTotal: \"173833381174065333754584\",\n      volTotal: \"58181506989788887393\",\n    },\n    {\n      price: 0.00033773,\n      amt: \"10964670732513311387215\",\n      vol: \"3703047602083844528\",\n      amtTotal: \"184798051906578645141799\",\n      volTotal: \"61884554591872731921\",\n    },\n    {\n      price: 0.00033848,\n      amt: \"10943090596879450870975\",\n      vol: \"3703921209677097807\",\n      amtTotal: \"195741142503458096012774\",\n      volTotal: \"65588475801549829728\",\n    },\n    {\n      price: 0.00033893,\n      amt: \"31086310012520000126976\",\n      vol: \"10535772189443278848\",\n      amtTotal: \"226827452515978096139750\",\n      volTotal: \"76124247990993108576\",\n    },\n    {\n      price: 0.00033907,\n      amt: \"10921574108084085072499\",\n      vol: \"3703126650187824910\",\n      amtTotal: \"237749026624062181212249\",\n      volTotal: \"79827374641180933486\",\n    },\n    {\n      price: 0.00033934,\n      amt: \"22061773569720001232896\",\n      vol: \"7486221625413088256\",\n      amtTotal: \"259810800193782182445145\",\n      volTotal: \"87313596266594021742\",\n    },\n    {\n      price: 0.00033975,\n      amt: \"11230093484570461106334\",\n      vol: \"3815326678720011608\",\n      amtTotal: \"271040893678352643551479\",\n      volTotal: \"91128922945314033350\",\n    },\n    {\n      price: 0.00034042,\n      amt: \"10878083875111520592396\",\n      vol: \"3703095772122414389\",\n      amtTotal: \"281918977553464164143875\",\n      volTotal: \"94832018717436447739\",\n    },\n    {\n      price: 0.00034061,\n      amt: \"19029641944770000453632\",\n      vol: \"6481686342808109056\",\n      amtTotal: \"300948619498234164597507\",\n      volTotal: \"101313705060244556795\",\n    },\n    {\n      price: 0.00034109,\n      amt: \"10856758733704286197912\",\n      vol: \"3703080631272015254\",\n      amtTotal: \"311805378231938450795419\",\n      volTotal: \"105016785691516572049\",\n    },\n    {\n      price: 0.00034176,\n      amt: \"10835496238854895014260\",\n      vol: \"3703065534900672185\",\n      amtTotal: \"322640874470793345809679\",\n      volTotal: \"108719851226417244234\",\n    },\n    {\n      price: 0.00034244,\n      amt: \"11141671799245742102774\",\n      vol: \"3815263899323431057\",\n      amtTotal: \"333782546270039087912453\",\n      volTotal: \"112535115125740675291\",\n    },\n    {\n      price: 0.00034312,\n      amt: \"10792518633700140402041\",\n      vol: \"3703035020801012310\",\n      amtTotal: \"344575064903739228314494\",\n      volTotal: \"116238150146541687601\",\n    },\n    {\n      price: 0.00034379,\n      amt: \"10771444484888773263977\",\n      vol: \"3703020058155356239\",\n      amtTotal: \"355346509388628001578471\",\n      volTotal: \"119941170204697043840\",\n    },\n    {\n      price: 0.00034447,\n      amt: \"11075875299655656611658\",\n      vol: \"3815217183808722096\",\n      amtTotal: \"366422384688283658190129\",\n      volTotal: \"123756387388505765936\",\n    },\n    {\n      price: 0.00034515,\n      amt: \"10728847020295584791583\",\n      vol: \"3702989813955495075\",\n      amtTotal: \"377151231708579242981712\",\n      volTotal: \"127459377202461261011\",\n    },\n    {\n      price: 0.00034582,\n      amt: \"10707958999548106661900\",\n      vol: \"3702974983460764366\",\n      amtTotal: \"387859190708127349643612\",\n      volTotal: \"131162352185922025377\",\n    },\n    {\n      price: 0.00034649,\n      amt: \"10687131919892014508549\",\n      vol: \"3702960196234208540\",\n      amtTotal: \"398546322628019364152161\",\n      volTotal: \"134865312382156233917\",\n    },\n    {\n      price: 0.00034718,\n      amt: \"10989265205593964126102\",\n      vol: \"3815155690641938295\",\n      amtTotal: \"409535587833613328278263\",\n      volTotal: \"138680468072798172212\",\n    },\n    {\n      price: 0.00034809,\n      amt: \"10645033127428079147754\",\n      vol: \"3705341637309061860\",\n      amtTotal: \"420180620961041407426017\",\n      volTotal: \"142385809710107234072\",\n    },\n    {\n      price: 0.00034854,\n      amt: \"10624389276271547157517\",\n      vol: \"3703021892850000724\",\n      amtTotal: \"430805010237312954583534\",\n      volTotal: \"146088831602957234796\",\n    },\n    {\n      price: 0.00034922,\n      amt: \"10603805418694082174472\",\n      vol: \"3703007072472544949\",\n      amtTotal: \"441408815656007036758006\",\n      volTotal: \"149791838675429779745\",\n    },\n    {\n      price: 0.00034991,\n      amt: \"10903667052066234563130\",\n      vol: \"3815203952623454269\",\n      amtTotal: \"452312482708073271321136\",\n      volTotal: \"153607042628053234014\",\n    },\n    {\n      price: 0.00035059,\n      amt: \"10562197544947631702552\",\n      vol: \"3702977114803447505\",\n      amtTotal: \"462874680253020903023688\",\n      volTotal: \"157310019742856681519\",\n    },\n    {\n      price: 0.00035127,\n      amt: \"10541794072549149477757\",\n      vol: \"3702962424303320597\",\n      amtTotal: \"473416474325570052501445\",\n      volTotal: \"161012982167160002116\",\n    },\n    {\n      price: 0.00035196,\n      amt: \"10839964505283434387937\",\n      vol: \"3815158086789770653\",\n      amtTotal: \"484256438830853486889382\",\n      volTotal: \"164828140253949772769\",\n    },\n    {\n      price: 0.00035265,\n      amt: \"10500550295026604907238\",\n      vol: \"3702932728783504366\",\n      amtTotal: \"494756989125880091796620\",\n      volTotal: \"168531072982733277135\",\n    },\n    {\n      price: 0.00035333,\n      amt: \"10480325106225117837726\",\n      vol: \"3702918166647567295\",\n      amtTotal: \"505237314232105209634346\",\n      volTotal: \"172233991149380844430\",\n    },\n    {\n      price: 0.00035401,\n      amt: \"10460158295034970667917\",\n      vol: \"3702903646543510388\",\n      amtTotal: \"515697472527140180302263\",\n      volTotal: \"175936894795924354818\",\n    },\n    {\n      price: 0.0003547,\n      amt: \"10756101480844670483856\",\n      vol: \"3815097705412174743\",\n      amtTotal: \"526453574007984850786119\",\n      volTotal: \"179751992501336529561\",\n    },\n    {\n      price: 0.000355,\n      amt: \"2879934000000000000000\",\n      vol: \"1022376570000000000\",\n      amtTotal: \"529333508007984850786119\",\n      volTotal: \"180774369071336529561\",\n    },\n    {\n      price: 0.00035539,\n      amt: \"10419392212908119384882\",\n      vol: \"3702874294964379056\",\n      amtTotal: \"539752900220892970171001\",\n      volTotal: \"184477243366300908617\",\n    },\n    {\n      price: 0.00035607,\n      amt: \"10399400937404414745812\",\n      vol: \"3702859901246016389\",\n      amtTotal: \"550152301158297384916813\",\n      volTotal: \"188180103267546925006\",\n    },\n    {\n      price: 0.00035675,\n      amt: \"10379467141462596339294\",\n      vol: \"3702845548912938279\",\n      amtTotal: \"560531768299759981256107\",\n      volTotal: \"191882948816459863285\",\n    },\n    {\n      price: 0.00035781,\n      amt: \"10673207910450037674513\",\n      vol: \"3818930797471485007\",\n      amtTotal: \"571204976210210018930620\",\n      volTotal: \"195701879613931348292\",\n    },\n    {\n      price: 0.00035815,\n      amt: \"10339171406073422424770\",\n      vol: \"3702919927697518809\",\n      amtTotal: \"581544147616283441355390\",\n      volTotal: \"199404799541628867101\",\n    },\n    {\n      price: 0.00035883,\n      amt: \"10319410450646547471681\",\n      vol: \"3702905502200057190\",\n      amtTotal: \"591863558066929988827071\",\n      volTotal: \"203107705043828924291\",\n    },\n    {\n      price: 0.00035887,\n      amt: \"1253970999999999795200\",\n      vol: \"449999996860000051\",\n      amtTotal: \"593117529066929988622271\",\n      volTotal: \"203557705040688924342\",\n    },\n    {\n      price: 0.00035952,\n      amt: \"10299706093934767574874\",\n      vol: \"3702891118019657590\",\n      amtTotal: \"603417235160864756197145\",\n      volTotal: \"207260596158708581932\",\n    },\n    {\n      price: 0.00036,\n      amt: \"491031000000000000000\",\n      vol: \"176771040000000000\",\n      amtTotal: \"603908266160864756197145\",\n      volTotal: \"207437367198708581932\",\n    },\n    {\n      price: 0.00036022,\n      amt: \"10591268908994289896668\",\n      vol: \"3815084938649532411\",\n      amtTotal: \"614499535069859046093813\",\n      volTotal: \"211252452137358114343\",\n    },\n  ],\n  asks_prices: [\n    0.00033331, 0.0003336, 0.00033371, 0.00033439, 0.00033501, 0.00033506,\n    0.00033572, 0.00033638, 0.000337, 0.00033706, 0.00033773, 0.00033848,\n    0.00033893, 0.00033907, 0.00033934, 0.00033975, 0.00034042, 0.00034061,\n    0.00034109, 0.00034176, 0.00034244, 0.00034312, 0.00034379, 0.00034447,\n    0.00034515, 0.00034582, 0.00034649, 0.00034718, 0.00034809, 0.00034854,\n    0.00034922, 0.00034991, 0.00035059, 0.00035127, 0.00035196, 0.00035265,\n    0.00035333, 0.00035401, 0.0003547, 0.000355, 0.00035539, 0.00035607,\n    0.00035675, 0.00035781, 0.00035815, 0.00035883, 0.00035887, 0.00035952,\n    0.00036, 0.00036022,\n  ],\n  asks_amtTotals: [\n    \"26466599999999999737856\",\n    \"60347400000000000786432\",\n    \"71489877800817400774420\",\n    \"82900001904293292971822\",\n    \"122234201904293285893934\",\n    \"133286497438765440124271\",\n    \"144316953761678803833989\",\n    \"155325635540196872873465\",\n    \"162513809223956873012729\",\n    \"173833381174065333754584\",\n    \"184798051906578645141799\",\n    \"195741142503458096012774\",\n    \"226827452515978096139750\",\n    \"237749026624062181212249\",\n    \"259810800193782182445145\",\n    \"271040893678352643551479\",\n    \"281918977553464164143875\",\n    \"300948619498234164597507\",\n    \"311805378231938450795419\",\n    \"322640874470793345809679\",\n    \"333782546270039087912453\",\n    \"344575064903739228314494\",\n    \"355346509388628001578471\",\n    \"366422384688283658190129\",\n    \"377151231708579242981712\",\n    \"387859190708127349643612\",\n    \"398546322628019364152161\",\n    \"409535587833613328278263\",\n    \"420180620961041407426017\",\n    \"430805010237312954583534\",\n    \"441408815656007036758006\",\n    \"452312482708073271321136\",\n    \"462874680253020903023688\",\n    \"473416474325570052501445\",\n    \"484256438830853486889382\",\n    \"494756989125880091796620\",\n    \"505237314232105209634346\",\n    \"515697472527140180302263\",\n    \"526453574007984850786119\",\n    \"529333508007984850786119\",\n    \"539752900220892970171001\",\n    \"550152301158297384916813\",\n    \"560531768299759981256107\",\n    \"571204976210210018930620\",\n    \"581544147616283441355390\",\n    \"591863558066929988827071\",\n    \"593117529066929988622271\",\n    \"603417235160864756197145\",\n    \"603908266160864756197145\",\n    \"614499535069859046093813\",\n  ],\n  asks_volTotals: [\n    \"8821317780000000000\",\n    \"20123952660000000000\",\n    \"23842308926910774549\",\n    \"27657649326129174254\",\n    \"40834606326129174254\",\n    \"44537715265574389972\",\n    \"48240808917571514537\",\n    \"51943887327387562395\",\n    \"54366229977077844891\",\n    \"58181506989788887393\",\n    \"61884554591872731921\",\n    \"65588475801549829728\",\n    \"76124247990993108576\",\n    \"79827374641180933486\",\n    \"87313596266594021742\",\n    \"91128922945314033350\",\n    \"94832018717436447739\",\n    \"101313705060244556795\",\n    \"105016785691516572049\",\n    \"108719851226417244234\",\n    \"112535115125740675291\",\n    \"116238150146541687601\",\n    \"119941170204697043840\",\n    \"123756387388505765936\",\n    \"127459377202461261011\",\n    \"131162352185922025377\",\n    \"134865312382156233917\",\n    \"138680468072798172212\",\n    \"142385809710107234072\",\n    \"146088831602957234796\",\n    \"149791838675429779745\",\n    \"153607042628053234014\",\n    \"157310019742856681519\",\n    \"161012982167160002116\",\n    \"164828140253949772769\",\n    \"168531072982733277135\",\n    \"172233991149380844430\",\n    \"175936894795924354818\",\n    \"179751992501336529561\",\n    \"180774369071336529561\",\n    \"184477243366300908617\",\n    \"188180103267546925006\",\n    \"191882948816459863285\",\n    \"195701879613931348292\",\n    \"199404799541628867101\",\n    \"203107705043828924291\",\n    \"203557705040688924342\",\n    \"207260596158708581932\",\n    \"207437367198708581932\",\n    \"211252452137358114343\",\n  ],\n  asks_amtTotal: \"614499535069859046093813\",\n  asks_volTotal: \"211252452137358114343\",\n};\n\nexport const dexDethRawMock = {\n  version: 4855849,\n  timestamp: 1680161323317,\n  market: \"LRC-USDT\",\n  bids: [\n    [\"327.41\", \"18.54000\", \"18540000000000000000\"],\n    [\"327.00\", \"1.84000\", \"1840000000000000000\"],\n    [\"326.90\", \"0.21000\", \"210000000000000000\"],\n    [\"326.80\", \"8.70000\", \"8700000000000000000\"],\n    [\"326.70\", \"5.09000\", \"5090000000000000000\"],\n    [\"326.60\", \"6.47000\", \"6470000000000000000\"],\n    [\"326.50\", \"7.23000\", \"7230000000000000000\"],\n    [\"326.40\", \"6.13000\", \"6130000000000000000\"],\n    [\"326.30\", \"7.45000\", \"7450000000000000000\"],\n    [\"326.21\", \"56.05000\", \"56050000000000000000\"],\n    [\"326.20\", \"5.98000\", \"5980000000000000000\"],\n  ],\n  asks: [\n    [\"310.64\", \"1.35000\", \"1350000000000000000\"],\n    [\"313.30\", \"9.36000\", \"9360000000000000000\"],\n    [\"313.40\", \"6.55000\", \"6550000000000000000\"],\n    [\"313.50\", \"5.65000\", \"5650000000000000000\"],\n    [\"313.60\", \"7.56000\", \"7560000000000000000\"],\n    [\"313.70\", \"8.68000\", \"8680000000000000000\"],\n    [\"313.80\", \"5.29000\", \"5290000000000000000\"],\n    [\"313.90\", \"6.25000\", \"6250000000000000000\"],\n    [\"314.00\", \"9.05000\", \"9050000000000000000\"],\n    [\"314.10\", \"7.90000\", \"7900000000000000000\"],\n    [\"314.20\", \"5.38000\", \"5380000000000000000\"],\n  ],\n};\n\n//v3/amm/balance?poolAddress=0xfEB069407df0e1e4B365C10992F1bc16c078E34b\nexport const ammPoolSnapshot: sdk.AmmPoolSnapshot = {\n  poolName: \"AMM-LRC-ETH\",\n  poolAddress: \"0x18920d6e6fb7ebe057a4dd9260d6d95845c95036\",\n  pooled: [\n    {\n      tokenId: 1,\n      volume: \"11198097977488137000000000\",\n    },\n    {\n      tokenId: 0,\n      volume: \"3725368050950874300000\",\n    },\n  ],\n  lp: {\n    tokenId: 83,\n    volume: \"34138981282200\",\n  },\n  risky: false,\n};\n//v3/amm/balance?poolAddress=0xfEB069407df0e1e4B365C10992F1bc16c078E34b\nexport const ammPool = {\n  poolName: \"AMM-LRC-ETH\",\n  poolAddress: \"0x18920d6e6fb7ebe057a4dd9260d6d95845c95036\",\n  pooled: [\n    { tokenId: 1, volume: \"11215027899488137000000000\" },\n    { tokenId: 0, volume: \"3720052711450874300000\" },\n  ],\n  lp: { tokenId: 83, volume: \"34141365482200\" },\n  risky: false,\n};\n\n//v3/mix/ticker?market=LRC-ETH\nexport const ticker = {\n  tickers: [\n    [\n      \"COMBINE-LRC-ETH\",\n      \"1655625077879\",\n      \"2429371927000000000000000\",\n      \"814655525450000000000\",\n      \"0.00035052\",\n      \"0.00035222\",\n      \"0.00032201\",\n      \"0.00033367\",\n      \"772\",\n      \"\",\n      \"\",\n      \"\",\n      \"\",\n    ],\n  ],\n};\n\n//v3/user/orderUserRateAmount?accountId=10427&market=LRC-ETH\nexport const userAmount = {\n  \"LRC-ETH\": {\n    LRC: {\n      tokenSymbol: \"LRC\",\n      baseOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"231046501539337141\",\n    },\n    ETH: {\n      tokenSymbol: \"ETH\",\n      baseOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"75150737796750\",\n    },\n  },\n  \"AMM-LRC-ETH\": {\n    LRC: {\n      tokenSymbol: \"LRC\",\n      baseOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"231046501539337141\",\n    },\n    ETH: {\n      tokenSymbol: \"ETH\",\n      baseOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"75150737796750\",\n    },\n  },\n};\nexport const TokenMapMockSwap = {\n  ETH: {\n    type: \"ETH\",\n    tokenId: 0,\n    symbol: \"ETH\",\n    name: \"Ethereum\",\n    address: \"0x0000000000000000000000000000000000000000\",\n    decimals: 18,\n    precision: 7,\n    precisionForOrder: 3,\n    orderAmounts: {\n      minimum: \"1700000000000000\",\n      maximum: \"1000000000000000000000\",\n      dust: \"200000000000000\",\n    },\n    luckyTokenAmounts: {\n      minimum: \"50000000000000\",\n      maximum: \"1000000000000000000000\",\n      dust: \"50000000000000\",\n    },\n    fastWithdrawLimit: \"100000000000000000000\",\n    gasAmounts: {\n      distribution: \"85000\",\n      deposit: \"110000\",\n    },\n    enabled: true,\n    isLpToken: false,\n    tradePairs: [\"LRC\"],\n  },\n  LRC: {\n    type: \"ERC20\",\n    tokenId: 1,\n    symbol: \"LRC\",\n    name: \"Loopring\",\n    address: \"0xbbbbca6a901c926f240b89eacb641d8aec7aeafd\",\n    decimals: 18,\n    precision: 3,\n    precisionForOrder: 3,\n    orderAmounts: {\n      minimum: \"5000000000000000000\",\n      maximum: \"5000000000000000000000000\",\n      dust: \"5000000000000000000\",\n    },\n    luckyTokenAmounts: {\n      minimum: \"50000000000000000\",\n      maximum: \"5000000000000000000000000\",\n      dust: \"50000000000000000\",\n    },\n    fastWithdrawLimit: \"750000000000000000000000\",\n    gasAmounts: {\n      distribution: \"101827\",\n      deposit: \"150000\",\n    },\n    enabled: true,\n    isLpToken: false,\n    tradePairs: [\"ETH\"],\n  },\n};\n\nexport const MAPFEEBIPS = 63;\n"
  },
  {
    "path": "src/tests/README.md",
    "content": "# Loopring SDK  \nLoopring SDK Initialize and Mock Data structure\n\n***\n## SDK Initialize \n```ts\nimport * as sdk from \"../index\";\nexport class LoopringAPIClass {\n  public static userAPI: UserAPI;\n  public static exchangeAPI: ExchangeAPI;\n  public static ammpoolAPI: AmmpoolAPI;\n  public static walletAPI: WalletAPI;\n  public static wsAPI: WsAPI;\n  public static nftAPI: NFTAPI;\n  public static delegate: DelegateAPI;\n  public static globalAPI: GlobalAPI;\n  public static contractAPI: typeof ContractAPI;\n  public static __chainId__: sdk.ChainId;\n  public static InitApi = (chainId: sdk.ChainId) => {\n    LoopringAPI.userAPI = new UserAPI({ chainId });\n    LoopringAPI.exchangeAPI = new ExchangeAPI({ chainId });\n    LoopringAPI.globalAPI = new GlobalAPI({ chainId });\n    LoopringAPI.ammpoolAPI = new AmmpoolAPI({ chainId });\n    LoopringAPI.walletAPI = new WalletAPI({ chainId });\n    LoopringAPI.wsAPI = new WsAPI({ chainId });\n    LoopringAPI.nftAPI = new NFTAPI({ chainId });\n    LoopringAPI.delegate = new DelegateAPI({ chainId });\n    LoopringAPI.__chainId__ = chainId;\n    LoopringAPI.contractAPI = ContractAPI;\n  };\n}\n/* env:\n * test:  sdk.ChainId.GOERLI \n * eth:  sdk.ChainId.MAINNET \n */\nLoopringAPIClass.InitApi({sdk.ChainId.MAINNET}); \n```\n***\n## Connect Wallet \nSuggestion web3 provider\n```shell\n# Using npm\nnpm i @loopring-web/web3-provider --save\n# Using yarn\nyarn add @loopring-web/web3-provider\n```\n- [Demo Vue](https://codesandbox.io/s/vue-8nco78)\n- [Demo React](https://codesandbox.io/s/react-4v50ft)\n \n[Mock Provider](#mock-provider)\n\n***\n## Loopring ERC20 Data Structure \n```ts\nconst {tokensMap, idIndex, addressIndex} = LoopringAPI.exchangeAPI.getTokens();\n```\n[Mock ERC20](#mock-erc20-token-map)\n\n***\n## Token Decimal\n```ts\nconst uiValue = 100;\nconst tradeValue = sdk.toBig(uiValue).times(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals);\n```\n\n***\n## Test Mock Data\n\n##### Mock Account\n```ts\nexport const LOOPRING_EXPORTED_ACCOUNT = {\n  address: \"0x727e0fa09389156fc803eaf9c7017338efd76e7f\",\n  privateKey:\n    \"491aecdb1d5f6400a6b62fd12a41a86715bbab675c37a4060ba115fecf94083c\",\n  accountId: 12454,\n  address2: \"0xb6d8c39D5528357dBCe6BEd82aC71c74e9D19079\",\n  privateKey2:\n    \"e020ed769032ba95d9a5207687a663d6198fe2f5cedf28a250f7cbd8c81a5263\",\n  accountId2: 10488,\n  addressCF: \"0x23dE4Da688c94a66E8bbE9BCc95CB03b4e209C15\",\n  accountIdCF: 11632,\n  addressContractWallet: \"0xD4BD7c71B6d4A09217ccc713f740d6ed8f4EA0cd\",\n  depositAddress: \"0xb684B265f650a77afd27Ce0D95252a7329B5bD72\",\n  exchangeAddress: \"0x2e76EBd1c7c0C8e7c2B875b6d505a260C525d25e\",\n  whitelistedAddress: \"0x35405E1349658BcA12810d0f879Bf6c5d89B512C\",\n  whitelistedEddkey:\n    \"0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\",\n  // const eddkeyWhitelisted =\n  //   \"0x27a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\";\n  //   apiKey: \"2PYgTOZwXHkPXtJMlOMG06ZX1QKJInpoky6iYIbtMgmkbfdL4PvxyEOj0LPOfgYX\",\n  chainId: 5,\n  nftTokenAddress: \"0x8394cB7e768070217592572582228f62CdDE4FCE\",\n  nftTokenId: 32768,\n  nftId: \"0xa0ce8990402955e559799af24ea765b14ffecc32dfa1cce2dadaf20016b074e6\",\n  nftData: \"0x1a2001aac7a1fd00cef07889cdb67b1355f86e5bc9df71cfa44fa1c7b49f598f\",\n  testNotOx: \"727e0fa09389156fc803eaf9c7017338efd76e7f\",\n  tradeLRCValue: 1000000000000000000,\n  tradeETHValue: 0.0001, //same as UI\n  gasPrice: 20, // for test\n  gasLimit: 200000, // for test\n  validUntil: Math.round(Date.now() / 1000) + 30 * 86400,\n};\nexport const CUSTOMER_KEY_SEED = \"XXXXXX\" + \" with key nonce: \" + \"${nonce}\";\n```\n\n##### Mock provider\n```ts \nconst provider = new PrivateKeyProvider(\nLOOPRING_EXPORTED_ACCOUNT.privateKey,\n\"https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3\"\n);\nconst provider2 = new PrivateKeyProvider(\nLOOPRING_EXPORTED_ACCOUNT.privateKey2,\n\"https://goerli.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3\"\n);\nexport const web3 = new Web3(provider);\nexport const web3_2 = new Web3(provider2);\n```\n\n##### Mock ERC20 Token Map\n```ts \nexport let TOKEN_INFO = {\n  addressIndex: {\n    \"0x0000000000000000000000000000000000000000\": \"ETH\",\n    \"0xfc28028d9b1f6966fe74710653232972f50673be\": \"LRC\",\n    \"0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a\": \"USDT\",\n    \"0xfeb069407df0e1e4b365c10992f1bc16c078e34b\": \"LP-LRC-ETH\",\n    \"0x049a02fa9bc6bd54a2937e67d174cc69a9194f8e\": \"LP-ETH-USDT\",\n    \"0xcd2c81b322a5b530b5fa3432e57da6803b0317f7\": \"DAI\",\n    \"0x47525e6a5def04c9a56706e93f54cc70c2e8f165\": \"USDC\",\n    \"0xf37cf4ced77b985708d591acc6bfd08586ab3409\": \"LP-USDC-ETH\",\n  },\n  tokenMap: {\n    ETH: {\n      type: \"ETH\",\n      tokenId: 0,\n      symbol: \"ETH\",\n      name: \"Ethereum\",\n      address: \"0x0000000000000000000000000000000000000000\",\n      decimals: 18,\n      precision: 7,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"5000000000000000\",\n        maximum: \"1000000000000000000000\",\n        dust: \"200000000000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"50000000000000\",\n        maximum: \"1000000000000000000000\",\n        dust: \"50000000000000\",\n      },\n      fastWithdrawLimit: \"100000000000000000000\",\n      gasAmounts: {\n        distribution: \"85000\",\n        deposit: \"100000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"LRC\", \"USDT\", \"USDC\"],\n    },\n    LRC: {\n      type: \"erc20Trade\",\n      tokenId: 1,\n      symbol: \"LRC\",\n      name: \"Loopring\",\n      address: \"0xfc28028d9b1f6966fe74710653232972f50673be\",\n      decimals: 18,\n      precision: 3,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"5000000000000000000\",\n        maximum: \"5000000000000000000000000\",\n        dust: \"5000000000000000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"50000000000000000\",\n        maximum: \"5000000000000000000000000\",\n        dust: \"50000000000000000\",\n      },\n      fastWithdrawLimit: \"750000000000000000000000\",\n      gasAmounts: {\n        distribution: \"101827\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"ETH\"],\n    },\n    USDT: {\n      type: \"erc20Trade\",\n      tokenId: 2,\n      symbol: \"USDT\",\n      name: \"USDT\",\n      address: \"0xd4e71c4bb48850f5971ce40aa428b09f242d3e8a\",\n      decimals: 6,\n      precision: 2,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"5000000\",\n        maximum: \"2000000000000\",\n        dust: \"250000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"50000\",\n        maximum: \"200000000000\",\n        dust: \"50000\",\n      },\n      fastWithdrawLimit: \"250000000000\",\n      gasAmounts: {\n        distribution: \"106233\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"ETH\", \"DAI\"],\n    },\n    \"LP-LRC-ETH\": {\n      type: \"erc20Trade\",\n      tokenId: 4,\n      symbol: \"LP-LRC-ETH\",\n      name: \"AMM-LRC-ETH\",\n      address: \"0xfeb069407df0e1e4b365c10992f1bc16c078e34b\",\n      decimals: 8,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000000000\",\n        dust: \"100000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000000000\",\n        dust: \"100000000\",\n      },\n      fastWithdrawLimit: \"20000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n    \"LP-ETH-USDT\": {\n      type: \"erc20Trade\",\n      tokenId: 7,\n      symbol: \"LP-ETH-USDT\",\n      name: \"LP-ETH-USDT\",\n      address: \"0x049a02fa9bc6bd54a2937e67d174cc69a9194f8e\",\n      decimals: 8,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000\",\n        dust: \"100000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"100000000\",\n        maximum: \"10000000000000\",\n        dust: \"100000000\",\n      },\n      fastWithdrawLimit: \"20000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n    DAI: {\n      type: \"erc20Trade\",\n      tokenId: 6,\n      symbol: \"DAI\",\n      name: \"dai\",\n      address: \"0xcd2c81b322a5b530b5fa3432e57da6803b0317f7\",\n      decimals: 18,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"10000000000000000000\",\n        maximum: \"100000000000000000000000\",\n        dust: \"10000000000000000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"10000000000000000000\",\n        maximum: \"100000000000000000000000\",\n        dust: \"10000000000000000000\",\n      },\n      fastWithdrawLimit: \"10000000000000000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"USDT\"],\n    },\n    USDC: {\n      type: \"USDC\",\n      tokenId: 8,\n      symbol: \"USDC\",\n      name: \"USDC\",\n      address: \"0x47525e6a5def04c9a56706e93f54cc70c2e8f165\",\n      decimals: 6,\n      precision: 6,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"1000\",\n        maximum: \"10000000000000000000\",\n        dust: \"100\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"1000000\",\n        maximum: \"10000000000\",\n        dust: \"1000000\",\n      },\n      fastWithdrawLimit: \"20000000000000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: false,\n      tradePairs: [\"ETH\"],\n    },\n    \"LP-USDC-ETH\": {\n      type: \"LP-USDC-ETH\",\n      tokenId: 9,\n      symbol: \"LP-USDC-ETH\",\n      name: \"LP-USDC-ETH\",\n      address: \"0xf37cf4ced77b985708d591acc6bfd08586ab3409\",\n      decimals: 8,\n      precision: 7,\n      precisionForOrder: 3,\n      orderAmounts: {\n        minimum: \"100000\",\n        maximum: \"1000000000000000000000000000000000000000\",\n        dust: \"10000\",\n      },\n      luckyTokenAmounts: {\n        minimum: \"1000000000000000\",\n        maximum: \"10000000000000000000\",\n        dust: \"1000000000000000\",\n      },\n      fastWithdrawLimit: \"20000000000000000000\",\n      gasAmounts: {\n        distribution: \"150000\",\n        deposit: \"200000\",\n      },\n      enabled: true,\n      isLpToken: true,\n    },\n  },\n  idIndex: {\n    \"0\": \"ETH\",\n    \"1\": \"LRC\",\n    \"2\": \"USDT\",\n    \"4\": \"LP-LRC-ETH\",\n    \"6\": \"DAI\",\n    \"7\": \"LP-ETH-USDT\",\n    \"8\": \"USDC\",\n    \"9\": \"LP-USDC-ETH\",\n  },\n  marketMap: {\n    \"LRC-ETH\": {\n      baseTokenId: 1,\n      enabled: true,\n      market: \"LRC-ETH\",\n      orderbookAggLevels: 5,\n      precisionForPrice: 6,\n      quoteTokenId: 0,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1617967800000,\n    },\n    \"ETH-USDT\": {\n      baseTokenId: 0,\n      enabled: true,\n      market: \"ETH-USDT\",\n      orderbookAggLevels: 3,\n      precisionForPrice: 3,\n      quoteTokenId: 2,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1617972300000,\n    },\n    \"DAI-USDT\": {\n      baseTokenId: 6,\n      enabled: true,\n      market: \"DAI-USDT\",\n      orderbookAggLevels: 2,\n      precisionForPrice: 4,\n      quoteTokenId: 2,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 0,\n    },\n    \"USDC-ETH\": {\n      baseTokenId: 8,\n      enabled: true,\n      market: \"USDC-ETH\",\n      orderbookAggLevels: 3,\n      precisionForPrice: 3,\n      quoteTokenId: 0,\n      status: 3,\n      isSwapEnabled: true,\n      createdAt: 1636974420000,\n    },\n  },\n};\n```\n\n##### Mock AMM MAP\n```ts \nexport let AMM_MAP = {\n  \"AMM-LRC-ETH\": {\n    name: \"LRCETH-Pool\",\n    market: \"AMM-LRC-ETH\",\n    address: \"0xfEB069407df0e1e4B365C10992F1bc16c078E34b\",\n    version: \"1.0.0\",\n    tokens: { pooled: [1, 0], lp: 4 },\n    feeBips: 20,\n    precisions: { price: 6, amount: 5 },\n    createdAt: \"1617967800000\",\n    status: 31,\n  },\n  \"AMM-ETH-USDT\": {\n    name: \"AMM-ETH-USDT\",\n    market: \"AMM-ETH-USDT\",\n    address: \"0x049a02FA9bc6bd54a2937E67D174cc69a9194f8e\",\n    version: \"1.0.0\",\n    tokens: { pooled: [0, 2], lp: 7 },\n    feeBips: 20,\n    precisions: { price: 3, amount: 3 },\n    createdAt: \"1617972300000\",\n    status: 31,\n  },\n  \"AMM-USDC-ETH\": {\n    name: \"AMM-USDC-ETH\",\n    market: \"AMM-USDC-ETH\",\n    address: \"0xf37cf4CEd77b985708D591AcC6BfD08586Ab3409\",\n    version: \"1.0.0\",\n    tokens: {\n      pooled: [8, 0],\n      lp: 9,\n    },\n    feeBips: 20,\n    precisions: {\n      price: 3,\n      amount: 4,\n    },\n    createdAt: \"1636974420000\",\n    status: 0,\n  },\n};\n```\n\n##### Mock EIP712 Typed Data\n```ts\nexport const testTypedData: EIP712TypedData = {\n  types: {\n    EIP712Domain: [\n      { name: \"name\", type: \"string\" },\n      { name: \"version\", type: \"string\" },\n      { name: \"chainId\", type: \"uint256\" },\n      { name: \"verifyingContract\", type: \"address\" },\n    ],\n    TestTypedData: [\n      { name: \"from\", type: \"address\" },\n      { name: \"to\", type: \"address\" },\n      { name: \"tokenID\", type: \"uint16\" },\n    ],\n  },\n  primaryType: \"TestTypedData\",\n  domain: {\n    name: \"Loopring Protocol\",\n    version: \"3.6.0\",\n    chainId: sdk.ChainId.GOERLI,\n    verifyingContract: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  },\n  message: {\n    from: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address2,\n    tokenID: TOKEN_INFO.tokenMap.LRC.tokenId,\n  },\n};\n ```\n\n##### Mock generate eddsaKey \n```ts \nexport async function signatureKeyPairMock(\n  accInfo: sdk.AccountInfo,\n  _web3: Web3 = web3\n) {\n  const eddsaKey = await sdk.generateKeyPair({\n    web3: _web3,\n    address: accInfo.owner,\n    keySeed:\n      accInfo.keySeed ??\n      sdk.GlobalAPI.KEY_MESSAGE.replace(\n        \"${exchangeAddress}\",\n        LOOPRING_EXPORTED_ACCOUNT.exchangeAddress\n      ).replace(\"${nonce}\", (accInfo.nonce - 1).toString()),\n    walletType: sdk.ConnectorNames.MetaMask,\n    chainId: sdk.ChainId.GOERLI,\n  });\n  return eddsaKey;\n}\n```\n"
  },
  {
    "path": "src/tests/UTC--2021-02-04T02-55-36.490219109Z--ef439044717c3af35f4f46e52aa99280217a7114",
    "content": "{'address':'ef439044717c3af35f4f46e52aa99280217a7114','crypto':{'cipher':'aes-128-ctr','ciphertext':'143482fb2ed65e3abc9cc13fcaeb6ba74c4d756c8214df71ac976aec8252ed09','cipherparams':{'iv':'5a968f30a2345ab47f17b27b903dc211'},'kdf':'scrypt','kdfparams':{'dklen':32,'n':262144,'p':1,'r':8,'salt':'da706a1d49a37f901393ea20604587f70a04bbfecec861f8d5188dc5477410c8'},'mac':'983f9b60b7bfd030f14d1445001f2375c654a8a1a116ac6321e0e58d9a1f63f8'},'id':'13090125-668c-4935-9bcd-77512c377afd','version':3}"
  },
  {
    "path": "src/tests/demo/NFTAction/collectionNFT.md",
    "content": "# Collection NFT\n\nDefinition: allow user create a NFT Collection with different Contract(token) address.\n\n- allow user mint the NFTs with collection\n- when collection deployed, NFTs will have different Contract(token) address in layer1\n- Loopring own collection on L2, allow user to view/edit their Collection information.\n- will soon enable the \"Import Collection\" to manage legacy NFTs\n\n***\n\n##Create Collection\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n { accountId: accInfo.accountId,},\n eddsaKey.sk\n);\nconst response = await LoopringAPI.userAPI.submitNFTCollection({\n\tname: 'XXX' + Date.now(), //required, one account is not able to multiple\n\ttileUri: 'ipfs://QmaNZ2FCgvBPqnxtkbToVVbK2Nes6xk5K4Ns6BsmkPucAM', //required\n\tdescription: 'test',\n\towner: mockData.accInfo.owner,\n\tavatar: 'ipfs://QmaNZ2FCgvBPqnxtkbToVVbK2Nes6xk5K4Ns6BsmkPucAM',\n\tbanner: 'ipfs://QmaNZ2FCgvBPqnxtkbToVVbK2Nes6xk5K4Ns6BsmkPucAM',\n\tnftFactory: NFTFactory_Collection[LOOPRING_EXPORTED_ACCOUNT.chainId as ChainId ]},\n\tLOOPRING_EXPORTED_ACCOUNT.chainId as ChainId,\n\tmockData.apiKey,\n\tmockData.eddsaKey.sk)\nconsole.log('createCollection', response)\n\n```\n\n## getUserNFFByCollection\n```ts\nconst response = await LoopringAPI.userAPI\n\t.getUserNFTCollection(\n\t\t{\n\t\t\taccountId: mockData.accInfo.accountId.toString(),\n\t\t\tlimit: 24,\n\t\t\toffset: 0,\n\t\t},\n\t\tmockData.apiKey\n\t)\n\t.catch((_error) => {\n\t\tthrow _error;\n\t});\nconsole.log(\"getUserNFFByCollection\", response);\n\n```\n\n## getUserOwnCollection (User own create Collection)\n```ts\nconst response = await LoopringAPI.userAPI\n  .getUserOwenCollection(\n    {\n      owner: mockData.accInfo.owner,\n      limit: 24,\n      offset: 0,\n      tokenAddress: undefined,\n      isMintable: false, //false\n    },\n    mockData.apiKey\n  )\n  .catch((_error) => {\n    throw _error;\n  });\nconsole.log(\"getUserNFFByCollection\", response);\n\n```\n\n## getUserNFTCollection  (User asset NFT's Collections)\n```ts \nconst response = await LoopringAPI.userAPI\n  .getUserNFTCollection({\n    tokenAddress: contract, // option\n    collectionId: id, // option\n    accountId:  mockData.accInfo.accountId,\n    limit: 20,\n    offset:10,\n  }, mockData.apiKey)\n\n```\n\n## getCollectionWholeNFTs\n```ts\nconst response = await LoopringAPI.nftAPI.getCollectionWholeNFTs({\n  id: 279,\n  offset: 0,\n  limit: 24,\n  metadata: true,\n});\nconsole.log(\"getCollectionWholeNFTs\", response);\n```"
  },
  {
    "path": "src/tests/demo/NFTAction/collectionNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport { AccountInfo, ChainId, NFTFactory_Collection } from \"../../../index\";\n\nlet mockData:\n  | {\n      accInfo: AccountInfo;\n      apiKey: string;\n      eddsaKey: any;\n    }\n  | undefined = undefined;\ndescribe(\"metaNFT\", function () {\n  beforeEach(async () => {\n    // Step 1. getAccount\n    const accInfo = (\n      await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n    ).accInfo;\n    const eddsaKey = await signatureKeyPairMock(accInfo);\n\n    // Step 3. apiKey\n    const apiKey = (\n      await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      )\n    ).apiKey;\n\n    mockData = {\n      apiKey,\n      accInfo,\n      eddsaKey,\n    };\n  }, DEFAULT_TIMEOUT * 3);\n  it(\n    \"getUserOwnCollection\",\n    async () => {\n      if (mockData) {\n        const response = await LoopringAPI.userAPI\n          .getUserOwenCollection(\n            {\n              owner: mockData.accInfo.owner,\n              limit: 24,\n              offset: 0,\n              tokenAddress: undefined,\n              isMintable: false, //false\n            },\n            mockData.apiKey\n          )\n          .catch((_error) => {\n            throw _error;\n          });\n        console.log(\"getUserNFFByCollection\", response);\n      }\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getUserNFFByCollection\",\n    async () => {\n      if (mockData) {\n        const response = await LoopringAPI.userAPI\n          .getUserNFTCollection(\n            {\n              accountId: mockData.accInfo.accountId.toString(),\n              limit: 24,\n              offset: 0,\n            },\n            mockData.apiKey\n          )\n          .catch((_error) => {\n            throw _error;\n          });\n        console.log(\"getUserNFFByCollection\", response);\n      }\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getCollectionWholeNFTs\",\n    async () => {\n      const response = await LoopringAPI.nftAPI.getCollectionWholeNFTs({\n        id: 279,\n        offset: 0,\n        limit: 24,\n        metadata: true,\n      });\n      console.log(\"getCollectionWholeNFTs\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"createCollection\",\n    async () => {\n      if (mockData) {\n        const response = await LoopringAPI.userAPI.submitNFTCollection(\n          {\n            name: \"XXX\" + Date.now(), //required, one account is not able to multiple\n            tileUri: \"ipfs://QmaNZ2FCgvBPqnxtkbToVVbK2Nes6xk5K4Ns6BsmkPucAM\", //required\n            description: \"test\",\n            owner: mockData.accInfo.owner,\n            avatar: \"ipfs://QmaNZ2FCgvBPqnxtkbToVVbK2Nes6xk5K4Ns6BsmkPucAM\",\n            banner: \"ipfs://QmaNZ2FCgvBPqnxtkbToVVbK2Nes6xk5K4Ns6BsmkPucAM\",\n            nftFactory:\n              NFTFactory_Collection[\n                LOOPRING_EXPORTED_ACCOUNT.chainId as ChainId\n              ],\n          },\n          LOOPRING_EXPORTED_ACCOUNT.chainId as ChainId,\n          mockData.apiKey,\n          mockData.eddsaKey.sk\n        );\n        console.log(\"createCollection\", response);\n      }\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/NFTAction/deployNFT.md",
    "content": "# Deploy NFT\n\nDefinition: Only nft minter can deploy NFT\n\n***\n\n## Step 1. get Account\n\n```ts \nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n```\n\n***\n\n## Step 2. get eddsaKey\n\n```ts\n   const eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n```\n\n***\n\n\n## Step 4. get fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_DEPLOY,\n    amount: \"0\",\n  },\n  apiKey\n);\nconsole.log(fee);\n```      \n***\n## Step 5. get storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId, // same as Step 7. transfer->token->tokenId\n  },\n  apiKey\n);\n```\n\n***\n\n## Step 6. broker\n\n```ts\nconst {broker} = await LoopringAPI.exchangeAPI.getAvailableBroker();\n```\n\n***\n## Step 7. Build transfer & Deploy\n\n```ts\n      const transfer = {\n  exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  payerAddr: LOOPRING_EXPORTED_ACCOUNT.address,\n  payerId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  payeeAddr: broker,\n  // payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n  storageId: storageId.offchainId,\n  token: {\n    tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n    volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n  },\n  validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n};\nconst response = await LoopringAPI.userAPI.submitDeployNFT({\n  request: {\n    transfer,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n\nconsole.log(response);\n```\n      \n\n"
  },
  {
    "path": "src/tests/demo/NFTAction/deployNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\ndescribe(\"deployNFT\", function () {\n  it(\n    \"submitDeployNFT\",\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. fee\n      const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_DEPLOY,\n          amount: \"0\",\n        },\n        apiKey\n      );\n      console.log(fee);\n\n      // Step 5. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId, // same as Step 7. transfer->token->tokenId\n        },\n        apiKey\n      );\n\n      // Step 6. broker\n      const { broker } = await LoopringAPI.exchangeAPI.getAvailableBroker({\n        type: 0,\n      });\n\n      // Step 7. Build transfer & Deploy\n      const transfer = {\n        exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        payerAddr: LOOPRING_EXPORTED_ACCOUNT.address,\n        payerId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        payeeAddr: broker,\n        // payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n        storageId: storageId.offchainId,\n        token: {\n          tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n          volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n        },\n        validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      };\n\n      const response = await LoopringAPI.userAPI.submitDeployNFT({\n        request: {\n          transfer,\n          tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n          nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        eddsaKey: eddsaKey.sk,\n        apiKey: apiKey,\n      });\n\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/NFTAction/metaNFT.md",
    "content": "# NFT META METHODS\n\n***\n\n## getContractNFTMeta\n\n```ts\nconst result = await LoopringAPI.nftAPI.getContractNFTMeta({\n  web3,\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n  nftType: sdk.NFTType.ERC1155,\n});\nconsole.log(result);\n```    \n\n***\n\n## getInfoForNFTTokens\n\n```ts\nconst response = await LoopringAPI.nftAPI.getInfoForNFTTokens({\n  nftDatas: [LOOPRING_EXPORTED_ACCOUNT.nftData],\n});\nconsole.log(`getInfoForNFTTokens: response: `, JSON.stringify(response));\n```\n\n***\n\n## computeNFTAddress\n\n```ts\nconst response = LoopringAPI.nftAPI.computeNFTAddress({\n  nftOwner: \"0xE20cF871f1646d8651ee9dC95AAB1d93160b3467\",\n  nftFactory: \"0x40F2C1770E11c5bbA3A26aEeF89616D209705C5D\",\n});\nconsole.log(\n  `computeNFTAddress:`,\n  response,\n  \"0xee354d81778a4c5a08fd9dbeb5cfd01a840a746d\"\n);\n```\n\n***\n\n## ipfsCid0ToNftID\n\n```ts\nconst ipfs = \"QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ\";\nconst nftID =\n  \"0x0880847b7587968f32ba6c741f9d797d9dc64971979922a80c4e590453b8dc2f\";\nconsole.log(\n  `ipfsCid0ToNftID: ipfs: `,\n  ipfs,\n  LoopringAPI.nftAPI.ipfsCid0ToNftID(ipfs)\n);\n```\n\n*** \n\n## ipfsNftIDToCid\n\n```ts\nconst ipfs = \"QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ\";\nconst nftID =\n  \"0x0880847b7587968f32ba6c741f9d797d9dc64971979922a80c4e590453b8dc2f\";\n\nconsole.log(\n  `ipfsCid0ToNftID: nftID: `,\n  nftID,\n  LoopringAPI.nftAPI.ipfsNftIDToCid(nftID)\n);\n```\n "
  },
  {
    "path": "src/tests/demo/NFTAction/metaNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\ndescribe(\"metaNFT\", function () {\n  it(\n    \"getContractNFTMeta\",\n    async () => {\n      const result = await LoopringAPI.nftAPI.getContractNFTMeta({\n        web3,\n        tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n        nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n        nftType: sdk.NFTType.ERC1155,\n      });\n      console.log(result);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getInfoForNFTTokens\",\n    async () => {\n      const response = await LoopringAPI.nftAPI.getInfoForNFTTokens({\n        nftDatas: [LOOPRING_EXPORTED_ACCOUNT.nftData],\n      });\n      console.log(`getInfoForNFTTokens: response: `, JSON.stringify(response));\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\"computeNFTAddress\", async () => {\n    const response = LoopringAPI.nftAPI.computeNFTAddress({\n      nftOwner: \"0xE20cF871f1646d8651ee9dC95AAB1d93160b3467\",\n      nftFactory: \"0x40F2C1770E11c5bbA3A26aEeF89616D209705C5D\",\n    });\n    console.log(\n      `computeNFTAddress:`,\n      response,\n      \"0xee354d81778a4c5a08fd9dbeb5cfd01a840a746d\"\n    );\n  });\n  it(\"ipfsCid0ToNftID\", () => {\n    const ipfs = \"QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ\";\n    const nftID =\n      \"0x0880847b7587968f32ba6c741f9d797d9dc64971979922a80c4e590453b8dc2f\";\n    console.log(\n      `ipfsCid0ToNftID: ipfs: `,\n      ipfs,\n      LoopringAPI.nftAPI.ipfsCid0ToNftID(ipfs)\n    );\n    expect(LoopringAPI.nftAPI.ipfsCid0ToNftID(ipfs)).toBe(nftID);\n  });\n  it(\"ipfsNftIDToCid\", () => {\n    const ipfs = \"QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ\";\n    const nftID =\n      \"0x0880847b7587968f32ba6c741f9d797d9dc64971979922a80c4e590453b8dc2f\";\n\n    console.log(\n      `ipfsCid0ToNftID: nftID: `,\n      nftID,\n      LoopringAPI.nftAPI.ipfsNftIDToCid(nftID)\n    );\n    expect(LoopringAPI.nftAPI.ipfsNftIDToCid(nftID)).toBe(ipfs);\n  });\n});\n"
  },
  {
    "path": "src/tests/demo/NFTAction/mintNFT.md",
    "content": "# Mint NFT\n\nDefinition: Mint Layer2 NFT, Loopring follow the ipfs NFT format, IPFS CID will convert to nftId, please view MetaNFT.md\n \n>    <p style={color:\"red\"}>!!! important  describe<p>\n>    <p>Follow method is the simple way for mint NTF, but this kind of NFT will using the same contact & with   no Contract metadata forever on L1</p> \n>    <p>New Version of NFT will has it isolate Contract/collection with metadata information</p> \n>    <P>From Step 3. nftTokenAddress please follow create `collectionNFT` step create collection(contract), the api will return follow info for mint NFT</p>\n>    \n```ts\ntokenAddress: collectionMeta.contractAddress\ncounterFactualNftInfo: {\n\tnftOwner: ccInfo.owner,\n\tnftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[chainId],\n\tnftBaseUri: collectionMeta?.baseUri ?? \"\",\n},\n```\n\n## Step 1. get Account\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n\towner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n``` \n\n***\n\n## Step 2. get eddsaKey\n\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey({\n   accountId: accInfo.accountId,\n },\n eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n```\n\n***\n\n## Step 4. get storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n{\n\taccountId: accInfo.accountId,\n\tsellTokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId, // same as maxFee tokenId\n},\napiKey\n);\n```\n\n***\n\n## Step 5. get collection Information(tokenAddress)\n\n```ts\nconst collectionRes = await LoopringAPI.userAPI\n\t.getUserOwenCollection({\n\t\t\towner: accInfo.owner,\n\t\t\ttokenAddress: mockData.nftTokenAddress,\n\t\t\tisMintable: true\n\t\t},\n\t\tapiKey\n\t)\nif ((collectionRes &&\n\t((collectionRes as sdk.RESULT_INFO).code ||\n\t\t(collectionRes as sdk.RESULT_INFO).message)) || !collectionRes.collections.length\n) {\n\tconsole.log(\"Collection is disable to mint \");\n\tthrow \"Collection is disable to mint \";\n}\n\nconst collectionMeta = (collectionRes as any).collections[ 0 ] as CollectionMeta;\n\nconst counterFactualNftInfo: NFTCounterFactualInfo = {\n\tnftOwner: accInfo.owner,\n\tnftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[ sdk.ChainId.GOERLI ],\n\tnftBaseUri: collectionMeta.baseUri,\n};\n\n```\n\n***\n\n## Step 6. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n\t{\n\t\taccountId: accInfo.accountId,\n\t\ttokenAddress: collectionMeta.contractAddress,\n\t\trequestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n\t},\n\tapiKey\n);\n```\n\n***\n\n## Step7. Mint\n\n```ts\nconst response = await LoopringAPI.userAPI.submitNFTMint({\n\trequest: {\n\t\texchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n\t\tminterId: accInfo.accountId,\n\t\tminterAddress: accInfo.owner,\n\t\ttoAccountId: accInfo.accountId,\n\t\ttoAddress: accInfo.owner,\n\t\tnftType: 0,\n\t\ttokenAddress: nftTokenAddress, // please read the description -> tokenAddress: collectionMeta.contractAddress,\n\t\tnftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n\t\tamount: \"1\",\n\t\tvalidUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n\t\tstorageId: storageId.offchainId ?? 9,\n\t\tmaxFee: {\n\t\t\ttokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId,\n\t\t\tamount: fee.fees[ \"LRC\" ].fee ?? \"9400000000000000000\",\n\t\t},\n\t\tcounterFactualNftInfo,\n\t\troyaltyPercentage: 5,\n\t\tforceToMint: true, // suggest use as false, for here is just for run test\n\t        // please read the description\n\t        // counterFactualNftInfo: {\n\t        //  nftOwner: ccInfo.owner,\n\t        //  nftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[chainId],\n\t        //  nftBaseUri: collectionMeta?.baseUri ?? \"\",\n\t        // },\n\t},\n\tweb3,\n\tchainId: sdk.ChainId.GOERLI,\n\twalletType: sdk.ConnectorNames.Unknown,\n\teddsaKey: eddsaKey.sk,\n\tapiKey: apiKey,\n});\n```\n\n____\n\n### ps: Mint with legacy nftFactory\n\n<font color='red'>! Mint NFT from this way has no collection information at deploy contract(tokenAdress is\nunique)</font>\n***\n\n#### Step 1,2,3,4 is same logic\n\n#### Step 5. get tokenAddress\n\n```ts\nconst counterFactualNftInfo = {\n\tnftOwner: accInfo.owner,\n\tnftFactory: sdk.NFTFactory[ sdk.ChainId.GOERLI ],\n\tnftBaseUri: \"\",\n};\nconst nftTokenAddress =\n\tLoopringAPI.nftAPI.computeNFTAddress(counterFactualNftInfo)\n\t\t.tokenAddress || \"\";\nconsole.log(\"nftTokenAddress\", nftTokenAddress);\n```\n\n***\n\n#### Step 6. get fee\n\n```ts\n const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n\t{\n\t\taccountId: accInfo.accountId,\n\t\ttokenAddress: nftTokenAddress,\n\t\trequestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n\t},\n\tapiKey\n);\n```\n\n#### Step 7. Mint\n\n```ts\n\nconst response = await LoopringAPI.userAPI.submitNFTMint({\n\trequest: {\n\t\texchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n\t\tminterId: accInfo.accountId,\n\t\tminterAddress: accInfo.owner,\n\t\ttoAccountId: accInfo.accountId,\n\t\ttoAddress: accInfo.owner,\n\t\tnftType: 0,\n\t\ttokenAddress: nftTokenAddress,\n\t\tnftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n\t\tamount: \"1\",\n\t\tvalidUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n\t\tstorageId: storageId.offchainId ?? 9,\n\t\tmaxFee: {\n\t\t\ttokenId: TOKEN_INFO.tokenMap[ \"LRC\" ].tokenId,\n\t\t\tamount: fee.fees[ \"LRC\" ].fee ?? \"9400000000000000000\",\n\t\t},\n\t\troyaltyPercentage: 5,\n\t\tcounterFactualNftInfo,\n\t\tforceToMint: true, // suggest use as false, for here is just for run test\n\t},\n\tweb3,\n\tchainId: sdk.ChainId.GOERLI,\n\twalletType: sdk.ConnectorNames.Unknown,\n\teddsaKey: eddsaKey.sk,\n\tapiKey: apiKey,\n});\n```\n"
  },
  {
    "path": "src/tests/demo/NFTAction/mintNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from '../../MockData'\nimport * as sdk from '../../../index'\nimport { CollectionMeta, NFTCounterFactualInfo } from '../../../defs'\nconst mockData = {\n  nftTokenAddress: '0xfc26d5b9277f4375ba8ff7d4708f4dbf78954124',\n}\n/**\n * !!!important  describe\n * Follow mehod is the simple way for mint NTF, but this kind of NFT will using the same contact & with no Contract metadata forever on L1,\n * New Version of NFT will has it isolate Contract/colletion with metadata inforamtion\n * From Step 3. nftTokenAddress please follow create `collectionNFT` step create collection(contract), the api will return follow info for mint NFT\n * tokenAddress: collectionMeta.contractAddress,\n * counterFactualNftInfo: {\n *  nftOwner: ccInfo.owner,\n *  nftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[chainId],\n *  nftBaseUri: collectionMeta?.baseUri ?? \"\",\n * },\n **/\ndescribe('mintNFT', function () {\n  it(\n    'submitNFTMint',\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n      console.log('accInfo:', accInfo)\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo)\n      console.log('eddsaKey:', eddsaKey.sk)\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk,\n      )\n      console.log('apiKey:', apiKey)\n\n      // Step 3. nftTokenAddress\n      const counterFactualNftInfo = {\n        nftOwner: accInfo.owner,\n        nftFactory: LOOPRING_EXPORTED_ACCOUNT.uatNFTFactory,\n        nftBaseUri: '',\n      }\n      const nftTokenAddress =\n        LoopringAPI.nftAPI.computeNFTAddress(counterFactualNftInfo).tokenAddress || ''\n      console.log('nftTokenAddress', nftTokenAddress)\n\n      // Step 4. fee\n      const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          tokenAddress: nftTokenAddress,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n        },\n        apiKey,\n      )\n\n      // Step 5. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap['LRC'].tokenId,\n        },\n        apiKey,\n      )\n\n      // Step 7. Mint\n      const response = await LoopringAPI.userAPI.submitNFTMint(\n        {\n          request: {\n            exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n            minterId: accInfo.accountId,\n            minterAddress: accInfo.owner,\n            toAccountId: accInfo.accountId,\n            toAddress: accInfo.owner,\n            nftType: 0,\n            tokenAddress: nftTokenAddress, // please read the description -> tokenAddress: collectionMeta.contractAddress,\n            nftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n            amount: '1',\n            validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n            storageId: storageId.offchainId ?? 9,\n            maxFee: {\n              tokenId: TOKEN_INFO.tokenMap['LRC'].tokenId,\n              amount: fee.fees['LRC'].fee ?? '9400000000000000000',\n            },\n            royaltyPercentage: 5,\n            forceToMint: true, // suggest use as false, for here is just for run test\n            // please read the description\n            // counterFactualNftInfo: {\n            //  nftOwner: ccInfo.owner,\n            //  nftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[chainId],\n            //  nftBaseUri: collectionMeta?.baseUri ?? \"\",\n            // },\n          },\n          web3,\n          chainId: sdk.ChainId.GOERLI,\n          walletType: sdk.ConnectorNames.Unknown,\n          eddsaKey: eddsaKey.sk,\n          apiKey: apiKey,\n        },\n        { _noEcdsa: true },\n      )\n\n      console.log(response)\n    },\n    DEFAULT_TIMEOUT * 3,\n  )\n\n  //Suggest use this function\n  it(\n    'submitNFTMintWithCollection',\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n      console.log('accInfo:', accInfo)\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo)\n      console.log('eddsaKey:', eddsaKey.sk)\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk,\n      )\n      console.log('apiKey:', apiKey)\n\n      // Step 4. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap['LRC'].tokenId, // same as maxFee tokenId\n        },\n        apiKey,\n      )\n\n      // Step 5. get collection Information(tokenAddress)\n      const collectionRes = await LoopringAPI.userAPI.getUserOwenCollection(\n        {\n          owner: accInfo.owner,\n          tokenAddress: mockData.nftTokenAddress,\n          isMintable: true,\n        },\n        apiKey,\n      )\n      if (\n        (collectionRes &&\n          ((collectionRes as sdk.RESULT_INFO).code ||\n            (collectionRes as sdk.RESULT_INFO).message)) ||\n        !collectionRes.collections.length\n      ) {\n        console.log('Collection is disable to mint ')\n        throw 'Collection is disable to mint '\n      }\n\n      const collectionMeta = (collectionRes as any).collections[0] as CollectionMeta\n\n      const counterFactualNftInfo: NFTCounterFactualInfo = {\n        nftOwner: accInfo.owner,\n        nftFactory: collectionMeta.nftFactory ?? sdk.NFTFactory_Collection[sdk.ChainId.GOERLI],\n        nftBaseUri: collectionMeta.baseUri,\n      }\n\n      // Step 6. fee\n      const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          tokenAddress: collectionMeta.contractAddress,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n        },\n        apiKey,\n      )\n\n      // Step 7. Mint\n      const response = await LoopringAPI.userAPI.submitNFTMint({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          minterId: accInfo.accountId,\n          minterAddress: accInfo.owner,\n          toAccountId: accInfo.accountId,\n          toAddress: accInfo.owner,\n          nftType: 0,\n          tokenAddress: collectionMeta.contractAddress,\n          nftId: LOOPRING_EXPORTED_ACCOUNT.nftId, //nftId.toString(16),\n          amount: '1',\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n          storageId: storageId.offchainId ?? 9,\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap['LRC'].tokenId,\n            amount: fee.fees['LRC'].fee ?? '9400000000000000000',\n          },\n          counterFactualNftInfo,\n          royaltyPercentage: 5,\n          forceToMint: true, // suggest use as false, for here is just for run test\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        eddsaKey: eddsaKey.sk,\n        apiKey: apiKey,\n      })\n\n      console.log(response)\n    },\n    DEFAULT_TIMEOUT * 3,\n  )\n})\n"
  },
  {
    "path": "src/tests/demo/NFTAction/tradeNFT.md",
    "content": "# Trade NFT\n\nDefinition: This method is help for understand how to match a maker with a taker order\n\n***\n\n## tradeNFT \n> Private or third account can signature and approve this order\n\n[mock order](#MockOrder)\n```ts\n// Step 1. getAccount\nconst accInfoC = (\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  })\n).accInfo;\n\n// Step 1. eddsaKeyC\nconst eddsaKeyC = await signatureKeyPairMock(accInfoC);\n\n// Step 3. apiKey\nconst apiKeyC = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfoC.accountId,\n    },\n    eddsaKeyC.sk\n  )\n).apiKey;\n//  NFT Trade\nconst response = await LoopringAPI.userAPI.submitNFTTrade({\n  request: {\n    maker: {\n      ...mockData.makerOrder,\n      eddsaSignature: mockData.makerOrderEddsaSignature,\n    },\n    makerFeeBips: 1000,\n    taker: {\n      ...mockData.takerOrder,\n      eddsaSignature: mockData.takerOrderEddsaSignature,\n    },\n    takerFeeBips: 100,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  apiKey: apiKeyC,\n  eddsaKey: eddsaKeyC.sk,\n});\n\nconsole.log(response);\n```\n\n***\n\n## MockOrder\n\n> Validate NFT Order please reader @Validate NFT Order\n\n```ts\n// Step 1. getAccount\nconst accInfo = (\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  })\n).accInfo;\nconst accInfo2 = (\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address2,\n  })\n).accInfo;\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconst eddsaKey2 = await signatureKeyPairMock(accInfo2, web3_2);\n// Step 3. apiKey\nconst apiKey = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo.accountId,\n    },\n    eddsaKey.sk\n  )\n).apiKey;\nconst apiKey2 = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo2.accountId,\n    },\n    eddsaKey2.sk\n  )\n).apiKey;\n\n// Step 4. storageId\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconst storageId2 = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo2.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  },\n  apiKey2\n);\n// Step 5. generate Order, please read validateNFTOrder\nconst makerOrder: sdk.NFTOrderRequestV3 = {\n  exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  accountId: accInfo.accountId,\n  storageId: storageId.orderId,\n  sellToken: {\n    tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n    nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n    amount: \"1\",\n  },\n  buyToken: {\n    tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n    amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  },\n  allOrNone: false,\n  fillAmountBOrS: false,\n  validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  maxFeeBips: 1000,\n};\nconst makerOrderEddsaSignature = sdk.get_EddsaSig_NFT_Order(\n  makerOrder,\n  eddsaKey.sk\n);\n\nconst takerOrder: sdk.NFTOrderRequestV3 = {\n  exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  accountId: accInfo2.accountId,\n  storageId: storageId2.orderId,\n  sellToken: {\n    tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n    amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  },\n  buyToken: {\n    tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n    nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n    amount: \"1\",\n  },\n  allOrNone: false,\n  fillAmountBOrS: true,\n  validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  maxFeeBips: 100,\n};\nconst takerOrderEddsaSignature = sdk.get_EddsaSig_NFT_Order(\n  takerOrder,\n  eddsaKey2.sk\n);\n\nmockData = {\n  takerOrder,\n  takerOrderEddsaSignature,\n  makerOrder,\n  makerOrderEddsaSignature,\n  makerFeeBips: 1000,\n  maxFeeBips: 100,\n};\n\n```\n"
  },
  {
    "path": "src/tests/demo/NFTAction/tradeNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  signatureKeyPairMock,\n  web3_2,\n  TOKEN_INFO,\n} from '../../MockData'\nimport * as sdk from '../../../index'\nimport { myLog } from '../../../utils/log_tools'\nlet mockData: any = {\n  takerOrder: undefined,\n  takerOrderEddsaSignature: undefined,\n  makerOrder: undefined,\n  makerOrderEddsaSignature: undefined,\n  makerFeeBips: 1000,\n  maxFeeBips: 100,\n}\nlet accInfoC: any = undefined\nlet eddsaKeyC: any = undefined\n\ndescribe('tradeNFT group', function () {\n  beforeEach(async () => {\n    // console.log('tradeNFT before all', LoopringAPI.exchangeAPI)\n    // Step 1. getAccount\n    const accInfo = (\n      await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n    ).accInfo\n\n    const accInfo2 = (\n      await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address2,\n      })\n    ).accInfo\n    // console.log(accInfo, accInfo2)\n\n    // Step 2. eddsaKey\n    const eddsaKey = await signatureKeyPairMock(accInfo)\n    const eddsaKey2 = await signatureKeyPairMock(accInfo2, web3_2)\n    accInfoC = accInfo\n    eddsaKeyC = eddsaKey\n\n    // Step 3. apiKey\n    const apiKey = (\n      await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk,\n      )\n    ).apiKey\n    const apiKey2 = (\n      await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo2.accountId,\n        },\n        eddsaKey2.sk,\n      )\n    ).apiKey\n\n    // Step 4. storageId\n    const storageId = await LoopringAPI.userAPI.getNextStorageId(\n      {\n        accountId: accInfo.accountId,\n        sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      },\n      apiKey,\n    )\n    const storageId2 = await LoopringAPI.userAPI.getNextStorageId(\n      {\n        accountId: accInfo2.accountId,\n        sellTokenId: TOKEN_INFO.tokenMap['LRC'].tokenId,\n      },\n      apiKey2,\n    )\n    // Step 5. generate Order, please read validateNFTOrder\n    const makerOrder: sdk.NFTOrderRequestV3 = {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      accountId: accInfo.accountId,\n      storageId: storageId.orderId,\n      sellToken: {\n        tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n        nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n        amount: '1',\n      },\n      buyToken: {\n        tokenId: TOKEN_INFO.tokenMap['LRC'].tokenId,\n        amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n      },\n      allOrNone: false,\n      fillAmountBOrS: false,\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      maxFeeBips: 1000,\n    }\n    const makerOrderEddsaSignature = sdk.get_EddsaSig_NFT_Order(makerOrder, eddsaKey.sk).result\n\n    const takerOrder: sdk.NFTOrderRequestV3 = {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      accountId: accInfo2.accountId,\n      storageId: storageId2.orderId,\n      sellToken: {\n        tokenId: TOKEN_INFO.tokenMap['LRC'].tokenId,\n        amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n      },\n      buyToken: {\n        tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n        nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n        amount: '1',\n      },\n      allOrNone: false,\n      fillAmountBOrS: true,\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      maxFeeBips: 100,\n    }\n    const takerOrderEddsaSignature = sdk.get_EddsaSig_NFT_Order(takerOrder, eddsaKey2.sk).result\n\n    mockData = {\n      takerOrder,\n      takerOrderEddsaSignature,\n      makerOrder,\n      makerOrderEddsaSignature,\n      makerFeeBips: 1000,\n      maxFeeBips: 100,\n    }\n  }, DEFAULT_TIMEOUT * 3)\n  it(\n    'tradeNFT',\n    async () => {\n      jest.useFakeTimers('legacy')\n      // private or third account can signature and approve this order\n      try {\n        myLog(\n          mockData,\n          'mockData.makerOrder',\n          mockData.makerOrder,\n          'mockData.takerOrder',\n          mockData.takerOrder,\n        )\n        // Step 1. getAccount\n        // const accInfoC = (\n        //   await LoopringAPI.exchangeAPI.getAccount({\n        //     owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        //   })\n        // ).accInfo;\n\n        // Step 2. eddsaKeyC\n        // const eddsaKeyC = await signatureKeyPairMock(accInfoC, web3);\n        myLog('accInfoC.accountId', accInfoC.accountId, 'eddsaKeyC', eddsaKeyC)\n        // Step 3. apiKey\n        const apiKeyC = (\n          await LoopringAPI.userAPI.getUserApiKey(\n            {\n              accountId: accInfoC.accountId,\n            },\n            eddsaKeyC.sk,\n          )\n        ).apiKey\n        myLog(\n          'mockData.makerOrder',\n          mockData.makerOrder,\n          'mockData.takerOrder',\n          mockData.takerOrder,\n        )\n        //  NFT Trade\n        const response = await LoopringAPI.userAPI.submitNFTTrade({\n          request: {\n            maker: {\n              ...mockData.makerOrder,\n              eddsaSignature: mockData.makerOrderEddsaSignature,\n            },\n            makerFeeBips: 1000,\n            taker: {\n              ...mockData.takerOrder,\n              eddsaSignature: mockData.takerOrderEddsaSignature,\n            },\n            takerFeeBips: 100,\n          },\n          web3,\n          chainId: sdk.ChainId.GOERLI,\n          walletType: sdk.ConnectorNames.Unknown,\n          apiKey: apiKeyC,\n          eddsaKey: eddsaKeyC.sk,\n        })\n\n        console.log(response)\n      } catch (e) {\n        console.log(e)\n      }\n    },\n    DEFAULT_TIMEOUT * 4,\n  )\n})\n"
  },
  {
    "path": "src/tests/demo/NFTAction/validateNFTOrder.md",
    "content": "# Validate NFT Order\n\nDefinition: Loopring L2 support a method help for Validate NFT one side Order, validate NFT Order is not required for\nLoopring, but when make NFT Trade, it should pass this validation\n\n## SellNFTByERC20\n\n```ts\n// Step 1. getAccount\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. apiKey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n// Step 4. storageId\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n// let hash: any = new BN(nftId,'hex')\n// hash = toHex(hash);//new BigInteger(sha256(nftId.toString()).toString(), 16)\n\n// Step 5. submitNFTValidateOrder\nconst response = await LoopringAPI.userAPI.submitNFTValidateOrder({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: accInfo.accountId,\n    storageId: storageId.orderId,\n    sellToken: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    buyToken: {\n      tokenId: 1,\n      amount: \"10000000000000\",\n    },\n    allOrNone: false,\n    fillAmountBOrS: false,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    maxFeeBips: 1000,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n\nconsole.log(\"sellNFT NFTOrderRequestV3:\", response);\n```\n\n***\n\n## BuyNFTByERC20\n\n```ts\n // Step 1. getAccount\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. apiKey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n// Step 5. submitNFTValidateOrder\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n\nconst response = await LoopringAPI.userAPI.submitNFTValidateOrder({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: accInfo.accountId,\n    storageId: storageId.orderId,\n    sellToken: {\n      tokenId: 1,\n      amount: \"10000000000000\",\n    },\n    buyToken: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    fillAmountBOrS: true,\n    allOrNone: false,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    maxFeeBips: 100,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\n```\n\n"
  },
  {
    "path": "src/tests/demo/NFTAction/validateNFTOrder.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\ndescribe(\"validateNFTOrder\", function () {\n  it(\n    \"sellNFTByERC20\",\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n      // let hash: any = new BN(nftId,'hex')\n      // hash = toHex(hash);//new BigInteger(sha256(nftId.toString()).toString(), 16)\n\n      // Step 5. submitNFTValidateOrder\n      const response = await LoopringAPI.userAPI.submitNFTValidateOrder({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          accountId: accInfo.accountId,\n          storageId: storageId.orderId,\n          sellToken: {\n            tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n            nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n            amount: \"1\",\n          },\n          buyToken: {\n            tokenId: 1,\n            amount: \"10000000000000\",\n          },\n          allOrNone: false,\n          fillAmountBOrS: false,\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n          maxFeeBips: 1000,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        eddsaKey: eddsaKey.sk,\n        apiKey: apiKey,\n      });\n\n      console.log(\"sellNFT NFTOrderRequestV3:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"buyNFTByERC20\",\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 5. submitNFTValidateOrder\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n\n      const response = await LoopringAPI.userAPI.submitNFTValidateOrder({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          accountId: accInfo.accountId,\n          storageId: storageId.orderId,\n          sellToken: {\n            tokenId: 1,\n            amount: \"10000000000000\",\n          },\n          buyToken: {\n            tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n            nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n            amount: \"1\",\n          },\n          fillAmountBOrS: true,\n          allOrNone: false,\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n          maxFeeBips: 100,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        eddsaKey: eddsaKey.sk,\n        apiKey: apiKey,\n      });\n      console.log(\"buyNFT NFTOrderRequestV3:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/account/account.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  signatureKeyPairMock,\n  TOKEN_INFO,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\n/*\n * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n */\ndescribe(\"Account\", function () {\n  it(\n    \"getAccount\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\"getWalletType\", async () => {\n    const [\n      { walletType: CFWalletType },\n      { walletType: EOAWalletType },\n      { walletType: ContractWalletType },\n    ] = await Promise.all([\n      LoopringAPI.walletAPI.getWalletType({\n        wallet: LOOPRING_EXPORTED_ACCOUNT.addressCF,\n      }),\n      LoopringAPI.walletAPI.getWalletType({\n        wallet: LOOPRING_EXPORTED_ACCOUNT.address,\n      }),\n      LoopringAPI.walletAPI.getWalletType({\n        wallet: LOOPRING_EXPORTED_ACCOUNT.addressContractWallet,\n      }),\n    ]);\n    console.log(\n      \"CFWalletType, EOAWalletType, ContractWalletType\",\n      CFWalletType,\n      EOAWalletType,\n      ContractWalletType\n    );\n  });\n\n  it(\n    \"getAllowances\",\n    async () => {\n      const { tokenAllowances } = await LoopringAPI.exchangeAPI.getAllowances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        token: [\n          TOKEN_INFO.tokenMap.LRC.address,\n          TOKEN_INFO.tokenMap.DAI.address,\n        ],\n      });\n      console.log(\n        \"getAllowances:\",\n        tokenAllowances.get(TOKEN_INFO.tokenMap.LRC.address),\n        tokenAllowances.get(TOKEN_INFO.tokenMap.DAI.address)\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getUserApiKey\",\n    async () => {\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getEthNonce\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getEthNonce({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"getEthNonce:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"Layer1_ETH_Balance\",\n    async () => {\n      const { ethBalance } = await LoopringAPI.exchangeAPI.getEthBalances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(`Layer1 ethBalance: ${ethBalance}`);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"Layer1_ERC20_Balance\",\n    async () => {\n      const { tokenBalances } = await LoopringAPI.exchangeAPI.getTokenBalances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        token: [TOKEN_INFO.tokenMap.LRC.address],\n      });\n      console.log(\n        `Layer1 ERC20 Balance LRC: ${tokenBalances.get(\n          TOKEN_INFO.tokenMap.LRC.address as unknown as sdk.TokenAddress\n        )}`\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\"Layer1_getNFTBalance\", async () => {\n    const response = await LoopringAPI.nftAPI.getNFTBalance({\n      web3,\n      account: LOOPRING_EXPORTED_ACCOUNT.address,\n      tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n      nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n      nftType: sdk.NFTType.ERC1155,\n    });\n    console.log(response);\n  });\n\n  it(\n    \"Layer2_getUserBalances\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. getUserBalances\n      const { userBalances } = await LoopringAPI.userAPI.getUserBalances(\n        { accountId: LOOPRING_EXPORTED_ACCOUNT.accountId, tokens: \"\" },\n        apiKey\n      );\n\n      console.log(`Layer2 ERC20 Balance: ${userBalances}`);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"Layer2_getUserNFTBalances\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. getUserNFTBalances\n      const { userNFTBalances } = await LoopringAPI.userAPI.getUserNFTBalances(\n        { accountId: accInfo.accountId, limit: 20 },\n        apiKey\n      );\n      console.log(`Layer2 NFT Balance: ${userNFTBalances}`);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getCounterFactualInfo\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getCounterFactualInfo({\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountIdCF,\n      });\n      console.log(\"getCounterFactualInfo\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/account/activeAccount.md",
    "content": "# Active Account\n\nDefinition: After user Deposit or (Third-Part Transfer), how to active Loopring L2 account.\n\n***\n\n## Step 1. get account info\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\n```\n\n***\n\n## Step 2. use keySeed or CUSTOMER_KEY_SEED generateKeyPair\n\n```ts\nconst keySeed = sdk.BaseAPI.KEY_MESSAGE.replace(\n      \"${exchangeAddress}\",\n      LOOPRING_EXPORTED_ACCOUNT.exchangeAddress\n    ).replace(\"${nonce}\", accInfo.nonce.toString());\nconst eddsaKey = await sdk.generateKeyPair({\n  web3,\n  address: accInfo.owner,\n  keySeed,\n  walletType: sdk.ConnectorNames.MetaMask,\n  chainId: sdk.ChainId.GOERLI,\n});\nconsole.log(\"eddsakey:\", eddsaKey.sk);\n```\n\nOr\n\n```ts\n// CUSTOMER_KEY_SEED = \"XXXXXX\" + \" with key nonce: \" + \"${nonce}\";\nconst keySeed = CUSTOMER_KEY_SEED.replace(\n  \"${nonce}\",\n  accInfo.nonce.toString()\nconst eddsaKey = await sdk.generateKeyPair({\n  web3,\n  address: accInfo.owner,\n  keySeed,\n  walletType: sdk.ConnectorNames.MetaMask,\n  chainId: sdk.ChainId.GOERLI,\n});\nconsole.log(\"eddsakey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. get fee\n\n```ts\nconst fee = await LoopringAPI.globalAPI.getActiveFeeInfo({\n  accountId: accInfo.accountId,\n});\nconsole.log(\"fee:\", fee);\n```  \n\n***\n\n## Step 4. updateAccount (active or rest）\n\n```ts\n      const result = await LoopringAPI.userAPI.updateAccount({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    owner: accInfo.owner,\n    accountId: accInfo.accountId,\n    publicKey: {x: eddsaKey.formatedPx, y: eddsaKey.formatedPy},\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    keySeed,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    nonce: accInfo.nonce as number,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  isHWAddr: false,\n});\n\nconst {accInfo: updateAccountInfo} =\n  await LoopringAPI.exchangeAPI.getAccount({\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  });\nconsole.log(\n  \"updateAccount Result: \",\n  result,\n  \"updateAccountInfo:\",\n  updateAccountInfo\n);\n```"
  },
  {
    "path": "src/tests/demo/account/activeAccount.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  TOKEN_INFO,\n  web3,\n  CUSTOMER_KEY_SEED,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\n/*\n * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddressess\n * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n */\ndescribe(\"ActiveAccount\", function () {\n  it(\n    \"updateAccount\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n\n      // Step 2. use keySeed generateKeyPair\n      const keySeed = sdk.BaseAPI.KEY_MESSAGE.replace(\n        \"${exchangeAddress}\",\n        LOOPRING_EXPORTED_ACCOUNT.exchangeAddress\n      ).replace(\"${nonce}\", accInfo.nonce.toString());\n      const eddsaKey = await sdk.generateKeyPair({\n        web3,\n        address: accInfo.owner,\n        keySeed,\n        walletType: sdk.ConnectorNames.MetaMask,\n        chainId: sdk.ChainId.GOERLI,\n      });\n      console.log(\"eddsakey:\", eddsaKey.sk);\n\n      // Step 3. fee\n      const fee = await LoopringAPI.globalAPI.getActiveFeeInfo({\n        accountId: accInfo.accountId,\n      });\n      console.log(\"fee:\", fee);\n\n      // Step 4. updateAccount (active or rest）\n      const result = await LoopringAPI.userAPI.updateAccount({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          owner: accInfo.owner,\n          accountId: accInfo.accountId,\n          publicKey: { x: eddsaKey.formatedPx, y: eddsaKey.formatedPy },\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n            volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n          },\n          keySeed,\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n          nonce: accInfo.nonce as number,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        isHWAddr: false,\n      });\n      const { accInfo: updateAccountInfo } =\n        await LoopringAPI.exchangeAPI.getAccount({\n          owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        });\n      console.log(\n        \"updateAccount Result: \",\n        result,\n        \"updateAccountInfo:\",\n        updateAccountInfo\n      );\n    },\n    DEFAULT_TIMEOUT * 2\n  );\n\n  it(\n    \"customer_keySeed\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n\n      // Step 2. use keySeed generateKeyPair\n      const keySeed = CUSTOMER_KEY_SEED.replace(\n        \"${nonce}\",\n        accInfo.nonce.toString()\n      );\n      const eddsaKey = await sdk.generateKeyPair({\n        web3,\n        address: accInfo.owner,\n        keySeed,\n        walletType: sdk.ConnectorNames.MetaMask,\n        chainId: sdk.ChainId.GOERLI,\n      });\n      console.log(\"eddsakey:\", eddsaKey.sk);\n\n      // Step 3. fee\n      const fee = await LoopringAPI.globalAPI.getActiveFeeInfo({\n        accountId: accInfo.accountId,\n      });\n      console.log(\"fee:\", fee);\n\n      // Step 4. updateAccount (active or rest）\n      const result = await LoopringAPI.userAPI.updateAccount({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          owner: accInfo.owner,\n          accountId: accInfo.accountId,\n          publicKey: { x: eddsaKey.formatedPx, y: eddsaKey.formatedPy },\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n            volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n          },\n          keySeed,\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n          nonce: accInfo.nonce as number,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        isHWAddr: false,\n      });\n\n      const { accInfo: updateAccountInfo } =\n        await LoopringAPI.exchangeAPI.getAccount({\n          owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        });\n      console.log(\n        \"updateAccount Result: \",\n        result,\n        \"updateAccountInfo:\",\n        updateAccountInfo,\n        \"keySeed:\",\n        updateAccountInfo.keySeed\n      );\n    },\n    DEFAULT_TIMEOUT * 2\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/account/fee.md",
    "content": "# Fee\n\nLoopring have 2 get Fee api:\n\n- getOffchainFeeAmt:\n  - `ORDER`,\n  - `FFCHAIN_WITHDRAWAL`,\n  - `UPDATE_ACCOUNT`,\n  - `TRANSFER`,\n  - `FAST_OFFCHAIN_WITHDRAWAL`,\n  - `OPEN_ACCOUNT`,\n  - `AMM_EXIT`,\n  - `DEPOSIT`,\n  - `AMM_JOIN`,\n- getNFTOffchainFeeAmt:\n  - `NFT_MINT`,\n  - `NFT_WITHDRAWAL`,\n  - `NFT_TRANSFER`,\n  - `NFT_DEPLOY`,\n\n***\n\n## Fee: updateAccount\n\n```ts\n    // Step 1. get account info\nconsole.log(LoopringAPI.exchangeAPI.getAccount);\n\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\n\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.UPDATE_ACCOUNT,\n  },\n  apiKey\n);\nconsole.log(\"updateAccount:\", response);\n```\n\n***\n\n## Fee: transfer\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.TRANSFER,\n  },\n  apiKey\n);\nconsole.log(\"transfer:\", response);\n```\n\n***\n\n## Fee: withdraw\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n    requestType: sdk.OffchainFeeReqType.OFFCHAIN_WITHDRAWAL,\n  },\n  apiKey\n);\nconsole.log(\"withdraw:\", response);\n```\n\n***\n\n## Fee: fastWithdraw\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.FAST_OFFCHAIN_WITHDRAWAL,\n    tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n  },\n  apiKey\n);\nconsole.log(\"fastWithdraw:\", response);\n```\n\n***\n\n## Fee: order\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.ORDER,\n    tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n  },\n  apiKey\n);\nconsole.log(\"order:\", response);\n```\n\n***\n\n## Fee: amm_exit\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.AMM_EXIT,\n  },\n  apiKey\n);\nconsole.log(\"amm_exit:\", response);\n```\n\n***\n\n## Fee: amm_join\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.AMM_JOIN,\n  },\n  apiKey\n);\nconsole.log(\"amm_join:\", response);\n```\n\n***\n\n## Fee: NFT Transfer\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_TRANSFER,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  },\n  apiKey\n);\nconsole.log(\"NFTTransfer:\", response);\n```\n\n***\n\n## Fee: NFT Withdrawal\n\n```ts\n    // Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nreturn {accInfo, eddsaKey, apiKey};\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_WITHDRAWAL,\n  },\n  apiKey\n);\nconsole.log(\"NFTWithdrawal:\", response);\n```\n\n## Fee: NFT Mint\n\n```ts\n// Step 1. get account info\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress\n  },\n  apiKey\n);\nconsole.log(\"NFTWithdrawal:\", response);\n\n```\n\n## Fee: NFT Deploy\n\n```ts \n// Step 1. get account info \nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount(\n  {owner: LOOPRING_EXPORTED_ACCOUNT.address,});\nconsole.log(\"accInfo:\", accInfo);\n\n// Step 2. eddsaKey\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n// Step 3. get apikey\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_DEPLOY,\n  },\n  apiKey\n);\nconsole.log(\"NFTWithdrawal:\", response);\n```\n\n***\n\n## getActiveFeeInfo without apikey & accountId\n\n```ts\nconst response = await LoopringAPI.globalAPI.getActiveFeeInfo({});\n```\n\n***\n\n## getActiveFeeInfo without apikey with accountId\n\n```ts\n const response = await\n  LoopringAPI.globalAPI.getActiveFeeInfo({accountId: LOOPRING_EXPORTED_ACCOUNT.accountId});\n```\n\n"
  },
  {
    "path": "src/tests/demo/account/fee.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  signatureKeyPairMock,\n  TOKEN_INFO,\n  LoopringAPI,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\n/*\n * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress = exchangeInfo.exchangeAddress\n * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n */\ndescribe(\"Fee\", function () {\n  it(\n    \"fee:updateAccount\",\n    async () => {\n      // Step 1. get account info\n      console.log(LoopringAPI.exchangeAPI.getAccount);\n\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.UPDATE_ACCOUNT,\n        },\n        apiKey\n      );\n      console.log(\"updateAccount:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"fee:transfer\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.TRANSFER,\n        },\n        apiKey\n      );\n      console.log(\"transfer:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"fee:withdraw\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n          requestType: sdk.OffchainFeeReqType.OFFCHAIN_WITHDRAWAL,\n        },\n        apiKey\n      );\n      console.log(\"withdraw:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"fee:fastWithdraw\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.FAST_OFFCHAIN_WITHDRAWAL,\n          tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n        },\n        apiKey\n      );\n      console.log(\"fastWithdraw:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"fee:order\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.ORDER,\n          tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n        },\n        apiKey\n      );\n      console.log(\"order:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"fee:amm_exit\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.AMM_EXIT,\n        },\n        apiKey\n      );\n      console.log(\"amm_exit:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"fee:amm_join\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.AMM_JOIN,\n        },\n        apiKey\n      );\n      console.log(\"amm_join:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"fee:NFTTransfer\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      return { accInfo, eddsaKey, apiKey };\n      const response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_TRANSFER,\n        },\n        apiKey\n      );\n      console.log(\"NFTTransfer:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"fee:NFTWithdrawal\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      const response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_WITHDRAWAL,\n          tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n        },\n        apiKey\n      );\n      console.log(\"NFTWithdrawal:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"fee:NFTMint\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      const response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_MINT,\n          tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n        },\n        apiKey\n      );\n      console.log(\"NFTWithdrawal:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"fee:NFTDeploy\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n      const response = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_DEPLOY,\n        },\n        apiKey\n      );\n      console.log(\"NFTWithdrawal:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getActiveFeeInfo without apikey & accountId\",\n    async () => {\n      const response = await LoopringAPI.globalAPI.getActiveFeeInfo({});\n      console.log(\"updateAccount without apikey & accountId:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getActiveFeeInfo without apikey with accountId\",\n    async () => {\n      const response = await LoopringAPI.globalAPI.getActiveFeeInfo({\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      });\n      console.log(\"updateAccount without apikey with accountId:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/account/historyRecord.md",
    "content": "# User Actions History\nFor check account Actions, more detail such as filters please read SDK interface or API .\n\n***\n\n## getUserTrades\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getUserTrades(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      offset: 0,\n      limit: 20,\n      fillTypes: sdk.TradesFillTypes.dex,\n    },\n    apiKey\n  );\n  console.log(\"getUserTrades:\", result);\n  ```\n\n***\n\n## getUserTxs\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getUserTxs(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      types: [\n        sdk.UserTxTypes.DEPOSIT,\n        sdk.UserTxTypes.TRANSFER,\n        sdk.UserTxTypes.ONCHAIN_WITHDRAWAL,\n      ],\n    },\n    apiKey\n  );\n  console.log(\"getUserTxs:\", result);\n  ```\n\n***\n\n## getUserNFTTransactionHistory\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getUserNFTTransactionHistory(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      types: [\n        sdk.UserNFTTxTypes.DEPOSIT,\n        sdk.UserNFTTxTypes.TRANSFER,\n        sdk.UserNFTTxTypes.WITHDRAW,\n        sdk.UserNFTTxTypes.MINT,\n      ],\n    },\n    apiKey\n  );\n  console.log(\"getUserNFTTransactionHistory:\", result);\n  ```\n\n***\n\n## getOrders\n\n```ts \n  async () => {\n  const result = await LoopringAPI.userAPI.getOrders(\n    {\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      orderTypes: sdk.OrderType.LimitOrder,\n    },\n    apiKey\n  );\n\n  console.log(\"getOrders:\", result);\n  ```\n"
  },
  {
    "path": "src/tests/demo/account/historyRecord.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\nlet apiKey = \"\";\ndescribe(\"historyRecord\", function () {\n  beforeEach(async () => {\n    // Step 1. getAccount\n    const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n      owner: LOOPRING_EXPORTED_ACCOUNT.address,\n    });\n    console.log(\"accInfo:\", accInfo);\n\n    // Step 2. eddsaKey\n    const eddsaKey = await signatureKeyPairMock(accInfo);\n    console.log(\"eddsaKey:\", eddsaKey.sk);\n\n    // Step 3. apiKey\n    apiKey = (\n      await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      )\n    ).apiKey;\n    console.log(\"apiKey:\", apiKey);\n  }, DEFAULT_TIMEOUT);\n\n  it(\n    \"getUserTrades\",\n    async () => {\n      const result = await LoopringAPI.userAPI.getUserTrades(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          offset: 0,\n          limit: 20,\n          fillTypes: sdk.TradesFillTypes.dex,\n        },\n        apiKey\n      );\n      console.log(\"getUserTrades:\", result);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getUserTxs\",\n    async () => {\n      const result = await LoopringAPI.userAPI.getUserTxs(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          types: [\n            sdk.UserTxTypes.DEPOSIT,\n            sdk.UserTxTypes.TRANSFER,\n            sdk.UserTxTypes.OFFCHAIN_WITHDRAWAL,\n          ],\n        },\n        apiKey\n      );\n      console.log(\"getUserTxs:\", result);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getUserNFTTransactionHistory\",\n    async () => {\n      const result = await LoopringAPI.userAPI.getUserNFTTransactionHistory(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          types: [\n            sdk.UserNFTTxTypes.DEPOSIT,\n            sdk.UserNFTTxTypes.TRANSFER,\n            sdk.UserNFTTxTypes.WITHDRAW,\n            sdk.UserNFTTxTypes.MINT,\n          ],\n        },\n        apiKey\n      );\n      console.log(\"getUserNFTTransactionHistory:\", result);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getOrders\",\n    async () => {\n      const result = await LoopringAPI.userAPI.getOrders(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          orderTypes: sdk.OrderType.LimitOrder,\n        },\n        apiKey\n      );\n\n      console.log(\"getOrders:\", result);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/account/signature.md",
    "content": "# Signature\n\nLoopring SDK support EOA (EOA hardware wallet) & Loopring Smart wallet Signature\n\n- For Browser extension, Dapp, Hardware wallet we only support for EOA\n- For Loopring Smart wallet (App), Provider gateway only can be walletConnect\n\n## Follow is the provider gateway we inject & test:\n\n- MetaMask  (Ledger, Trezor)\n- WalletConnect (Authereum, Loopring Smart wallet )\n- Coinbase\n- [Coming soon...](https://desk.zoho.com/portal/loopring/en/newticket)\n\n## For signature:\n\nFor eth_sign signing types (eth_sign, personal_sign, v1, v3, v4)\n\n### EOA:\n\n- For Browser\n  extension ([More information: signing-data](https://docs.metamask.io/guide/signing-data.html#a-brief-history))\n  + common EOA we use the `v4` signature and `web3.eth.personal.ecRecover` validate signature\n  + when `v4` signature is failed for any step, we will try `personal_sign` and `web3.eth.personal.ecRecover` validate\n    signature\n- For Dapp\n  + when loopring Dex is inside Dapp Webview & connect by `window.ethereum`, we remove the `web3.eth.personal.ecRecover`\n    validate\n\n### Loopring Smart wallet:\n\n- For Smart wallet we send `eth_signTypedData` by walletConnect & validate\n  ABI.Contracts.ContractWallet.encodeInputs `isValidSignature(bytes32,bytes)`\n\n### Loopring Counterfactual wallet:\n\n- signature is same as Smart wallet\n- But ecRecover is by\n  walletOwner, `const {walletOwner} = await LoopringAPI.exchangeAPI.getCounterFactualInfo({ accountId: LOOPRING_EXPORTED_ACCOUNT.accountIdCF, });`\n\n***\n\n## generateKeyPair\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst result = await signatureKeyPairMock(accInfo);\nconsole.log(result.sk);\n```\n\n***\n\n## getEcDSASig: eth_signTypedData_v4\n\n```ts\n// test case is not allow brock by Mock provider\nconst result = await sdk.getEcDSASig(\n  web3,\n  testTypedData,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  sdk.GetEcDSASigType.HasDataStruct,\n  sdk.ChainId.GOERLI,\n  LOOPRING_EXPORTED_ACCOUNT.accountId,\n  \"\",\n  sdk.ConnectorNames.Unknown\n);\nconsole.log(\"getEcDSASig:eth_signTypedData_v4\",\n  result,\n  \"ecdsaSig+sdk.SigSuffix.Suffix02\",\n  result.ecdsaSig + sdk.SigSuffix.Suffix02\n);\n```\n\n***\n\n## getEcDSASig: personalSign(WithoutDataStruct--Hardware wallet)\n\n```ts\nconst result = await sdk.getEcDSASig(\n  web3,\n  testTypedData,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  sdk.GetEcDSASigType.WithoutDataStruct,\n  sdk.ChainId.GOERLI,\n  LOOPRING_EXPORTED_ACCOUNT.accountId,\n  \"\",\n  sdk.ConnectorNames.Unknown\n);\nconsole.log(\n  \"getEcDSASig:WithoutDataStruct(personalSign)\",\n  result,\n  \"ecdsaSig+sdk.SigSuffix.Suffix03\",\n  result.ecdsaSig + sdk.SigSuffix.Suffix03\n);\n```\n\n***\n\n## getEcDSASig: personalSign(Contract)\n\n```ts\n// test case is not allow brock by Mock provider\nconst result = await sdk.getEcDSASig(\n  web3,\n  testTypedData,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  sdk.GetEcDSASigType.Contract,\n  sdk.ChainId.GOERLI,\n  LOOPRING_EXPORTED_ACCOUNT.accountId,\n  \"\",\n  sdk.ConnectorNames.Unknown\n);\nconsole.log(\n  \"getEcDSASig:personalSign(Contract)\",\n  result\n);\n```\n\n## Validate signature\n\n[github: src/api/base_api.ts#personalSign](https://github.com/Loopring/loopring_sdk/blob/2c79c1837114f4f383e2d292de3da4b2dac02252/src/api/base_api.ts#L549)\n\n```\n export async function personalSign(\n  web3: any,\n  account: string | undefined,\n  pwd: string,\n  msg: string,\n  walletType: ConnectorNames,\n  chainId: ChainId,\n  accountId?: number,\n  counterFactualInfo?: CounterFactualInfo,\n  isMobile?: boolean\n) {\n  if (!account) {\n    return { error: \"personalSign got no account\" };\n  }\n\n  return new Promise((resolve) => {\n    try {\n      web3.eth.personal.sign(\n        msg,\n        account,\n        pwd,\n        async function (err: any, result: any) {\n          if (!err) {\n            // Valid:1. counter Factual signature Valid\n            if (counterFactualInfo && accountId) {\n              myLog(\"fcWalletValid counterFactualInfo accountId:\");\n              const fcValid = await fcWalletValid(\n                web3,\n                account,\n                msg,\n                result,\n                accountId,\n                chainId,\n                counterFactualInfo\n              );\n              if (fcValid.result) {\n                resolve({\n                  sig: result,\n                  counterFactualInfo: fcValid.counterFactualInfo,\n                });\n                return;\n              }\n            }\n\n            // Valid: 2. webview directory signature Valid\n            if (\n              (window?.ethereum?.isImToken || window?.ethereum?.isMetaMask) &&\n              isMobile &&\n              // Mobile directory connect will sign ConnectorNames as MetaMask only\n              walletType === ConnectorNames.MetaMask\n            ) {\n              const address: string[] = await window.ethereum?.request({\n                method: \"eth_requestAccounts\",\n              });\n              if (\n                address?.find(\n                  (item) => item.toLowerCase() === account.toLowerCase()\n                )\n              ) {\n                return resolve({ sig: result });\n              }\n            }\n\n            // Valid: 3. EOA signature Valid by ecRecover\n            const valid: any = await ecRecover(web3, account, msg, result);\n            if (valid.result) {\n              return resolve({ sig: result });\n            }\n\n            // Valid: 4. contractWallet signature Valid `isValidSignature(bytes32,bytes)`\n            const walletValid2: any = await contractWalletValidate32(\n              web3,\n              account,\n              msg,\n              result\n            );\n\n            if (walletValid2.result) {\n              return resolve({ sig: result });\n            }\n\n            // Valid: 5. counter Factual signature Valid when no counterFactualInfo\n            if (accountId) {\n              const fcValid = await fcWalletValid(\n                web3,\n                account,\n                msg,\n                result,\n                accountId,\n                chainId\n              );\n              if (fcValid.result) {\n                return resolve({\n                  sig: result,\n                  counterFactualInfo: fcValid.counterFactualInfo,\n                });\n              }\n            }\n\n            // Valid: 6. myKeyValid Valid again\n            const myKeyValid: any = await mykeyWalletValid(\n              web3,\n              account,\n              msg,\n              result\n            );\n\n            if (myKeyValid.result) {\n              return resolve({ sig: result });\n            }\n\n            // Valid: Error cannot pass personalSign Valid\n            // eslint-disable-next-line no-console\n            console.log(\n              \"web3.eth.personal.sign Valid, valid 5 ways, all failed!\"\n            );\n            return resolve({\n              error: \"web3.eth.personal.sign Valid, valid 5 ways, all failed!\",\n            });\n          } else {\n            return resolve({\n              error: \"personalSign err before Validate:\" + err,\n            });\n          }\n        }\n      );\n    } catch (reason) {\n      resolve({ error: reason });\n    }\n  });\n}\n```"
  },
  {
    "path": "src/tests/demo/account/signature.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  signatureKeyPairMock,\n  testTypedData,\n  web3,\n} from '../../MockData'\nimport * as sdk from '../../../index'\n\ndescribe('signature', function () {\n  it(\n    'generateKeyPair',\n    async () => {\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n      const result = await signatureKeyPairMock(accInfo)\n      console.log(result.sk)\n    },\n    DEFAULT_TIMEOUT,\n  )\n  /**\n   * test case is not allow brock by Mock provider\n   */\n  // it(\n  //   \"getEcDSASig:eth_signTypedData_v4\",\n  //   async () => {\n  //     // test case is not allow brock by Mock provider\n  //     const result = await sdk.getEcDSASig(\n  //       web3,\n  //       testTypedData,\n  //       LOOPRING_EXPORTED_ACCOUNT.address,\n  //       sdk.GetEcDSASigType.HasDataStruct,\n  //       sdk.ChainId.GOERLI,\n  //       LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //       \"\",\n  //       sdk.ConnectorNames.Unknown\n  //     );\n  //     console.log(\n  //       \"getEcDSASig:eth_signTypedData_v4\",\n  //       result,\n  //       \"ecdsaSig+sdk.SigSuffix.Suffix02\",\n  //       result.ecdsaSig + sdk.SigSuffix.Suffix02\n  //     );\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n\n  it('getEcDSASig:WithoutDataStruct(personalSign)', async () => {\n    const result = await sdk.getEcDSASig(\n      web3,\n      testTypedData,\n      LOOPRING_EXPORTED_ACCOUNT.address,\n      sdk.GetEcDSASigType.WithoutDataStruct,\n      sdk.ChainId.GOERLI,\n      LOOPRING_EXPORTED_ACCOUNT.accountId,\n      '',\n      sdk.ConnectorNames.Unknown,\n    )\n    console.log('getEcDSASig:WithoutDataStruct(personalSign)', result)\n  })\n  /**\n   * test case is not allow brock by Mock provider\n   */\n  // it(\"personalSign Contract\", async () => {\n  //   await sdk.getEcDSASig(\n  //     web3,\n  //     testTypedData,\n  //     LOOPRING_EXPORTED_ACCOUNT.address,\n  //     sdk.GetEcDSASigType.Contract,\n  //     sdk.ChainId.GOERLI,\n  //     LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //     \"\",\n  //     sdk.ConnectorNames.Unknown\n  //   );\n  // });\n})\n\nexport default {}\n"
  },
  {
    "path": "src/tests/demo/deposit/deposit.md",
    "content": "# Deposit ERC20\n\nDefinition: Move user L1 ERC20 assets to Loopring L2\n> **All Deposit Method, User should have enough `ETH` pay for the Ethereum Gas (Loopring have no charge, no fee for Deposit).**\n\nProvider will give the Gas Price & Limit, sdk also have a method get gasPrice:\n`const gasPrice = (await LoopringAPI.exchangeAPI.getGasPrice() ).gasPrice;`\n\n# ETH\n\n***\n\n## Step 1. getNonce\n\n```ts\nconst nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\nconsole.log(\n  `deposit: ${TOKEN_INFO.tokenMap.ETH.symbol}-${LOOPRING_EXPORTED_ACCOUNT.tradeETHValue}, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n);\n```\n\n***\n\n## Step 2. deposit\n\n```ts\nconst response = await sdk.deposit(\n  web3,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  TOKEN_INFO.tokenMap.ETH,\n  LOOPRING_EXPORTED_ACCOUNT.tradeETHValue,\n  0,\n  LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n  sdk.ChainId.GOERLI,\n  nonce,\n  true\n);\n\nconsole.log(`nonce: ${nonce} deposit_ETH: `, response);\n```\n\n# ERC20\n\n***\n\n## Step 1. getAllowances\n\n```ts\nconst {tokenAllowances} = await LoopringAPI.exchangeAPI.getAllowances({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  token: [TOKEN_INFO.tokenMap.LRC.address],\n});\nif (\n  tokenAllowances.has(TOKEN_INFO.tokenMap.LRC.address) &&\n  Number(tokenAllowances.get(TOKEN_INFO.tokenMap.LRC.address)) <\n  LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue\n) {\n  const nonce = await web3.eth.getTransactionCount(\n    LOOPRING_EXPORTED_ACCOUNT.address\n  );\n  await sdk.approveMax(\n    web3,\n    LOOPRING_EXPORTED_ACCOUNT.address,\n    TOKEN_INFO.tokenMap.LRC.address, // LRC address  {tokenIdMap} = getTokens();  tokenIdMap['LRC']\n    LOOPRING_EXPORTED_ACCOUNT.depositAddress, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.depositAddress\n    LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n    LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n    sdk.ChainId.GOERLI,\n    nonce,\n    true\n  );\n}\n```\n\n***\n\n## Step 2. getNonce\n\n```ts\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\nconsole.log(\n  `deposit: ${TOKEN_INFO.tokenMap.LRC.symbol}-${LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue}, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n);\n```\n\n***\n\n## Step 3. deposit\n\n```ts\n      const response = await sdk.deposit(\n  web3,\n  LOOPRING_EXPORTED_ACCOUNT.address,\n  LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  TOKEN_INFO.tokenMap.LRC,\n  sdk\n    .toBig(LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue)\n    .div(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)\n    .toNumber(),\n  0,\n  LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n  sdk.ChainId.GOERLI,\n  nonce,\n  true\n);\n\nconsole.log(`nonce: ${nonce}  deposit_LRC: `, response);\n```    \n\n"
  },
  {
    "path": "src/tests/demo/deposit/deposit.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\ndescribe(\"deposit\", function () {\n  beforeEach(async () => {\n    jest.setTimeout(DEFAULT_TIMEOUT * 3);\n\n    LOOPRING_EXPORTED_ACCOUNT.gasPrice = (\n      await LoopringAPI.exchangeAPI.getGasPrice()\n    ).gasPrice;\n  }, DEFAULT_TIMEOUT);\n  it(\n    \"deposit_LRC\",\n    async () => {\n      // step1: getAllowances\n      const { tokenAllowances } = await LoopringAPI.exchangeAPI.getAllowances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        token: [TOKEN_INFO.tokenMap.LRC.address],\n      });\n      if (\n        tokenAllowances.has(TOKEN_INFO.tokenMap.LRC.address) &&\n        Number(tokenAllowances.get(TOKEN_INFO.tokenMap.LRC.address)) <\n          LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue\n      ) {\n        const nonce = await web3.eth.getTransactionCount(\n          LOOPRING_EXPORTED_ACCOUNT.address\n        );\n        await sdk.approveMax(\n          web3,\n          LOOPRING_EXPORTED_ACCOUNT.address,\n          TOKEN_INFO.tokenMap.LRC.address, // LRC address  {tokenIdMap} = getTokens();  tokenIdMap['LRC']\n          LOOPRING_EXPORTED_ACCOUNT.depositAddress, //{exchangeInfo} = getExchangeInfo()  exchangeInfo.depositAddress\n          LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n          LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n          sdk.ChainId.GOERLI,\n          nonce,\n          true\n        );\n      }\n\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n      console.log(\n        `deposit: ${TOKEN_INFO.tokenMap.LRC.symbol}-${LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue}, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n      );\n      const response = await sdk.deposit(\n        web3,\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        TOKEN_INFO.tokenMap.LRC,\n        sdk\n          .toBig(LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue)\n          .div(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)\n          .toNumber(),\n        0,\n        LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n        LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n        sdk.ChainId.GOERLI,\n        nonce,\n        true\n      );\n\n      console.log(`nonce: ${nonce}  deposit_LRC: `, response);\n    },\n    DEFAULT_TIMEOUT * 3\n  );\n\n  it(\n    \"deposit_ETH\",\n    async () => {\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n      console.log(\n        `deposit: ${TOKEN_INFO.tokenMap.ETH.symbol}-${LOOPRING_EXPORTED_ACCOUNT.tradeETHValue}, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n      );\n      const response = await sdk.deposit(\n        web3,\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        TOKEN_INFO.tokenMap.ETH,\n        LOOPRING_EXPORTED_ACCOUNT.tradeETHValue,\n        0,\n        LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n        LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n        sdk.ChainId.GOERLI,\n        nonce,\n        true\n      );\n\n      console.log(`nonce: ${nonce} deposit_ETH: `, response);\n    },\n    DEFAULT_TIMEOUT * 3\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/deposit/depositNFT.md",
    "content": "# Deposit NFT\n\nDefinition: Move user L1 NFT assets to Loopring L2\n\n> **All Deposit Method, User should have enough `ETH` pay for the Ethereum Gas (Loopring have no charge, no fee for Deposit).**\n\n\n***\n\n## Step 1. getNFTBalance & getEthBalances\n\n```ts\nconst {ethBalance} = await LoopringAPI.exchangeAPI.getEthBalances({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst nftBalance = await LoopringAPI.nftAPI.getNFTBalance({\n  web3,\n  account: LOOPRING_EXPORTED_ACCOUNT.address,\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n  nftType: sdk.NFTType.ERC1155,\n});\n```\n\n***\n\n## Step 2. isApprovedForAll\n\n```ts\n const isApprovedForAll = await LoopringAPI.nftAPI.isApprovedForAll({\n  web3,\n  from: LOOPRING_EXPORTED_ACCOUNT.address,\n  exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  nftType: sdk.NFTType.ERC1155, // todo： sdk.NFTType.ERC721\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n});\nconsole.log(`check is approveNFT`, isApprovedForAll);\n\n```\n\n***\n\n## Step 3. approveNFT All\n\n```ts\n  if (!isApprovedForAll) {\n  const nonce = await sdk.getNonce(\n    web3,\n    LOOPRING_EXPORTED_ACCOUNT.address\n  );\n  const approveNFT = await LoopringAPI.nftAPI.approveNFT({\n    web3,\n    from: LOOPRING_EXPORTED_ACCOUNT.address,\n    depositAddress: LOOPRING_EXPORTED_ACCOUNT.depositAddress,\n    tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    nftType: sdk.NFTType.ERC1155, // todo： sdk.NFTType.ERC721\n    gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n    gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n    chainId: sdk.ChainId.GOERLI,\n    nonce,\n    sendByMetaMask: true,\n  });\n  console.log(`nonce: ${nonce} approveNFT: ${approveNFT?.result}`);\n}\n```\n\n***\n\n## Step 3. nonce\n\n```ts\n const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n\nconsole.log(\n  `deposit: NFT, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n);\n```\n\n***\n\n## Step 4. depositNFT\n\n```ts\n  const response = await LoopringAPI.nftAPI.depositNFT({\n  web3,\n  from: LOOPRING_EXPORTED_ACCOUNT.address,\n  exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  nftType: sdk.NFTType.ERC1155,   // todo： sdk.NFTType.ERC721\n  tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n  nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n  amount: 2,   // todo：when sdk.NFTType.ERC721  amount: 1,\n  gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit + 100000,\n  chainId: sdk.ChainId.GOERLI,\n  nonce,\n  sendByMetaMask: true,\n});\nconsole.log(`nonce: ${nonce} deposit NFT ERC1155: `, response);\n\n```\n"
  },
  {
    "path": "src/tests/demo/deposit/depositNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  TOKEN_INFO,\n  web3,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\ndescribe(\"depositNFT\", function () {\n  beforeEach(async () => {\n    jest.setTimeout(DEFAULT_TIMEOUT * 3);\n    LOOPRING_EXPORTED_ACCOUNT.gasPrice = (\n      await LoopringAPI.exchangeAPI.getGasPrice()\n    ).gasPrice;\n  }, DEFAULT_TIMEOUT);\n  it(\n    \"deposit NFTAction ERC1155\",\n    async () => {\n      // Step 1. getNFTBalance & getEthBalances\n      const { ethBalance } = await LoopringAPI.exchangeAPI.getEthBalances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      const nftBalance = await LoopringAPI.nftAPI.getNFTBalance({\n        web3,\n        account: LOOPRING_EXPORTED_ACCOUNT.address,\n        tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n        nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n        nftType: sdk.NFTType.ERC1155,\n      });\n\n      // Step 2. isApprovedForAll\n      const isApprovedForAll = await LoopringAPI.nftAPI.isApprovedForAll({\n        web3,\n        from: LOOPRING_EXPORTED_ACCOUNT.address,\n        exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        nftType: sdk.NFTType.ERC1155,\n        tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n      });\n      console.log(`check is approveNFT`, isApprovedForAll);\n\n      // Step 3. approveNFT All\n      if (!isApprovedForAll) {\n        const nonce = await sdk.getNonce(\n          web3,\n          LOOPRING_EXPORTED_ACCOUNT.address\n        );\n        const approveNFT = await LoopringAPI.nftAPI.approveNFT({\n          web3,\n          from: LOOPRING_EXPORTED_ACCOUNT.address,\n          depositAddress: LOOPRING_EXPORTED_ACCOUNT.depositAddress,\n          tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n          nftType: sdk.NFTType.ERC1155,\n          gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n          gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n          chainId: sdk.ChainId.GOERLI,\n          nonce,\n          sendByMetaMask: true,\n        });\n        console.log(`nonce: ${nonce} approveNFT: ${approveNFT?.result}`);\n      }\n\n      // Step 4. nonce\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n\n      console.log(\n        `deposit: NFT, gasPrice: ${LOOPRING_EXPORTED_ACCOUNT.gasPrice}, `\n      );\n      // Step 5. depositNFT\n      const response = await LoopringAPI.nftAPI.depositNFT({\n        web3,\n        from: LOOPRING_EXPORTED_ACCOUNT.address,\n        exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        nftType: sdk.NFTType.ERC1155,\n        tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n        nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n        amount: 1,\n        gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n        gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit + 100000,\n        chainId: sdk.ChainId.GOERLI,\n        nonce,\n        sendByMetaMask: true,\n      });\n\n      console.log(`nonce: ${nonce} deposit NFT ERC1155: `, response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  // it(\n  //   \"deposit NFTAction ERC721\",\n  //   async () => {\n  //     const nonce = await sdk.getNonce(\n  //       web3,\n  //       LOOPRING_EXPORTED_ACCOUNT.address\n  //     );\n  //     const response = await LoopringAPI.nftAPI.depositNFT({\n  //       web3,\n  //       from: LOOPRING_EXPORTED_ACCOUNT.address,\n  //       exchangeAddress: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  //       nftType: NFTType.ERC721,\n  //       tokenAddress: '// TODO:',\n  //       nftId:  '// TODO:',\n  //       amount: 1,\n  //       gasPrice: LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n  //       gasLimit: LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n  //       chainId: ChainId.GOERLI,\n  //       nonce,\n  //       sendByMetaMask: true,\n  //     });\n  //\n  //     console.log(`nonce: ${nonce} deposit NFT ERC1155: `, response);\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n});\n"
  },
  {
    "path": "src/tests/demo/erc20Trade/orderERC20.md",
    "content": "# Order ERC20\n\n*** \n## mini-order\nTo support small quantity trading, we introduce an additional concept \"tradeCost\", which is the minimum gas fee when a trade transaction is uplink to Ethereum. \n\nLet's take LRC-ETH trading as an example.\n\nBelow are the steps - \n\n**1) Query  api/v3/exchange/tokens to get the dust value of orderAmounts for both LRC and ETH.** \n\nThe dust value is the minimum value to pass Relayer check. Any amount less than \"dust\" can't be traded. In this case, we will get both minTOkenLRC and minTokenETH after getting dust value. If user wants to convert LRC to ETH, the set LRC amount can't be less than minTokenLRC and the converted ETH amount can't be less than minTokenETH.   \n\n**2) Query api/v3/user/orderUserRateAmount to get the tradeCost value.**\n\nThe parameters to call this interface are \"accountId\" and \"market=LRC-ETH\". In this example, we will get two tradeCost values for LRC and ETH as tradeCostLRC and tradeCostETH.\n\n**3) Set maxAllowBips = 50% as the maxFeeBips can't exceed 50%**\n\n**4) Set slippage as the slippage value user configured in UI (for example 0.1%)**\n\n**5）Caculate minCostLRC and minCostETH as below**\n\n    minCostLRC = max(minTokenLRC, tradeCostLRC/maxAllowBips)\n    minCostETH = max(minTokenETH, tradeCostETH/maxAllowBips)\n \n**6) Caculate the cost by considering slippage**\n\n    minCostLRCSlip = minCostLRC/(1-slippage)\n    minCostETHSlip = minCostETH/(1-slippage)\n    \n\n**7) Cacluate the minimum quantity user has to set**\n\n    tradeCostSellLRC = max(tradeCostSellLRC, minTokenLRC) * 1.1\n    tradeCostSellETH = max(tradeCostSellETH, minTokenETH) * 1.1\nHere we add additonally 10% tolerance.\n\n**8) Caculate the previous minimum token amount per calling api/v3/user/orderUserRateAmount (existing logic)**\n\nThis is the threshold to distinguish small quantity trading and normal trading  \nWe will get two values (configSellLRC and configSellETH) which are used for previous trading quantity limit (Per USD 100) caculation\n\n**9) Caculate the new maxFeeBips and start trading**\n\nLet's take LRC->ETH as the example\nUser inputs the amount of LRC to convert, amount = sellLRC\n\n    if sellLRC >= configSellLRC then \n    \t// Normal trading case, stay with previous logic\n    \tmaxFeeBips=63 (the default value for maxFeeBips)\n    \tTrade \n    else if sellLRC < tradeCostSellLRC then \n    \t// Really too small to support\n    \tPrompt user the amount is too small to support\n    \tExit\n    else \n    \t// This is what we call as small quantity \n    \tcostRate = Ceil(tradeCostETH/minbuyETH) \n    \tmaxFeeBips = max(costRate, takerRate)\n    \tTrade \n    End If \n    \n\n### price impact update\n\n**1）sellTokenMinAmount  =  baseOrderInfo.minAmount from  LoopringAPI.userAPI.getMinimumTokenAmt({accountId,marke}, apiKey);**\n\n**2）{output} from  sdk.getOutputAmount(input: sellTokenMinAmount, isAtoB: isAtoB,…}).output**\n\n**3）PriceBase = output / sellTokenMinAmount**\n\n**4）tradePrice = calcTradeParams.minReceive / userInputSell**\n\n**5）priceImpact = 1 - tradePrice/PriceBase - 0.005**\n\n**6）If priceImpact < 0 priceImpact = 0  Else priceImpact**\n\n##  \n```ts\nconst calculateSwap = (\n  sellSymbol = \"LRC\",\n  buySymbol = \"ETH\",\n  isInputSellToBuy: boolean,\n  inputValue: number, // user Input value no decimal,\n  _slippage = 0.1,\n  // MOCK value\n  amountMap: { [key: string]: any } = userAmount,\n  market: string = deepMock.symbol,\n  // close = ticker.tickers[7],\n  depth: any = deepMock,\n  ammPoolSnapshot: sdk.AmmPoolSnapshot = ammPoolSnapshotMock,\n  tokenMap: sdk.LoopringMap<sdk.TokenInfo> = TokenMapMockSwap,\n  ammMap: { [key: string]: any } = AMM_MAP\n) => {\n  let calcFor100USDAmount, calcForMinCost, calcForPriceImpact;\n  if (depth && market && tokenMap) {\n    const sellToken = tokenMap[sellSymbol];\n    const buyToken = tokenMap[buySymbol];\n    const isInputSellOutputBuy = isInputSellToBuy;\n    let input: any = inputValue;\n\n    console.log(\n      \"sellToken: Symbol \",\n      sellSymbol,\n      \"buyToken: Symbol\",\n      buySymbol,\n      \"is Input Sell Output Buy:\",\n      isInputSellOutputBuy,\n      \"input value\",\n      input\n    );\n    input = input === undefined || isNaN(Number(input)) ? 0 : Number(input);\n    let slippage = sdk.toBig(_slippage).times(100).toString();\n    let totalFee = undefined;\n    let feeTakerRate = undefined;\n    let feeBips = undefined;\n    let takerRate = undefined;\n    let buyMinAmtInfo = undefined;\n    let sellMinAmtInfo = undefined;\n    let tradeCost = undefined;\n    let basePrice = undefined;\n    let maxFeeBips = MAPFEEBIPS;\n    let minAmt = undefined;\n\n    if (amountMap && amountMap[market] && ammMap) {\n      console.log(`amountMap[${market}]:`, amountMap[market]);\n\n      const ammMarket = `AMM-${market}`;\n\n      const amountMarket = amountMap[market]; // userAmount from  LRC-ETH(Market)\n\n      buyMinAmtInfo = amountMarket[buySymbol];\n      sellMinAmtInfo = amountMarket[sellSymbol];\n      console.log(\n        `buyMinAmtInfo: ${market}, ${buySymbol}`,\n        buyMinAmtInfo,\n        `sellMinAmtInfo: ${market}, ${sellSymbol}`,\n        sellMinAmtInfo\n      );\n\n      feeBips = ammMap[ammMarket] ? ammMap[ammMarket].feeBips : 1;\n\n      feeTakerRate =\n        amountMarket[buySymbol] &&\n        amountMarket[buySymbol].userOrderInfo.takerRate;\n      tradeCost = amountMarket[buySymbol].tradeCost;\n\n      /** @description for charge fee calc, calcFor100USDAmount\n       *  Loopring market consider buyToken value small then  max(buyMinAmtInfo.userOrderInfo.minAmount,buyToken.orderAmounts.dust) is a small order,\n       * the fee will take the Max(tradeCost,userTakeRate)\n       * use the buyMinAmount Input calc the selltoken value,\n       * please read Line:321\n       * **/\n      const minAmountInput = BigNumber.max(\n        buyMinAmtInfo.userOrderInfo.minAmount,\n        buyToken.orderAmounts.dust\n      )\n        .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n        .div(\"1e\" + buyToken.decimals)\n        .toString();\n      calcFor100USDAmount = sdk.getOutputAmount({\n        input: minAmountInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: false,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: slippage,\n      });\n\n      console.log(\n        \"buyMinAmtInfo.userOrderInfo.minAmount:\",\n        buyMinAmtInfo.userOrderInfo.minAmount,\n        `buyMinAmtInfo.userOrderInfo.minAmount, with slippage:${slippage}`,\n        sdk\n          .toBig(buyMinAmtInfo.userOrderInfo.minAmount)\n          .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n          .toString()\n      );\n\n      /*** calc for Price Impact ****/\n      const sellMinAmtInput = sdk\n        .toBig(sellMinAmtInfo.baseOrderInfo.minAmount)\n        .div(\"1e\" + sellToken.decimals)\n        .toString();\n\n      calcForPriceImpact = sdk.getOutputAmount({\n        input: sellMinAmtInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: true,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: \"10\",\n      });\n\n      basePrice = sdk.toBig(calcForPriceImpact?.output).div(sellMinAmtInput);\n\n      console.log(\n        \"calcForPriceImpact input: \",\n        sellMinAmtInput,\n        \", output: \",\n        sdk.toBig(calcForPriceImpact?.output).div(sellMinAmtInput).toNumber(),\n        \", calcForPriceImpact:\",\n        calcForPriceImpact?.amountBOutSlip?.minReceivedVal,\n        \", calcForPriceImpact basePrice: \",\n        basePrice.toNumber()\n      );\n\n      /**** calc for mini Cost ****/\n\n      //minCostBuyToken = max(dustBuyToken, tradeCostETH/maxAllowBips)\n      const dustToken = buyToken;\n      let minCostBuyTokenInput = BigNumber.max(\n        sdk.toBig(tradeCost).times(2), //maxAllowBips = 50% tradeCostETH/50%\n        dustToken.orderAmounts.dust\n      );\n\n      const tradeCostInput = sdk\n        .toBig(minCostBuyTokenInput)\n        .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n        .div(\"1e\" + dustToken.decimals)\n        .toString();\n\n      console.log(\n        `tradeCost: ${tradeCost}*2:`,\n        sdk.toBig(tradeCost).times(2).toString(),\n        \"buyToken.orderAmounts.dust\",\n        buyToken.orderAmounts.dust,\n        \"minCostBuyToken:\",\n        minCostBuyTokenInput.toString(),\n        `calcForMinCostInput, with slippage:${slippage}`,\n        sdk\n          .toBig(minCostBuyTokenInput ?? 0)\n          .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n          .toString(),\n        \"calcForMinCost, Input\",\n        tradeCostInput\n      );\n\n      calcForMinCost = sdk.getOutputAmount({\n        input: tradeCostInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: false,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: slippage,\n      });\n\n      //add additionally 10% tolerance for minimum quantity user has to set on sell Token\n      /**\n       * @output: minAmt for UI\n       * this value mini-order Sell token amount (show on the UI for available order check)\n       * setSellMinAmt(minAmt.toString());\n       */\n      minAmt = BigNumber.max(\n        sellToken.orderAmounts.dust,\n        calcForMinCost?.amountS ?? 0\n      ).times(1.1);\n\n      console.log(\n        \"UI show mini-order Sell token amount:\",\n        minAmt.toString(),\n        sdk\n          .toBig(minAmt)\n          .div(\"1e\" + sellToken.decimals)\n          .toString()\n      );\n\n      console.log(\n        `calcFor100USDAmount.amountS`,\n        sdk\n          .toBig(calcFor100USDAmount?.amountS ?? 0)\n          .div(\"1e\" + sellToken.decimals)\n          .toString(),\n        \"calcForMinCost.amountS\",\n        sdk\n          .toBig(calcForMinCost?.amountS ?? 0)\n          .div(\"1e\" + sellToken.decimals)\n          .toString()\n      );\n    }\n    const calcTradeParams = sdk.getOutputAmount({\n      input: input.toString(),\n      sell: sellSymbol,\n      buy: buySymbol,\n      isAtoB: isInputSellOutputBuy,\n      marketArr: marketArray as string[],\n      tokenMap: tokenMap as any,\n      marketMap: marketMap as any,\n      depth,\n      ammPoolSnapshot: ammPoolSnapshot,\n      feeBips: feeBips ? feeBips.toString() : 1,\n      takerRate: \"0\", // for new calc miniReceive will minus fee, so takeRate can fix as 0\n      slipBips: slippage,\n    });\n\n    const minSymbol = buySymbol;\n    const tradePrice = sdk\n      .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n      .div(isInputSellOutputBuy ? input.toString() : calcTradeParams?.output);\n    const priceImpact = sdk\n      .toBig(1)\n      .minus(sdk.toBig(tradePrice).div(basePrice ?? 1))\n      .minus(0.001);\n    if (calcTradeParams && priceImpact.gte(0)) {\n      calcTradeParams.priceImpact = priceImpact.toFixed(4, 1);\n    } else {\n      calcTradeParams && (calcTradeParams.priceImpact = \"0\");\n    }\n\n    console.log(\n      \"calcTradeParams input:\",\n      input.toString(),\n      \", calcTradeParams Price: \",\n      sdk\n        .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n        .div(input.toString())\n        .toNumber(),\n      `isAtoB mean isInputSellOutputBuy:${isInputSellOutputBuy}, ${\n        isInputSellOutputBuy ? input.toString() : calcTradeParams?.output\n      } tradePrice: `,\n      tradePrice.toString(),\n      \"basePrice: \",\n      basePrice?.toString(),\n      \"toBig(tradePrice).div(basePrice)\",\n      sdk\n        .toBig(tradePrice)\n        .div(basePrice ?? 1)\n        .toNumber(),\n      \"priceImpact (1-tradePrice/basePrice) - 0.001\",\n      priceImpact.toNumber(),\n      \"priceImpact view\",\n      calcTradeParams?.priceImpact\n    );\n\n    if (\n      tradeCost &&\n      calcTradeParams &&\n      calcTradeParams.amountBOutSlip?.minReceived &&\n      feeTakerRate\n    ) {\n      let value = sdk\n        .toBig(calcTradeParams.amountBOutSlip?.minReceived)\n        .times(feeTakerRate)\n        .div(10000);\n\n      console.log(\n        \"input Accounts\",\n        calcTradeParams?.amountS,\n        \"100 U Amount Sell:\",\n        calcFor100USDAmount?.amountS\n      );\n\n      let validAmt = !!(\n        calcTradeParams?.amountS &&\n        calcFor100USDAmount?.amountS &&\n        sdk.toBig(calcTradeParams?.amountS).gte(calcFor100USDAmount.amountS)\n      );\n      let totalFeeRaw;\n\n      console.log(\n        `${minSymbol} tradeCost:`,\n        tradeCost,\n        \"useTakeRate Fee:\",\n        value.toString(),\n        \"calcFor100USDAmount?.amountS:\",\n        calcFor100USDAmount?.amountS,\n        `is setup minTrade amount, ${calcFor100USDAmount?.amountS}:`,\n        validAmt\n      );\n\n      if (!validAmt) {\n        if (sdk.toBig(tradeCost).gte(value)) {\n          totalFeeRaw = sdk.toBig(tradeCost);\n        } else {\n          totalFeeRaw = value;\n        }\n        console.log(\n          \"maxFeeBips update for tradeCost before value:\",\n          maxFeeBips,\n          \"totalFeeRaw\",\n          totalFeeRaw.toString()\n        );\n        maxFeeBips = Math.ceil(\n          totalFeeRaw\n            .times(10000)\n            .div(calcTradeParams.amountBOutSlip?.minReceived)\n            .toNumber()\n        );\n        console.log(\"maxFeeBips update for tradeCost after value:\", maxFeeBips);\n      } else {\n        totalFeeRaw = sdk.toBig(value);\n      }\n\n      /**\n       * totalFee\n       */\n      totalFee = totalFeeRaw\n        .div(\"1e\" + tokenMap[minSymbol].decimals)\n        .toString();\n      /** @output: UI\n       *   getValuePrecisionThousand(\n       *   totalFeeRaw.div(\"1e\" + tokenMap[minSymbol].decimals).toString(),\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   false,\n       *   { floor: true }\n       * );\n       */\n\n      tradeCost = sdk\n        .toBig(tradeCost)\n        // @ts-ignore\n        .div(\"1e\" + tokenMap[minSymbol].decimals)\n        .toString();\n\n      /** @output:  UI code with precision\n       *   getValuePrecisionThousand(\n       *   sdk\n       *     .toBig(tradeCost)\n       *     .div(\"1e\" + tokenMap[minSymbol].decimals)\n       *     .toString(),\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   false,\n       *   { floor: true }\n       * );\n       */\n\n      console.log(\"totalFee view value:\", totalFee + \" \" + minSymbol);\n      console.log(\"tradeCost view value:\", tradeCost + \" \" + minSymbol);\n    }\n\n    const minimumReceived = sdk\n      .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n      .minus(totalFee ?? 0)\n      .toString();\n    console.log(\"minimumReceived:\", minimumReceived);\n\n    /** @output:   UI code with precision\n     *   getValuePrecisionThousand(\n     *   toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n     *     .minus(totalFee)\n     *     .toString(),\n     *   tokenMap[minSymbol].precision,\n     *   tokenMap[minSymbol].precision,\n     *   tokenMap[minSymbol].precision,\n     *   false,\n     *   { floor: true }\n     * );\n     */\n\n    let priceImpactView: any = calcTradeParams?.priceImpact\n      ? parseFloat(calcTradeParams?.priceImpact) * 100\n      : undefined;\n    console.log(\"priceImpact view:\", priceImpactView + \"%\");\n    //  @output:   UI code with color alert\n    // const priceImpactObj = getPriceImpactInfo(calcTradeParams);\n    // const _tradeCalcData: Partial<TradeCalcData<C>> = {\n    //   priceImpact: priceImpactObj.value.toString(),\n    //   priceImpactColor: priceImpactObj.priceImpactColor,\n    //   minimumReceived: !minimumReceived?.toString().startsWith(\"-\")\n    //     ? minimumReceived\n    //     : undefined,\n    //   fee: totalFee,\n    //   feeTakerRate,\n    //   tradeCost,\n    // };\n\n    console.log(\n      `isInputSellOutputBuy:${isInputSellOutputBuy}`,\n      `output ${isInputSellOutputBuy ? \"Buy\" : \"Sell\"}`,\n      calcTradeParams?.output\n    );\n\n    return {\n      market,\n      feeBips,\n      takerRate,\n      sellMinAmtInfo: sellMinAmtInfo as any,\n      buyMinAmtInfo: buyMinAmtInfo as any,\n      totalFee,\n      maxFeeBips,\n      feeTakerRate,\n      tradeCost,\n      minimumReceived,\n      calcTradeParams,\n      minAmt,\n    };\n  }\n};\n```\n\n### Step 1. get apikey & eddsaKey\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst eddsaKey = await signatureKeyPairMock(accInfo);\napiKey = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo.accountId,\n    },\n    eddsaKey.sk\n  )\n).apiKey;\n```\n\n### Step 2. storageId\n\n```ts\n\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n  },\n  apiKey\n);\n```\n\n### Step 3. get user AmountMap, which decided user minimum order\n\n```ts\nconst amountMap = {\n  [AMM_MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: AMM_MAP[AMM_MARKET].market,\n      },\n      apiKey\n    )\n  ).amountMap,\n  [MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: MARKET,\n      },\n      apiKey\n    )\n  ).amountMap,\n};\n```\n\n### Step 4. depth, ammPoolSnapshot ,tickMap\n\n```ts\nconst [{depth}, {ammPoolSnapshot}] = await Promise.all([\n  LoopringAPI.exchangeAPI.getMixDepth({\n    market: AMM_MAP[\"AMM-LRC-ETH\"].market,\n  }),\n  LoopringAPI.ammpoolAPI.getAmmPoolSnapshot({\n    poolAddress: AMM_MAP[\"AMM-LRC-ETH\"].address,\n  }),\n]);\n```\n\n### Step 5. Check MinAmt see log and calc mini receive and ouput value & maxfeeBips & priceImpact & swap output\n\n```ts\nconst { calcTradeParams, maxFeeBips, minimumReceived } = calculateSwap(\n        sell,\n        buy,\n        isAtoB,\n        10, // user Input value no decimal 10 lrc,\n        0.1,\n        //TODO MOCK value\n        amountMap,\n        \"LRC-ETH\",\n        // close = ticker.tickers[7],\n        depth,\n        ammPoolSnapshot,\n        TOKEN_INFO.tokenMap,\n        AMM_MAP\n      );\n```\n\n### Step 6. Submit\n\n```ts\nconst response: { hash: string } | any =\n  await LoopringAPI.userAPI.submitOrder(\n    {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      storageId: storageId.orderId,\n      sellToken: {\n        tokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n        volume: calcTradeParams?.amountS as string,\n      },\n      buyToken: {\n        tokenId: TOKEN_INFO.tokenMap[buy].tokenId,\n        volume: calcTradeParams?.amountBOutSlip.minReceived as string,\n      },\n      allOrNone: false,\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      maxFeeBips: 63,\n      fillAmountBOrS: false, // amm only false\n      tradeChannel: calcTradeParams?.exceedDepth\n        ? sdk.TradeChannel.BLANK\n        : sdk.TradeChannel.MIXED,\n      orderType: calcTradeParams?.exceedDepth\n        ? sdk.OrderType.ClassAmm\n        : sdk.OrderType.TakerOnly,\n      eddsaSignature: \"\",\n    },\n    eddsaKey.sk,\n    apiKey\n  );\nconsole.log(\"submitOrder\", response);\n```   \n\n***\n\n## ETH-LRC : for Quote to Base\n\n### MOCK Data\n\n> user should had apikey, please check get apikey\n\n```ts\nconst buy = \"ETH\",\n  sell = \"LRC\",\n  MARKET = \"LRC-ETH\",\n  AMM_MARKET = \"AMM-LRC-ETH\",\n  slippage = \"50\";\nconst isAtoB = false;\n```\n\n### Step 1. get apikey & eddsaKey\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconst eddsaKey = await signatureKeyPairMock(accInfo);\napiKey = (\n  await LoopringAPI.userAPI.getUserApiKey(\n    {\n      accountId: accInfo.accountId,\n    },\n    eddsaKey.sk\n  )\n).apiKey;\n```\n\n### Step  2. storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n  },\n  apiKey\n);\n```\n\n### Step 3. get user AmountMap, which decided user minimum order\n\n```ts\nconst amountMap = {\n  [AMM_MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: AMM_MAP[AMM_MARKET].market,\n      },\n      apiKey\n    )\n  ).amountMap,\n  [MARKET]: (\n    await LoopringAPI.userAPI.getMinimumTokenAmt(\n      {\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        market: MARKET,\n      },\n      apiKey\n    )\n  ).amountMap,\n};\n```\n\n### Step 4. depth, ammPoolSnapshot ,tickMap\n\n```ts\nconst [{depth}, {ammPoolSnapshot}] = await Promise.all([\n  LoopringAPI.exchangeAPI.getMixDepth({\n    market: AMM_MAP[\"AMM-LRC-ETH\"].market,\n  }),\n  LoopringAPI.ammpoolAPI.getAmmPoolSnapshot({\n    poolAddress: AMM_MAP[\"AMM-LRC-ETH\"].address,\n  }),\n]);\n```\n\n### Step  5. check MinAmt see log and calc mini receive and ouput value & maxfeeBips & priceImpact\n\n```ts\nconst { calcTradeParams, maxFeeBips, minimumReceived } = calculateSwap(\n        sell,\n        buy,\n        isAtoB,\n        10, // user Input value no decimal 10 lrc,\n        0.1,\n        //TODO MOCK value\n        amountMap,\n        \"LRC-ETH\",\n        // close = ticker.tickers[7],\n        depth,\n        ammPoolSnapshot,\n        TOKEN_INFO.tokenMap,\n        AMM_MAP\n);\nconsole.log(\n  \"Buy\",\n  \",ETH:\",\n  LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  \",minAmountInput ETH:\",\n  minAmountInput,\n  \",LRC:\",\n  calcTradeParams?.amountBOutSlip?.minReceivedVal\n);\n\nconst response: { hash: string } | any =\n  await LoopringAPI.userAPI.submitOrder(\n    {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      storageId: storageId.orderId,\n      sellToken: {\n        tokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n        volume: calcTradeParams?.amountS as string,\n      },\n      buyToken: {\n        tokenId: TOKEN_INFO.tokenMap[buy].tokenId,\n        volume: calcTradeParams?.amountBOutSlip.minReceived as string,\n      },\n      allOrNone: false,\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      maxFeeBips: 63,\n      fillAmountBOrS: false, // amm only false\n      tradeChannel: calcTradeParams?.exceedDepth\n        ? sdk.TradeChannel.BLANK\n        : sdk.TradeChannel.MIXED,\n      orderType: calcTradeParams?.exceedDepth\n        ? sdk.OrderType.ClassAmm\n        : sdk.OrderType.TakerOnly,\n      eddsaSignature: \"\",\n    },\n    eddsaKey.sk,\n    apiKey\n  );\nconsole.log(\"submitOrder\", response);\n``` \n\n\n### MockSwapData\n```ts\n//Default config value from getTokens & getMixMarkets\nimport * as sdk from \"../index\";\n\nexport const marketArray = [\"LRC-ETH\"];\nexport const marketMap = {\n  \"LRC-ETH\": {\n    baseTokenId: 1,\n    enabled: true,\n    market: \"LRC-ETH\",\n    orderbookAggLevels: 5,\n    precisionForPrice: 6,\n    quoteTokenId: 0,\n    status: 3,\n    isSwapEnabled: true,\n    createdAt: 1617967800000,\n  },\n};\n//v3/mix/depth?level=0&limit=50&market=LRC-ETH\nexport const deepMock = {\n  symbol: \"LRC-ETH\",\n  version: 23249677,\n  timestamp: 1655719492365,\n  mid_price: 0.00033248,\n  bids: [\n    {\n      price: 0.00030689,\n      amt: \"12041160324514792497908\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"618450503644320209925641\",\n      volTotal: \"198539605794234049017\",\n    },\n    {\n      price: 0.00030752,\n      amt: \"12016302126785109160251\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"606409343319805417427733\",\n      volTotal: \"194844233461662963807\",\n    },\n    {\n      price: 0.00030816,\n      amt: \"11991520826895479525387\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"594393041193020308267482\",\n      volTotal: \"191148861129091878597\",\n    },\n    {\n      price: 0.00030881,\n      amt: \"12329062048917727073625\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"582401520366124828742095\",\n      volTotal: \"187453488796520793387\",\n    },\n    {\n      price: 0.00030945,\n      amt: \"11941442525358097768419\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"570072458317207101668470\",\n      volTotal: \"183646135484174826807\",\n    },\n    {\n      price: 0.0003102,\n      amt: \"3223726000000000000000\",\n      vol: \"999999805200000000\",\n      amtTotal: \"558131015791849003900051\",\n      volTotal: \"179950763151603741597\",\n    },\n    {\n      price: 0.0003104,\n      amt: \"11904963012947201084062\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"554907289791849003900051\",\n      volTotal: \"178950763346403741597\",\n    },\n    {\n      price: 0.00031072,\n      amt: \"11892800074855146120151\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"543002326778901802815989\",\n      volTotal: \"175255391013832656387\",\n    },\n    {\n      price: 0.00031137,\n      amt: \"12227667622887455762012\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"531109526704046656695838\",\n      volTotal: \"171560018681261571177\",\n    },\n    {\n      price: 0.00031202,\n      amt: \"11843337524732768607817\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"518881859081159200933826\",\n      volTotal: \"167752665368915604597\",\n    },\n    {\n      price: 0.00031266,\n      amt: \"11819088718260537718160\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"507038521556426432326009\",\n      volTotal: \"164057293036344519387\",\n    },\n    {\n      price: 0.0003133,\n      amt: \"11794914308461194855590\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"495219432838165894607849\",\n      volTotal: \"160361920703773434177\",\n    },\n    {\n      price: 0.00031395,\n      amt: \"12127129883064173669497\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"483424518529704699752259\",\n      volTotal: \"156666548371202348967\",\n    },\n    {\n      price: 0.0003146,\n      amt: \"11746060536480763829870\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"471297388646640526082762\",\n      volTotal: \"152859195058856382387\",\n    },\n    {\n      price: 0.00031524,\n      amt: \"11722109721002274877424\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"459551328110159762252892\",\n      volTotal: \"149163822726285297177\",\n    },\n    {\n      price: 0.0003159,\n      amt: \"12052351993023897680738\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"447829218389157487375468\",\n      volTotal: \"145468450393714211967\",\n    },\n    {\n      price: 0.00031655,\n      amt: \"11673707113082743010268\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"435776866396133589694730\",\n      volTotal: \"141661097081368245387\",\n    },\n    {\n      price: 0.00031699,\n      amt: \"615000000000000000000\",\n      vol: \"194954999999999949\",\n      amtTotal: \"424103159283050846684462\",\n      volTotal: \"137965724748797160177\",\n    },\n    {\n      price: 0.00031719,\n      amt: \"11649977142974837964110\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"423488159283050846684462\",\n      volTotal: \"137770769748797160228\",\n    },\n    {\n      price: 0.00031784,\n      amt: \"11626319455782556517212\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"411838182140076008720352\",\n      volTotal: \"134075397416226075018\",\n    },\n    {\n      price: 0.0003185,\n      amt: \"11953964321007990024755\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"400211862684293452203140\",\n      volTotal: \"130380025083654989808\",\n    },\n    {\n      price: 0.00031934,\n      amt: \"11571837200722111826863\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"388257898363285462178385\",\n      volTotal: \"126572671771309023228\",\n    },\n    {\n      price: 0.00031979,\n      amt: \"11555429099390519988949\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"376686061162563350351522\",\n      volTotal: \"122877299438737938018\",\n    },\n    {\n      price: 0.00032,\n      amt: \"300000000000000000000\",\n      vol: \"96000000000000000\",\n      amtTotal: \"365130632063172830362573\",\n      volTotal: \"119181927106166852808\",\n    },\n    {\n      price: 0.00032044,\n      amt: \"11532058329906875386268\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"364830632063172830362573\",\n      volTotal: \"119085927106166852808\",\n    },\n    {\n      price: 0.0003211,\n      amt: \"11857145662584872212009\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"353298573733265954976305\",\n      volTotal: \"115390554773595767598\",\n    },\n    {\n      price: 0.00032176,\n      amt: \"11484826169666631095087\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"341441428070681082764296\",\n      volTotal: \"111583201461249801018\",\n    },\n    {\n      price: 0.00032241,\n      amt: \"11461669156035188891431\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"329956601901014451669209\",\n      volTotal: \"107887829128678715808\",\n    },\n    {\n      price: 0.00032294,\n      amt: \"22266286128259997368320\",\n      vol: \"7190674442260284416\",\n      amtTotal: \"318494932744979262777778\",\n      volTotal: \"104192456796107630598\",\n    },\n    {\n      price: 0.00032307,\n      amt: \"11784846142950476791130\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"296228646616719265409458\",\n      volTotal: \"97001782353847346182\",\n    },\n    {\n      price: 0.00032333,\n      amt: \"31042151210389998665728\",\n      vol: \"10037169172367501312\",\n      amtTotal: \"284443800473768788618328\",\n      volTotal: \"93194429041501379602\",\n    },\n    {\n      price: 0.00032354,\n      amt: \"19082720347089998446592\",\n      vol: \"6174214168300968960\",\n      amtTotal: \"253401649263378789952600\",\n      volTotal: \"83157259869133878290\",\n    },\n    {\n      price: 0.00032373,\n      amt: \"11414868337793698506576\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"234318928916288791506008\",\n      volTotal: \"76983045700832909330\",\n    },\n    {\n      price: 0.00032438,\n      amt: \"11391922481177051106050\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"222904060578495092999432\",\n      volTotal: \"73287673368261824120\",\n    },\n    {\n      price: 0.00032503,\n      amt: \"11369045742792164433715\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"211512138097318041893382\",\n      volTotal: \"69592301035690738910\",\n    },\n    {\n      price: 0.00032512,\n      amt: \"7101984539779999465472\",\n      vol: \"2308997213573273600\",\n      amtTotal: \"200143092354525877459667\",\n      volTotal: \"65896928703119653700\",\n    },\n    {\n      price: 0.0003257,\n      amt: \"11689707913498419991686\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"193041107814745877994195\",\n      volTotal: \"63587931489546380100\",\n    },\n    {\n      price: 0.00032636,\n      amt: \"11322810509578528739940\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"181351399901247458002509\",\n      volTotal: \"59780578177200413520\",\n    },\n    {\n      price: 0.00032702,\n      amt: \"11300141532643741902081\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"170028589391668929262569\",\n      volTotal: \"56085205844629328310\",\n    },\n    {\n      price: 0.00032709,\n      amt: \"1511898000000000000000\",\n      vol: \"494541835799999898\",\n      amtTotal: \"158728447859025187360488\",\n      volTotal: \"52389833512058243100\",\n    },\n    {\n      price: 0.00032767,\n      amt: \"11277540564700637960582\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"157216549859025187360488\",\n      volTotal: \"51895291676258243202\",\n    },\n    {\n      price: 0.00032838,\n      amt: \"11594014901713773553177\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"145939009294324549399906\",\n      volTotal: \"48199919343687157992\",\n    },\n    {\n      price: 0.00032899,\n      amt: \"11232203228917728004878\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"134344994392610775846729\",\n      volTotal: \"44392566031341191412\",\n    },\n    {\n      price: 0.00032959,\n      amt: \"31100749000000000753664\",\n      vol: \"10250806870400000000\",\n      amtTotal: \"123112791163693047841851\",\n      volTotal: \"40697193698770106202\",\n    },\n    {\n      price: 0.00032965,\n      amt: \"11209805337410429375102\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"92012042163693047088187\",\n      volTotal: \"30446386828370106202\",\n    },\n    {\n      price: 0.00033031,\n      amt: \"11187474373893810850495\",\n      vol: \"3695372332571085210\",\n      amtTotal: \"80802236826282617713085\",\n      volTotal: \"26751014495799020992\",\n    },\n    {\n      price: 0.00033098,\n      amt: \"11503202913004006553102\",\n      vol: \"3807353312345966580\",\n      amtTotal: \"69614762452388806862590\",\n      volTotal: \"23055642163227935782\",\n    },\n    {\n      price: 0.00033099,\n      amt: \"26515451000000002129920\",\n      vol: \"8776614281000000512\",\n      amtTotal: \"58111559539384800309488\",\n      volTotal: \"19248288850881969202\",\n    },\n    {\n      price: 0.0003313,\n      amt: \"20499506300000000802816\",\n      vol: \"6791486437190000640\",\n      amtTotal: \"31596108539384798179568\",\n      volTotal: \"10471674569881968690\",\n    },\n    {\n      price: 0.00033165,\n      amt: \"11096602239384797376752\",\n      vol: \"3680188132691968050\",\n      amtTotal: \"11096602239384797376752\",\n      volTotal: \"3680188132691968050\",\n    },\n  ],\n  bids_prices: [\n    0.00030689, 0.00030752, 0.00030816, 0.00030881, 0.00030945, 0.0003102,\n    0.0003104, 0.00031072, 0.00031137, 0.00031202, 0.00031266, 0.0003133,\n    0.00031395, 0.0003146, 0.00031524, 0.0003159, 0.00031655, 0.00031699,\n    0.00031719, 0.00031784, 0.0003185, 0.00031934, 0.00031979, 0.00032,\n    0.00032044, 0.0003211, 0.00032176, 0.00032241, 0.00032294, 0.00032307,\n    0.00032333, 0.00032354, 0.00032373, 0.00032438, 0.00032503, 0.00032512,\n    0.0003257, 0.00032636, 0.00032702, 0.00032709, 0.00032767, 0.00032838,\n    0.00032899, 0.00032959, 0.00032965, 0.00033031, 0.00033098, 0.00033099,\n    0.0003313, 0.00033165,\n  ],\n  bids_amtTotals: [\n    \"618450503644320209925641\",\n    \"606409343319805417427733\",\n    \"594393041193020308267482\",\n    \"582401520366124828742095\",\n    \"570072458317207101668470\",\n    \"558131015791849003900051\",\n    \"554907289791849003900051\",\n    \"543002326778901802815989\",\n    \"531109526704046656695838\",\n    \"518881859081159200933826\",\n    \"507038521556426432326009\",\n    \"495219432838165894607849\",\n    \"483424518529704699752259\",\n    \"471297388646640526082762\",\n    \"459551328110159762252892\",\n    \"447829218389157487375468\",\n    \"435776866396133589694730\",\n    \"424103159283050846684462\",\n    \"423488159283050846684462\",\n    \"411838182140076008720352\",\n    \"400211862684293452203140\",\n    \"388257898363285462178385\",\n    \"376686061162563350351522\",\n    \"365130632063172830362573\",\n    \"364830632063172830362573\",\n    \"353298573733265954976305\",\n    \"341441428070681082764296\",\n    \"329956601901014451669209\",\n    \"318494932744979262777778\",\n    \"296228646616719265409458\",\n    \"284443800473768788618328\",\n    \"253401649263378789952600\",\n    \"234318928916288791506008\",\n    \"222904060578495092999432\",\n    \"211512138097318041893382\",\n    \"200143092354525877459667\",\n    \"193041107814745877994195\",\n    \"181351399901247458002509\",\n    \"170028589391668929262569\",\n    \"158728447859025187360488\",\n    \"157216549859025187360488\",\n    \"145939009294324549399906\",\n    \"134344994392610775846729\",\n    \"123112791163693047841851\",\n    \"92012042163693047088187\",\n    \"80802236826282617713085\",\n    \"69614762452388806862590\",\n    \"58111559539384800309488\",\n    \"31596108539384798179568\",\n    \"11096602239384797376752\",\n  ],\n  bids_volTotals: [\n    \"198539605794234049017\",\n    \"194844233461662963807\",\n    \"191148861129091878597\",\n    \"187453488796520793387\",\n    \"183646135484174826807\",\n    \"179950763151603741597\",\n    \"178950763346403741597\",\n    \"175255391013832656387\",\n    \"171560018681261571177\",\n    \"167752665368915604597\",\n    \"164057293036344519387\",\n    \"160361920703773434177\",\n    \"156666548371202348967\",\n    \"152859195058856382387\",\n    \"149163822726285297177\",\n    \"145468450393714211967\",\n    \"141661097081368245387\",\n    \"137965724748797160177\",\n    \"137770769748797160228\",\n    \"134075397416226075018\",\n    \"130380025083654989808\",\n    \"126572671771309023228\",\n    \"122877299438737938018\",\n    \"119181927106166852808\",\n    \"119085927106166852808\",\n    \"115390554773595767598\",\n    \"111583201461249801018\",\n    \"107887829128678715808\",\n    \"104192456796107630598\",\n    \"97001782353847346182\",\n    \"93194429041501379602\",\n    \"83157259869133878290\",\n    \"76983045700832909330\",\n    \"73287673368261824120\",\n    \"69592301035690738910\",\n    \"65896928703119653700\",\n    \"63587931489546380100\",\n    \"59780578177200413520\",\n    \"56085205844629328310\",\n    \"52389833512058243100\",\n    \"51895291676258243202\",\n    \"48199919343687157992\",\n    \"44392566031341191412\",\n    \"40697193698770106202\",\n    \"30446386828370106202\",\n    \"26751014495799020992\",\n    \"23055642163227935782\",\n    \"19248288850881969202\",\n    \"10471674569881968690\",\n    \"3680188132691968050\",\n  ],\n  bids_amtTotal: \"618450503644320209925641\",\n  bids_volTotal: \"198539605794234049017\",\n  asks: [\n    {\n      price: 0.00033331,\n      amt: \"26466599999999999737856\",\n      vol: \"8821317780000000000\",\n      amtTotal: \"26466599999999999737856\",\n      volTotal: \"8821317780000000000\",\n    },\n    {\n      price: 0.0003336,\n      amt: \"33880800000000001048576\",\n      vol: \"11302634880000000000\",\n      amtTotal: \"60347400000000000786432\",\n      volTotal: \"20123952660000000000\",\n    },\n    {\n      price: 0.00033371,\n      amt: \"11142477800817399987988\",\n      vol: \"3718356266910774549\",\n      amtTotal: \"71489877800817400774420\",\n      volTotal: \"23842308926910774549\",\n    },\n    {\n      price: 0.00033439,\n      amt: \"11410124103475892197402\",\n      vol: \"3815340399218399705\",\n      amtTotal: \"82900001904293292971822\",\n      volTotal: \"27657649326129174254\",\n    },\n    {\n      price: 0.00033501,\n      amt: \"39334199999999992922112\",\n      vol: \"13176957000000000000\",\n      amtTotal: \"122234201904293285893934\",\n      volTotal: \"40834606326129174254\",\n    },\n    {\n      price: 0.00033506,\n      amt: \"11052295534472154230337\",\n      vol: \"3703108939445215718\",\n      amtTotal: \"133286497438765440124271\",\n      volTotal: \"44537715265574389972\",\n    },\n    {\n      price: 0.00033572,\n      amt: \"11030456322913363709718\",\n      vol: \"3703093651997124565\",\n      amtTotal: \"144316953761678803833989\",\n      volTotal: \"48240808917571514537\",\n    },\n    {\n      price: 0.00033638,\n      amt: \"11008681778518069039476\",\n      vol: \"3703078409816047858\",\n      amtTotal: \"155325635540196872873465\",\n      volTotal: \"51943887327387562395\",\n    },\n    {\n      price: 0.000337,\n      amt: \"7188173683760000139264\",\n      vol: \"2422342649690282496\",\n      amtTotal: \"162513809223956873012729\",\n      volTotal: \"54366229977077844891\",\n    },\n    {\n      price: 0.00033706,\n      amt: \"11319571950108460741855\",\n      vol: \"3815277012711042502\",\n      amtTotal: \"173833381174065333754584\",\n      volTotal: \"58181506989788887393\",\n    },\n    {\n      price: 0.00033773,\n      amt: \"10964670732513311387215\",\n      vol: \"3703047602083844528\",\n      amtTotal: \"184798051906578645141799\",\n      volTotal: \"61884554591872731921\",\n    },\n    {\n      price: 0.00033848,\n      amt: \"10943090596879450870975\",\n      vol: \"3703921209677097807\",\n      amtTotal: \"195741142503458096012774\",\n      volTotal: \"65588475801549829728\",\n    },\n    {\n      price: 0.00033893,\n      amt: \"31086310012520000126976\",\n      vol: \"10535772189443278848\",\n      amtTotal: \"226827452515978096139750\",\n      volTotal: \"76124247990993108576\",\n    },\n    {\n      price: 0.00033907,\n      amt: \"10921574108084085072499\",\n      vol: \"3703126650187824910\",\n      amtTotal: \"237749026624062181212249\",\n      volTotal: \"79827374641180933486\",\n    },\n    {\n      price: 0.00033934,\n      amt: \"22061773569720001232896\",\n      vol: \"7486221625413088256\",\n      amtTotal: \"259810800193782182445145\",\n      volTotal: \"87313596266594021742\",\n    },\n    {\n      price: 0.00033975,\n      amt: \"11230093484570461106334\",\n      vol: \"3815326678720011608\",\n      amtTotal: \"271040893678352643551479\",\n      volTotal: \"91128922945314033350\",\n    },\n    {\n      price: 0.00034042,\n      amt: \"10878083875111520592396\",\n      vol: \"3703095772122414389\",\n      amtTotal: \"281918977553464164143875\",\n      volTotal: \"94832018717436447739\",\n    },\n    {\n      price: 0.00034061,\n      amt: \"19029641944770000453632\",\n      vol: \"6481686342808109056\",\n      amtTotal: \"300948619498234164597507\",\n      volTotal: \"101313705060244556795\",\n    },\n    {\n      price: 0.00034109,\n      amt: \"10856758733704286197912\",\n      vol: \"3703080631272015254\",\n      amtTotal: \"311805378231938450795419\",\n      volTotal: \"105016785691516572049\",\n    },\n    {\n      price: 0.00034176,\n      amt: \"10835496238854895014260\",\n      vol: \"3703065534900672185\",\n      amtTotal: \"322640874470793345809679\",\n      volTotal: \"108719851226417244234\",\n    },\n    {\n      price: 0.00034244,\n      amt: \"11141671799245742102774\",\n      vol: \"3815263899323431057\",\n      amtTotal: \"333782546270039087912453\",\n      volTotal: \"112535115125740675291\",\n    },\n    {\n      price: 0.00034312,\n      amt: \"10792518633700140402041\",\n      vol: \"3703035020801012310\",\n      amtTotal: \"344575064903739228314494\",\n      volTotal: \"116238150146541687601\",\n    },\n    {\n      price: 0.00034379,\n      amt: \"10771444484888773263977\",\n      vol: \"3703020058155356239\",\n      amtTotal: \"355346509388628001578471\",\n      volTotal: \"119941170204697043840\",\n    },\n    {\n      price: 0.00034447,\n      amt: \"11075875299655656611658\",\n      vol: \"3815217183808722096\",\n      amtTotal: \"366422384688283658190129\",\n      volTotal: \"123756387388505765936\",\n    },\n    {\n      price: 0.00034515,\n      amt: \"10728847020295584791583\",\n      vol: \"3702989813955495075\",\n      amtTotal: \"377151231708579242981712\",\n      volTotal: \"127459377202461261011\",\n    },\n    {\n      price: 0.00034582,\n      amt: \"10707958999548106661900\",\n      vol: \"3702974983460764366\",\n      amtTotal: \"387859190708127349643612\",\n      volTotal: \"131162352185922025377\",\n    },\n    {\n      price: 0.00034649,\n      amt: \"10687131919892014508549\",\n      vol: \"3702960196234208540\",\n      amtTotal: \"398546322628019364152161\",\n      volTotal: \"134865312382156233917\",\n    },\n    {\n      price: 0.00034718,\n      amt: \"10989265205593964126102\",\n      vol: \"3815155690641938295\",\n      amtTotal: \"409535587833613328278263\",\n      volTotal: \"138680468072798172212\",\n    },\n    {\n      price: 0.00034809,\n      amt: \"10645033127428079147754\",\n      vol: \"3705341637309061860\",\n      amtTotal: \"420180620961041407426017\",\n      volTotal: \"142385809710107234072\",\n    },\n    {\n      price: 0.00034854,\n      amt: \"10624389276271547157517\",\n      vol: \"3703021892850000724\",\n      amtTotal: \"430805010237312954583534\",\n      volTotal: \"146088831602957234796\",\n    },\n    {\n      price: 0.00034922,\n      amt: \"10603805418694082174472\",\n      vol: \"3703007072472544949\",\n      amtTotal: \"441408815656007036758006\",\n      volTotal: \"149791838675429779745\",\n    },\n    {\n      price: 0.00034991,\n      amt: \"10903667052066234563130\",\n      vol: \"3815203952623454269\",\n      amtTotal: \"452312482708073271321136\",\n      volTotal: \"153607042628053234014\",\n    },\n    {\n      price: 0.00035059,\n      amt: \"10562197544947631702552\",\n      vol: \"3702977114803447505\",\n      amtTotal: \"462874680253020903023688\",\n      volTotal: \"157310019742856681519\",\n    },\n    {\n      price: 0.00035127,\n      amt: \"10541794072549149477757\",\n      vol: \"3702962424303320597\",\n      amtTotal: \"473416474325570052501445\",\n      volTotal: \"161012982167160002116\",\n    },\n    {\n      price: 0.00035196,\n      amt: \"10839964505283434387937\",\n      vol: \"3815158086789770653\",\n      amtTotal: \"484256438830853486889382\",\n      volTotal: \"164828140253949772769\",\n    },\n    {\n      price: 0.00035265,\n      amt: \"10500550295026604907238\",\n      vol: \"3702932728783504366\",\n      amtTotal: \"494756989125880091796620\",\n      volTotal: \"168531072982733277135\",\n    },\n    {\n      price: 0.00035333,\n      amt: \"10480325106225117837726\",\n      vol: \"3702918166647567295\",\n      amtTotal: \"505237314232105209634346\",\n      volTotal: \"172233991149380844430\",\n    },\n    {\n      price: 0.00035401,\n      amt: \"10460158295034970667917\",\n      vol: \"3702903646543510388\",\n      amtTotal: \"515697472527140180302263\",\n      volTotal: \"175936894795924354818\",\n    },\n    {\n      price: 0.0003547,\n      amt: \"10756101480844670483856\",\n      vol: \"3815097705412174743\",\n      amtTotal: \"526453574007984850786119\",\n      volTotal: \"179751992501336529561\",\n    },\n    {\n      price: 0.000355,\n      amt: \"2879934000000000000000\",\n      vol: \"1022376570000000000\",\n      amtTotal: \"529333508007984850786119\",\n      volTotal: \"180774369071336529561\",\n    },\n    {\n      price: 0.00035539,\n      amt: \"10419392212908119384882\",\n      vol: \"3702874294964379056\",\n      amtTotal: \"539752900220892970171001\",\n      volTotal: \"184477243366300908617\",\n    },\n    {\n      price: 0.00035607,\n      amt: \"10399400937404414745812\",\n      vol: \"3702859901246016389\",\n      amtTotal: \"550152301158297384916813\",\n      volTotal: \"188180103267546925006\",\n    },\n    {\n      price: 0.00035675,\n      amt: \"10379467141462596339294\",\n      vol: \"3702845548912938279\",\n      amtTotal: \"560531768299759981256107\",\n      volTotal: \"191882948816459863285\",\n    },\n    {\n      price: 0.00035781,\n      amt: \"10673207910450037674513\",\n      vol: \"3818930797471485007\",\n      amtTotal: \"571204976210210018930620\",\n      volTotal: \"195701879613931348292\",\n    },\n    {\n      price: 0.00035815,\n      amt: \"10339171406073422424770\",\n      vol: \"3702919927697518809\",\n      amtTotal: \"581544147616283441355390\",\n      volTotal: \"199404799541628867101\",\n    },\n    {\n      price: 0.00035883,\n      amt: \"10319410450646547471681\",\n      vol: \"3702905502200057190\",\n      amtTotal: \"591863558066929988827071\",\n      volTotal: \"203107705043828924291\",\n    },\n    {\n      price: 0.00035887,\n      amt: \"1253970999999999795200\",\n      vol: \"449999996860000051\",\n      amtTotal: \"593117529066929988622271\",\n      volTotal: \"203557705040688924342\",\n    },\n    {\n      price: 0.00035952,\n      amt: \"10299706093934767574874\",\n      vol: \"3702891118019657590\",\n      amtTotal: \"603417235160864756197145\",\n      volTotal: \"207260596158708581932\",\n    },\n    {\n      price: 0.00036,\n      amt: \"491031000000000000000\",\n      vol: \"176771040000000000\",\n      amtTotal: \"603908266160864756197145\",\n      volTotal: \"207437367198708581932\",\n    },\n    {\n      price: 0.00036022,\n      amt: \"10591268908994289896668\",\n      vol: \"3815084938649532411\",\n      amtTotal: \"614499535069859046093813\",\n      volTotal: \"211252452137358114343\",\n    },\n  ],\n  asks_prices: [\n    0.00033331, 0.0003336, 0.00033371, 0.00033439, 0.00033501, 0.00033506,\n    0.00033572, 0.00033638, 0.000337, 0.00033706, 0.00033773, 0.00033848,\n    0.00033893, 0.00033907, 0.00033934, 0.00033975, 0.00034042, 0.00034061,\n    0.00034109, 0.00034176, 0.00034244, 0.00034312, 0.00034379, 0.00034447,\n    0.00034515, 0.00034582, 0.00034649, 0.00034718, 0.00034809, 0.00034854,\n    0.00034922, 0.00034991, 0.00035059, 0.00035127, 0.00035196, 0.00035265,\n    0.00035333, 0.00035401, 0.0003547, 0.000355, 0.00035539, 0.00035607,\n    0.00035675, 0.00035781, 0.00035815, 0.00035883, 0.00035887, 0.00035952,\n    0.00036, 0.00036022,\n  ],\n  asks_amtTotals: [\n    \"26466599999999999737856\",\n    \"60347400000000000786432\",\n    \"71489877800817400774420\",\n    \"82900001904293292971822\",\n    \"122234201904293285893934\",\n    \"133286497438765440124271\",\n    \"144316953761678803833989\",\n    \"155325635540196872873465\",\n    \"162513809223956873012729\",\n    \"173833381174065333754584\",\n    \"184798051906578645141799\",\n    \"195741142503458096012774\",\n    \"226827452515978096139750\",\n    \"237749026624062181212249\",\n    \"259810800193782182445145\",\n    \"271040893678352643551479\",\n    \"281918977553464164143875\",\n    \"300948619498234164597507\",\n    \"311805378231938450795419\",\n    \"322640874470793345809679\",\n    \"333782546270039087912453\",\n    \"344575064903739228314494\",\n    \"355346509388628001578471\",\n    \"366422384688283658190129\",\n    \"377151231708579242981712\",\n    \"387859190708127349643612\",\n    \"398546322628019364152161\",\n    \"409535587833613328278263\",\n    \"420180620961041407426017\",\n    \"430805010237312954583534\",\n    \"441408815656007036758006\",\n    \"452312482708073271321136\",\n    \"462874680253020903023688\",\n    \"473416474325570052501445\",\n    \"484256438830853486889382\",\n    \"494756989125880091796620\",\n    \"505237314232105209634346\",\n    \"515697472527140180302263\",\n    \"526453574007984850786119\",\n    \"529333508007984850786119\",\n    \"539752900220892970171001\",\n    \"550152301158297384916813\",\n    \"560531768299759981256107\",\n    \"571204976210210018930620\",\n    \"581544147616283441355390\",\n    \"591863558066929988827071\",\n    \"593117529066929988622271\",\n    \"603417235160864756197145\",\n    \"603908266160864756197145\",\n    \"614499535069859046093813\",\n  ],\n  asks_volTotals: [\n    \"8821317780000000000\",\n    \"20123952660000000000\",\n    \"23842308926910774549\",\n    \"27657649326129174254\",\n    \"40834606326129174254\",\n    \"44537715265574389972\",\n    \"48240808917571514537\",\n    \"51943887327387562395\",\n    \"54366229977077844891\",\n    \"58181506989788887393\",\n    \"61884554591872731921\",\n    \"65588475801549829728\",\n    \"76124247990993108576\",\n    \"79827374641180933486\",\n    \"87313596266594021742\",\n    \"91128922945314033350\",\n    \"94832018717436447739\",\n    \"101313705060244556795\",\n    \"105016785691516572049\",\n    \"108719851226417244234\",\n    \"112535115125740675291\",\n    \"116238150146541687601\",\n    \"119941170204697043840\",\n    \"123756387388505765936\",\n    \"127459377202461261011\",\n    \"131162352185922025377\",\n    \"134865312382156233917\",\n    \"138680468072798172212\",\n    \"142385809710107234072\",\n    \"146088831602957234796\",\n    \"149791838675429779745\",\n    \"153607042628053234014\",\n    \"157310019742856681519\",\n    \"161012982167160002116\",\n    \"164828140253949772769\",\n    \"168531072982733277135\",\n    \"172233991149380844430\",\n    \"175936894795924354818\",\n    \"179751992501336529561\",\n    \"180774369071336529561\",\n    \"184477243366300908617\",\n    \"188180103267546925006\",\n    \"191882948816459863285\",\n    \"195701879613931348292\",\n    \"199404799541628867101\",\n    \"203107705043828924291\",\n    \"203557705040688924342\",\n    \"207260596158708581932\",\n    \"207437367198708581932\",\n    \"211252452137358114343\",\n  ],\n  asks_amtTotal: \"614499535069859046093813\",\n  asks_volTotal: \"211252452137358114343\",\n};\n//v3/amm/balance?poolAddress=0xfEB069407df0e1e4B365C10992F1bc16c078E34b\nexport const ammPoolSnapshot: sdk.AmmPoolSnapshot = {\n  poolName: \"AMM-LRC-ETH\",\n  poolAddress: \"0x18920d6e6fb7ebe057a4dd9260d6d95845c95036\",\n  pooled: [\n    {\n      tokenId: 1,\n      volume: \"11198097977488137000000000\",\n    },\n    {\n      tokenId: 0,\n      volume: \"3725368050950874300000\",\n    },\n  ],\n  lp: {\n    tokenId: 83,\n    volume: \"34138981282200\",\n  },\n  risky: false,\n};\n//v3/amm/balance?poolAddress=0xfEB069407df0e1e4B365C10992F1bc16c078E34b\nexport const ammPool = {\n  poolName: \"AMM-LRC-ETH\",\n  poolAddress: \"0x18920d6e6fb7ebe057a4dd9260d6d95845c95036\",\n  pooled: [\n    { tokenId: 1, volume: \"11215027899488137000000000\" },\n    { tokenId: 0, volume: \"3720052711450874300000\" },\n  ],\n  lp: { tokenId: 83, volume: \"34141365482200\" },\n  risky: false,\n};\n\n//v3/mix/ticker?market=LRC-ETH\nexport const ticker = {\n  tickers: [\n    [\n      \"COMBINE-LRC-ETH\",\n      \"1655625077879\",\n      \"2429371927000000000000000\",\n      \"814655525450000000000\",\n      \"0.00035052\",\n      \"0.00035222\",\n      \"0.00032201\",\n      \"0.00033367\",\n      \"772\",\n      \"\",\n      \"\",\n      \"\",\n      \"\",\n    ],\n  ],\n};\n\n//v3/user/orderUserRateAmount?accountId=10427&market=LRC-ETH\nexport const userAmount = {\n  \"LRC-ETH\": {\n    LRC: {\n      tokenSymbol: \"LRC\",\n      baseOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"231046501539337141\",\n    },\n    ETH: {\n      tokenSymbol: \"ETH\",\n      baseOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"75150737796750\",\n    },\n  },\n  \"AMM-LRC-ETH\": {\n    LRC: {\n      tokenSymbol: \"LRC\",\n      baseOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"266240681576144834931\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"231046501539337141\",\n    },\n    ETH: {\n      tokenSymbol: \"ETH\",\n      baseOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      userOrderInfo: {\n        minAmount: \"86598080986525339\",\n        makerRate: 0,\n        takerRate: 10,\n      },\n      tradeCost: \"75150737796750\",\n    },\n  },\n};\nexport const TokenMapMockSwap = {\n  ETH: {\n    type: \"ETH\",\n    tokenId: 0,\n    symbol: \"ETH\",\n    name: \"Ethereum\",\n    address: \"0x0000000000000000000000000000000000000000\",\n    decimals: 18,\n    precision: 7,\n    precisionForOrder: 3,\n    orderAmounts: {\n      minimum: \"1700000000000000\",\n      maximum: \"1000000000000000000000\",\n      dust: \"200000000000000\",\n    },\n    luckyTokenAmounts: {\n      minimum: \"50000000000000\",\n      maximum: \"1000000000000000000000\",\n      dust: \"50000000000000\",\n    },\n    fastWithdrawLimit: \"100000000000000000000\",\n    gasAmounts: {\n      distribution: \"85000\",\n      deposit: \"110000\",\n    },\n    enabled: true,\n    isLpToken: false,\n    tradePairs: [\"LRC\"],\n  },\n  LRC: {\n    type: \"ERC20\",\n    tokenId: 1,\n    symbol: \"LRC\",\n    name: \"Loopring\",\n    address: \"0xbbbbca6a901c926f240b89eacb641d8aec7aeafd\",\n    decimals: 18,\n    precision: 3,\n    precisionForOrder: 3,\n    orderAmounts: {\n      minimum: \"5000000000000000000\",\n      maximum: \"5000000000000000000000000\",\n      dust: \"5000000000000000000\",\n    },\n    luckyTokenAmounts: {\n      minimum: \"50000000000000000\",\n      maximum: \"5000000000000000000000000\",\n      dust: \"50000000000000000\",\n    },\n    fastWithdrawLimit: \"750000000000000000000000\",\n    gasAmounts: {\n      distribution: \"101827\",\n      deposit: \"150000\",\n    },\n    enabled: true,\n    isLpToken: false,\n    tradePairs: [\"ETH\"],\n  },\n};\n\nexport const MAPFEEBIPS = 63;\n\n\n```\n\n"
  },
  {
    "path": "src/tests/demo/erc20Trade/orderERC20.test.ts",
    "content": "import {\n  AMM_MAP,\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  signatureKeyPairMock,\n  TOKEN_INFO,\n} from \"../../MockData\";\nimport {\n  deepMock,\n  ammPool,\n  ticker,\n  userAmount,\n  MAPFEEBIPS,\n  marketArray,\n  marketMap,\n  TokenMapMockSwap,\n  ammPoolSnapshot as ammPoolSnapshotMock,\n} from \"../../MockSwapData\";\nimport * as sdk from \"../../../index\";\nimport BigNumber from \"bignumber.js\";\nlet apiKey = \"\";\n// const { tokenMap } = TOKEN_INFO;\n// const ammMap = AMM_MAP;\nconst calculateSwap = (\n  sellSymbol = \"LRC\",\n  buySymbol = \"ETH\",\n  isInputSellToBuy: boolean,\n  inputValue: number, // user Input value no decimal,\n  _slippage = 0.1,\n  // MOCK value\n  amountMap: { [key: string]: any } = userAmount,\n  market: string = deepMock.symbol,\n  // close = ticker.tickers[7],\n  depth: any = deepMock,\n  ammPoolSnapshot: sdk.AmmPoolSnapshot = ammPoolSnapshotMock,\n  tokenMap: sdk.LoopringMap<sdk.TokenInfo> = TokenMapMockSwap,\n  ammMap: { [key: string]: any } = AMM_MAP\n) => {\n  let calcFor100USDAmount, calcForMinCost, calcForPriceImpact;\n  if (depth && market && tokenMap) {\n    const sellToken = tokenMap[sellSymbol];\n    const buyToken = tokenMap[buySymbol];\n    const isInputSellOutputBuy = isInputSellToBuy;\n    let input: any = inputValue;\n\n    console.log(\n      \"sellToken: Symbol \",\n      sellSymbol,\n      \"buyToken: Symbol\",\n      buySymbol,\n      \"is Input Sell Output Buy:\",\n      isInputSellOutputBuy,\n      \"input value\",\n      input\n    );\n    input = input === undefined || isNaN(Number(input)) ? 0 : Number(input);\n    let slippage = sdk.toBig(_slippage).times(100).toString();\n    let totalFee = undefined;\n    let feeTakerRate = undefined;\n    let feeBips = undefined;\n    let takerRate = undefined;\n    let buyMinAmtInfo = undefined;\n    let sellMinAmtInfo = undefined;\n    let tradeCost = undefined;\n    let basePrice = undefined;\n    let maxFeeBips = MAPFEEBIPS;\n    let minAmt = undefined;\n\n    if (amountMap && amountMap[market] && ammMap) {\n      console.log(`amountMap[${market}]:`, amountMap[market]);\n\n      const ammMarket = `AMM-${market}`;\n\n      const amountMarket = amountMap[market]; // userAmount from  LRC-ETH(Market)\n\n      buyMinAmtInfo = amountMarket[buySymbol];\n      sellMinAmtInfo = amountMarket[sellSymbol];\n      console.log(\n        `buyMinAmtInfo: ${market}, ${buySymbol}`,\n        buyMinAmtInfo,\n        `sellMinAmtInfo: ${market}, ${sellSymbol}`,\n        sellMinAmtInfo\n      );\n\n      feeBips = ammMap[ammMarket] ? ammMap[ammMarket].feeBips : 1;\n\n      feeTakerRate =\n        amountMarket[buySymbol] &&\n        amountMarket[buySymbol].userOrderInfo.takerRate;\n      tradeCost = amountMarket[buySymbol].tradeCost;\n\n      /** @description for charge fee calc, calcFor100USDAmount\n       *  Loopring market consider buyToken value small then  max(buyMinAmtInfo.userOrderInfo.minAmount,buyToken.orderAmounts.dust) is a small order,\n       * the fee will take the Max(tradeCost,userTakeRate)\n       * use the buyMinAmount Input calc the selltoken value,\n       * please read Line:321\n       * **/\n      const minAmountInput = BigNumber.max(\n        buyMinAmtInfo.userOrderInfo.minAmount,\n        buyToken.orderAmounts.dust\n      )\n        .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n        .div(\"1e\" + buyToken.decimals)\n        .toString();\n      calcFor100USDAmount = sdk.getOutputAmount({\n        input: minAmountInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: false,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: slippage,\n      });\n\n      console.log(\n        \"buyMinAmtInfo.userOrderInfo.minAmount:\",\n        buyMinAmtInfo.userOrderInfo.minAmount,\n        `buyMinAmtInfo.userOrderInfo.minAmount, with slippage:${slippage}`,\n        sdk\n          .toBig(buyMinAmtInfo.userOrderInfo.minAmount)\n          .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n          .toString()\n      );\n\n      /*** calc for Price Impact ****/\n      const sellMinAmtInput = sdk\n        .toBig(sellMinAmtInfo.baseOrderInfo.minAmount)\n        .div(\"1e\" + sellToken.decimals)\n        .toString();\n\n      calcForPriceImpact = sdk.getOutputAmount({\n        input: sellMinAmtInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: true,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: \"10\",\n      });\n\n      basePrice = sdk.toBig(calcForPriceImpact?.output).div(sellMinAmtInput);\n\n      console.log(\n        \"calcForPriceImpact input: \",\n        sellMinAmtInput,\n        \", output: \",\n        sdk.toBig(calcForPriceImpact?.output).div(sellMinAmtInput).toNumber(),\n        \", calcForPriceImpact:\",\n        calcForPriceImpact?.amountBOutSlip?.minReceivedVal,\n        \", calcForPriceImpact basePrice: \",\n        basePrice.toNumber()\n      );\n\n      /**** calc for mini Cost ****/\n\n      //minCostBuyToken = max(dustBuyToken, tradeCostETH/maxAllowBips)\n      const dustToken = buyToken;\n      let minCostBuyTokenInput = BigNumber.max(\n        sdk.toBig(tradeCost).times(2), //maxAllowBips = 50% tradeCostETH/50%\n        dustToken.orderAmounts.dust\n      );\n\n      const tradeCostInput = sdk\n        .toBig(minCostBuyTokenInput)\n        .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n        .div(\"1e\" + dustToken.decimals)\n        .toString();\n\n      console.log(\n        `tradeCost: ${tradeCost}*2:`,\n        sdk.toBig(tradeCost).times(2).toString(),\n        \"buyToken.orderAmounts.dust\",\n        buyToken.orderAmounts.dust,\n        \"minCostBuyToken:\",\n        minCostBuyTokenInput.toString(),\n        `calcForMinCostInput, with slippage:${slippage}`,\n        sdk\n          .toBig(minCostBuyTokenInput ?? 0)\n          .div(sdk.toBig(1).minus(sdk.toBig(slippage).div(10000)))\n          .toString(),\n        \"calcForMinCost, Input\",\n        tradeCostInput\n      );\n\n      calcForMinCost = sdk.getOutputAmount({\n        input: tradeCostInput,\n        sell: sellSymbol,\n        buy: buySymbol,\n        isAtoB: false,\n        marketArr: marketArray as string[],\n        tokenMap: tokenMap as any,\n        marketMap: marketMap as any,\n        depth,\n        ammPoolSnapshot: ammPoolSnapshot,\n        feeBips: feeBips ? feeBips.toString() : 1,\n        takerRate: \"0\",\n        slipBips: slippage,\n      });\n\n      //add additionally 10% tolerance for minimum quantity user has to set on sell Token\n      /**\n       * @output: minAmt for UI\n       * this value mini-order Sell token amount (show on the UI for available order check)\n       * setSellMinAmt(minAmt.toString());\n       */\n      minAmt = BigNumber.max(\n        sellToken.orderAmounts.dust,\n        calcForMinCost?.amountS ?? 0\n      ).times(1.1);\n\n      console.log(\n        \"UI show mini-order Sell token amount:\",\n        minAmt.toString(),\n        sdk\n          .toBig(minAmt)\n          .div(\"1e\" + sellToken.decimals)\n          .toString()\n      );\n\n      console.log(\n        `calcFor100USDAmount.amountS`,\n        sdk\n          .toBig(calcFor100USDAmount?.amountS ?? 0)\n          .div(\"1e\" + sellToken.decimals)\n          .toString(),\n        \"calcForMinCost.amountS\",\n        sdk\n          .toBig(calcForMinCost?.amountS ?? 0)\n          .div(\"1e\" + sellToken.decimals)\n          .toString()\n      );\n    }\n    const calcTradeParams = sdk.getOutputAmount({\n      input: input.toString(),\n      sell: sellSymbol,\n      buy: buySymbol,\n      isAtoB: isInputSellOutputBuy,\n      marketArr: marketArray as string[],\n      tokenMap: tokenMap as any,\n      marketMap: marketMap as any,\n      depth,\n      ammPoolSnapshot: ammPoolSnapshot,\n      feeBips: feeBips ? feeBips.toString() : 1,\n      takerRate: \"0\", // for new calc miniReceive will minus fee, so takeRate can fix as 0\n      slipBips: slippage,\n    });\n\n    const minSymbol = buySymbol;\n    const tradePrice = sdk\n      .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n      .div(isInputSellOutputBuy ? input.toString() : calcTradeParams?.output);\n    const priceImpact = sdk\n      .toBig(1)\n      .minus(sdk.toBig(tradePrice).div(basePrice ?? 1))\n      .minus(0.001);\n    if (calcTradeParams && priceImpact.gte(0)) {\n      calcTradeParams.priceImpact = priceImpact.toFixed(4, 1);\n    } else {\n      calcTradeParams && (calcTradeParams.priceImpact = \"0\");\n    }\n\n    console.log(\n      \"calcTradeParams input:\",\n      input.toString(),\n      \", calcTradeParams Price: \",\n      sdk\n        .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n        .div(input.toString())\n        .toNumber(),\n      `isAtoB mean isInputSellOutputBuy:${isInputSellOutputBuy}, ${\n        isInputSellOutputBuy ? input.toString() : calcTradeParams?.output\n      } tradePrice: `,\n      tradePrice.toString(),\n      \"basePrice: \",\n      basePrice?.toString(),\n      \"toBig(tradePrice).div(basePrice)\",\n      sdk\n        .toBig(tradePrice)\n        .div(basePrice ?? 1)\n        .toNumber(),\n      \"priceImpact (1-tradePrice/basePrice) - 0.001\",\n      priceImpact.toNumber(),\n      \"priceImpact view\",\n      calcTradeParams?.priceImpact\n    );\n\n    if (\n      tradeCost &&\n      calcTradeParams &&\n      calcTradeParams.amountBOutSlip?.minReceived &&\n      feeTakerRate\n    ) {\n      let value = sdk\n        .toBig(calcTradeParams.amountBOutSlip?.minReceived)\n        .times(feeTakerRate)\n        .div(10000);\n\n      console.log(\n        \"input Accounts\",\n        calcTradeParams?.amountS,\n        \"100 U Amount Sell:\",\n        calcFor100USDAmount?.amountS\n      );\n\n      let validAmt = !!(\n        calcTradeParams?.amountS &&\n        calcFor100USDAmount?.amountS &&\n        sdk.toBig(calcTradeParams?.amountS).gte(calcFor100USDAmount.amountS)\n      );\n      let totalFeeRaw;\n\n      console.log(\n        `${minSymbol} tradeCost:`,\n        tradeCost,\n        \"useTakeRate Fee:\",\n        value.toString(),\n        \"calcFor100USDAmount?.amountS:\",\n        calcFor100USDAmount?.amountS,\n        `is setup minTrade amount, ${calcFor100USDAmount?.amountS}:`,\n        validAmt\n      );\n\n      if (!validAmt) {\n        if (sdk.toBig(tradeCost).gte(value)) {\n          totalFeeRaw = sdk.toBig(tradeCost);\n        } else {\n          totalFeeRaw = value;\n        }\n        console.log(\n          \"maxFeeBips update for tradeCost before value:\",\n          maxFeeBips,\n          \"totalFeeRaw\",\n          totalFeeRaw.toString()\n        );\n        maxFeeBips = Math.ceil(\n          totalFeeRaw\n            .times(10000)\n            .div(calcTradeParams.amountBOutSlip?.minReceived)\n            .toNumber()\n        );\n        console.log(\"maxFeeBips update for tradeCost after value:\", maxFeeBips);\n      } else {\n        totalFeeRaw = sdk.toBig(value);\n      }\n\n      /**\n       * totalFee\n       */\n      totalFee = totalFeeRaw\n        .div(\"1e\" + tokenMap[minSymbol].decimals)\n        .toString();\n      /** @output: UI\n       *   getValuePrecisionThousand(\n       *   totalFeeRaw.div(\"1e\" + tokenMap[minSymbol].decimals).toString(),\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   false,\n       *   { floor: true }\n       * );\n       */\n\n      tradeCost = sdk\n        .toBig(tradeCost)\n        // @ts-ignore\n        .div(\"1e\" + tokenMap[minSymbol].decimals)\n        .toString();\n\n      /** @output:  UI code with precision\n       *   getValuePrecisionThousand(\n       *   sdk\n       *     .toBig(tradeCost)\n       *     .div(\"1e\" + tokenMap[minSymbol].decimals)\n       *     .toString(),\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   tokenMap[minSymbol].precision,\n       *   false,\n       *   { floor: true }\n       * );\n       */\n\n      console.log(\"totalFee view value:\", totalFee + \" \" + minSymbol);\n      console.log(\"tradeCost view value:\", tradeCost + \" \" + minSymbol);\n    }\n\n    const minimumReceived = sdk\n      .toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n      .minus(totalFee ?? 0)\n      .toString();\n    console.log(\"minimumReceived:\", minimumReceived);\n\n    /** @output:   UI code with precision\n     *   getValuePrecisionThousand(\n     *   toBig(calcTradeParams?.amountBOutSlip?.minReceivedVal ?? 0)\n     *     .minus(totalFee)\n     *     .toString(),\n     *   tokenMap[minSymbol].precision,\n     *   tokenMap[minSymbol].precision,\n     *   tokenMap[minSymbol].precision,\n     *   false,\n     *   { floor: true }\n     * );\n     */\n\n    let priceImpactView: any = calcTradeParams?.priceImpact\n      ? parseFloat(calcTradeParams?.priceImpact) * 100\n      : undefined;\n    console.log(\"priceImpact view:\", priceImpactView + \"%\");\n    //  @output:   UI code with color alert\n    // const priceImpactObj = getPriceImpactInfo(calcTradeParams);\n    // const _tradeCalcData: Partial<TradeCalcData<C>> = {\n    //   priceImpact: priceImpactObj.value.toString(),\n    //   priceImpactColor: priceImpactObj.priceImpactColor,\n    //   minimumReceived: !minimumReceived?.toString().startsWith(\"-\")\n    //     ? minimumReceived\n    //     : undefined,\n    //   fee: totalFee,\n    //   feeTakerRate,\n    //   tradeCost,\n    // };\n\n    console.log(\n      `isInputSellOutputBuy:${isInputSellOutputBuy}`,\n      `output ${isInputSellOutputBuy ? \"Buy\" : \"Sell\"}`,\n      calcTradeParams?.output\n    );\n\n    return {\n      market,\n      feeBips,\n      takerRate,\n      sellMinAmtInfo: sellMinAmtInfo as any,\n      buyMinAmtInfo: buyMinAmtInfo as any,\n      totalFee,\n      maxFeeBips,\n      feeTakerRate,\n      tradeCost,\n      minimumReceived,\n      calcTradeParams,\n      minAmt,\n    };\n  }\n};\ndescribe(\"orderERC20\", function () {\n  beforeEach(async () => {\n    // deepMock, ammPool, ticker should update every 15's, useAmount should update every 15 minutes\n    jest.setTimeout(DEFAULT_TIMEOUT * 3);\n    LOOPRING_EXPORTED_ACCOUNT.gasPrice = (\n      await LoopringAPI.exchangeAPI.getGasPrice()\n    ).gasPrice;\n  }, DEFAULT_TIMEOUT);\n  it(\"Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder\", async () => {\n    const inputValue = 5.6;\n    const slippage = 0.1;\n    console.log(\n      `output Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder Input value: ${inputValue},slippage: ${slippage} `,\n      calculateSwap(\n        \"LRC\", //sellSymbol\n        \"ETH\", //buySymbol\n        true, //isInputSellToBuy\n        inputValue, // user Input value no decimal,\n        slippage //_slippage\n      )\n    );\n  });\n  it(\"Swap_SellLRC_BuyETH_USER_INPUT_LRC_lessThenMiniOrder\", async () => {\n    const inputValue = 1;\n    const slippage = 0.1;\n    console.log(\n      `output Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder Input value: ${inputValue},slippage: ${slippage} `,\n      calculateSwap(\n        \"LRC\", //sellSymbol\n        \"ETH\", //buySymbol\n        true, //isInputSellToBuy\n        inputValue, // user Input value no decimal,\n        slippage //_slippage\n      )\n    );\n  });\n  it(\"Swap_SellLRC_BuyETH_USER_INPUT_LRC_LargeOrder\", async () => {\n    const inputValue = 100000;\n    const slippage = 0.1;\n    console.log(\n      `output Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder Input value: ${inputValue},slippage: ${slippage} `,\n      calculateSwap(\n        \"LRC\", //sellSymbol\n        \"ETH\", //buySymbol\n        true, //isInputSellToBuy\n        inputValue, // user Input value no decimal,\n        slippage //_slippage\n      )\n    );\n  });\n  it(\"Swap_SellLRC_BuyETH_USER_INPUT_LRC_Slippage50\", async () => {\n    const inputValue = 5.6;\n    const slippage = 50;\n    console.log(\n      `output Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder Input value: ${inputValue},slippage: ${\n        slippage * 50\n      } `,\n      calculateSwap(\n        \"LRC\", //sellSymbol\n        \"ETH\", //buySymbol\n        true, //isInputSellToBuy\n        inputValue, // user Input value no decimal,\n        slippage //_slippage\n      )\n    );\n  });\n  it(\"Swap_SellLRC_BuyETH_USER_INPUT_ETH_miniOrder\", async () => {\n    const inputValue = 0.0019;\n    const slippage = 0.1;\n    console.log(\n      `output Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder Input value: ${inputValue},slippage: ${\n        slippage * 50\n      } `,\n      calculateSwap(\n        \"LRC\", //sellSymbol\n        \"ETH\", //buySymbol\n        false, //isInputSellToBuy\n        inputValue, // user Input value no decimal,\n        slippage //_slippage\n      )\n    );\n  });\n  it(\"Swap_SellETH_BuyLRC_USER_INPUT_ETH\", async () => {\n    const inputValue = 0.0017999;\n    const slippage = 0.1;\n    console.log(\n      `output Swap_SellLRC_BuyETH_USER_INPUT_LRC_miniOrder Input value: ${inputValue},slippage: ${\n        slippage * 50\n      } `,\n      calculateSwap(\n        \"ETH\", //sellSymbol\n        \"LRC\", //buySymbol\n        false, //isInputSellToBuy\n        inputValue, // user Input value no decimal,\n        slippage //_slippage\n      )\n    );\n  });\n  it(\n    \"RealOrderLRC-ETH_AtoB\",\n    async () => {\n      try {\n        // MOCK Data\n        const buy = \"ETH\",\n          sell = \"LRC\",\n          MARKET = \"LRC-ETH\",\n          AMM_MARKET = \"AMM-LRC-ETH\",\n          isAtoB = true,\n          slippage = \"50\";\n\n        // Step 1. get apikey & eddsaKey\n        const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n          owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        });\n        const eddsaKey = await signatureKeyPairMock(accInfo);\n        apiKey = (\n          await LoopringAPI.userAPI.getUserApiKey(\n            {\n              accountId: accInfo.accountId,\n            },\n            eddsaKey.sk\n          )\n        ).apiKey;\n\n        // Step 2. storageId\n        const storageId = await LoopringAPI.userAPI.getNextStorageId(\n          {\n            accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n            sellTokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n          },\n          apiKey\n        );\n\n        // Step 3. get user AmountMap, which decided user minimum order\n        const amountMap = {\n          [AMM_MARKET]: (\n            await LoopringAPI.userAPI.getMinimumTokenAmt(\n              {\n                accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n                market: AMM_MAP[AMM_MARKET].market,\n              },\n              apiKey\n            )\n          ).amountMap,\n          [MARKET]: (\n            await LoopringAPI.userAPI.getMinimumTokenAmt(\n              {\n                accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n                market: MARKET,\n              },\n              apiKey\n            )\n          ).amountMap,\n        };\n\n        // Step 4. depth, ammPoolSnapshot, tickMap\n        const [{ depth }, { ammPoolSnapshot }] = await Promise.all([\n          LoopringAPI.exchangeAPI.getMixDepth({\n            market: AMM_MAP[\"AMM-LRC-ETH\"].market,\n          }),\n          LoopringAPI.ammpoolAPI.getAmmPoolSnapshot({\n            poolAddress: AMM_MAP[\"AMM-LRC-ETH\"].address,\n          }),\n        ]);\n\n        // Step 5. check MinAmt see log and calc mini receive and ouput value & maxfeeBips & priceImpact\n        // @ts-ignore\n        const { calcTradeParams, maxFeeBips, minimumReceived } = calculateSwap(\n          sell,\n          buy,\n          isAtoB,\n          10, // user Input value no decimal 10 lrc,\n          0.1,\n          amountMap,\n          \"LRC-ETH\",\n          // close = ticker.tickers[7],\n          depth,\n          ammPoolSnapshot,\n          TOKEN_INFO.tokenMap,\n          AMM_MAP\n        );\n\n        console.log(\n          \"calcTradeParams\",\n          calcTradeParams,\n          \"minimumReceived\",\n          minimumReceived,\n          \"maxFeeBips\",\n          maxFeeBips\n        );\n\n        // Step 6. submit\n        const response: { hash: string } | any =\n          await LoopringAPI.userAPI.submitOrder(\n            {\n              exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n              accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n              storageId: storageId.orderId,\n              sellToken: {\n                tokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n                volume: calcTradeParams?.amountS as string,\n              },\n              buyToken: {\n                tokenId: TOKEN_INFO.tokenMap[buy].tokenId,\n                volume: calcTradeParams?.amountBOutSlip.minReceived as string,\n              },\n              allOrNone: false,\n              validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n              maxFeeBips: maxFeeBips,\n              fillAmountBOrS: false, // amm only false\n              tradeChannel: calcTradeParams?.exceedDepth\n                ? sdk.TradeChannel.BLANK\n                : sdk.TradeChannel.MIXED,\n              orderType: calcTradeParams?.exceedDepth\n                ? sdk.OrderType.ClassAmm\n                : sdk.OrderType.TakerOnly,\n              eddsaSignature: \"\",\n            },\n            eddsaKey.sk,\n            apiKey\n          );\n        console.log(\"submitOrder\", response);\n      } catch (err) {\n        console.log(err);\n      }\n    },\n    DEFAULT_TIMEOUT\n  );\n  //\n  // it(\n  //   \"RealOrderETH-LRC_BtoA\",\n  //   async () => {\n  //     try {\n  //       // before user should have apikey, please check get apikey\n  //       const buy = \"ETH\",\n  //         sell = \"LRC\",\n  //         MARKET = \"LRC-ETH\",\n  //         AMM_MARKET = \"AMM-LRC-ETH\",\n  //         slippage = \"50\";\n  //       const isAtoB = false;\n  //\n  //       // Step 1. get apikey & eddsaKey\n  //       const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  //         owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  //       });\n  //       const eddsaKey = await signatureKeyPairMock(accInfo);\n  //       apiKey = (\n  //         await LoopringAPI.userAPI.getUserApiKey(\n  //           {\n  //             accountId: accInfo.accountId,\n  //           },\n  //           eddsaKey.sk\n  //         )\n  //       ).apiKey;\n  //\n  //       // Step 2. storageId\n  //       const storageId = await LoopringAPI.userAPI.getNextStorageId(\n  //         {\n  //           accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //           sellTokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n  //         },\n  //         apiKey\n  //       );\n  //\n  //       // Step 3. get user AmountMap, which decided user minimum order\n  //       const amountMap = {\n  //         [AMM_MARKET]: (\n  //           await LoopringAPI.userAPI.getMinimumTokenAmt(\n  //             {\n  //               accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //               market: AMM_MAP[AMM_MARKET].market,\n  //             },\n  //             apiKey\n  //           )\n  //         ).amountMap,\n  //         [MARKET]: (\n  //           await LoopringAPI.userAPI.getMinimumTokenAmt(\n  //             {\n  //               accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //               market: MARKET,\n  //             },\n  //             apiKey\n  //           )\n  //         ).amountMap,\n  //       };\n  //\n  //       // Step 4.  depth,  ammPoolSnapshot ,tickMap\n  //       const [{ depth }, { ammPoolSnapshot }] = await Promise.all([\n  //         LoopringAPI.exchangeAPI.getMixDepth({\n  //           market: AMM_MAP[\"AMM-LRC-ETH\"].market,\n  //         }),\n  //         LoopringAPI.ammpoolAPI.getAmmPoolSnapshot({\n  //           poolAddress: AMM_MAP[\"AMM-LRC-ETH\"].address,\n  //         }),\n  //       ]);\n  //\n  //       // Step 5. check  MinAmt\n  //       const amount: sdk.LoopringMap<sdk.TokenAmount> =\n  //         amountMap[AMM_MARKET] ?? amountMap[MARKET];\n  //\n  //       let buyMinAmtInfo = amount[buy];\n  //       // let sellMinAmtInfo = amount[sell];\n  //\n  //       let takerRate = buyMinAmtInfo\n  //         ? buyMinAmtInfo.userOrderInfo.takerRate\n  //         : 0;\n  //\n  //       const minAmountInput = buyMinAmtInfo.userOrderInfo.minAmount;\n  //\n  //       // Step 6. calcTradeParams\n  //       const calcTradeParams = sdk.getOutputAmount({\n  //         input: LOOPRING_EXPORTED_ACCOUNT.tradeETHValue.toString(),\n  //         sell,\n  //         buy,\n  //         isAtoB,\n  //         marketArr: [\"LRC-ETH\", \"ETH-USDT\", \"DAI-USDT\", \"USDC-ETH\"],\n  //         tokenMap: TOKEN_INFO.tokenMap,\n  //         marketMap: TOKEN_INFO.marketMap,\n  //         depth,\n  //         ammPoolSnapshot: ammPoolSnapshot,\n  //         feeBips: AMM_MAP[\"AMM-LRC-ETH\"].feeBips.toString(),\n  //         takerRate: takerRate ? takerRate.toString() : \"0\",\n  //         slipBips: slippage,\n  //       });\n  //       console.log(\n  //         \"Buy\",\n  //         \",ETH:\",\n  //         LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  //         \",minAmountInput ETH:\",\n  //         minAmountInput,\n  //         \",LRC:\",\n  //         calcTradeParams?.amountBOutSlip?.minReceivedVal\n  //       );\n  //\n  //       const response: { hash: string } | any =\n  //         await LoopringAPI.userAPI.submitOrder(\n  //           {\n  //             exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  //             accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //             storageId: storageId.orderId,\n  //             sellToken: {\n  //               tokenId: TOKEN_INFO.tokenMap[sell].tokenId,\n  //               volume: calcTradeParams?.amountS as string,\n  //             },\n  //             buyToken: {\n  //               tokenId: TOKEN_INFO.tokenMap[buy].tokenId,\n  //               volume: calcTradeParams?.amountBOutSlip.minReceived as string,\n  //             },\n  //             allOrNone: false,\n  //             validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  //             maxFeeBips: 63,\n  //             fillAmountBOrS: false, // amm only false\n  //             tradeChannel: calcTradeParams?.exceedDepth\n  //               ? sdk.TradeChannel.BLANK\n  //               : sdk.TradeChannel.MIXED,\n  //             orderType: calcTradeParams?.exceedDepth\n  //               ? sdk.OrderType.ClassAmm\n  //               : sdk.OrderType.TakerOnly,\n  //             eddsaSignature: \"\",\n  //           },\n  //           eddsaKey.sk,\n  //           apiKey\n  //         );\n  //       console.log(\"submitOrder\", response);\n  //     } catch (err) {\n  //       console.log(err);\n  //     }\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n});\n\nexport default {};\n"
  },
  {
    "path": "src/tests/demo/exchange/exchange.md",
    "content": "# Loopring Exchange\n\nDefinition: Loopring Dex Main API for get Exchange Information, L2 Block, ERC20 Token Information, AMM Information,\nMarket Config and so on static and dynamic information\n\n***\n\n## getExchangeInfo\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getExchangeInfo();\nconsole.log(response);\n```\n\n***\n\n## getTokens\n\n```ts\nconst {tokensMap, coinMap, totalCoinMap, idIndex, addressIndex} =\n  await LoopringAPI.exchangeAPI.getTokens<any>();\nconsole.log(\n  \"tokenMap:\",\n  tokensMap,\n  coinMap,\n  totalCoinMap,\n  idIndex,\n  addressIndex\n);\n```\n\n***\n\n## getMixMarkets\n\n```ts\nconst {markets, pairs, tokenArr, tokenArrStr, marketArr, marketArrStr} =\n  await LoopringAPI.exchangeAPI.getMixMarkets();\nconsole.log(\"markets:\", markets);\nconsole.log(\"pairs:\", pairs);\nconsole.log(\"tokenArr:\", tokenArr);\nconsole.log(\"tokenArrStr:\", tokenArrStr);\nconsole.log(\"marketArr\", marketArr);\nconsole.log(\"marketArrStr\", marketArrStr);\n```\n\n***\n\n## getAmmPoolConf\n\n```ts\nconst response = await LoopringAPI.ammpoolAPI.getAmmPoolConf();\nconsole.log(response.ammpools);\nconsole.log(response.pairs);\n```\n\n***\n\n## getAvailableBroker\n\n```ts\nconst result = await LoopringAPI.exchangeAPI.getAvailableBroker();\nconsole.log(result);\n```\n\n***\n\n## getTokenPrices\n\n```ts\nconst response = await LoopringAPI.walletAPI.getTokenPrices({\n  token: TOKEN_INFO.tokenMap.LRC.address,\n});\nconsole.log(response);\n```\n\n***\n\n## getLatestTokenPrices\n\n```ts\nconst response = await LoopringAPI.walletAPI.getLatestTokenPrices();\nconsole.log(response);\n```\n\n***\n\n## getLatestTokenPrices_cny\n\n```ts\nconst response = await LoopringAPI.walletAPI.getLatestTokenPrices({\n  currency: sdk.Currency.cny,\n});\nconsole.log(response);\n```\n\n***\n\n## getWithdrawalAgents\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getWithdrawalAgents({\n  tokenId: 1,\n  amount: \"10000000000\",\n});\nconsole.log(response);\n```\n\n***\n\n## getCandlestick\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getCandlestick({\n  market: \"LRC-ETH\",\n  interval: sdk.TradingInterval.min15,\n  limit: 96,\n});\nconsole.log(response);\n```\n\n***\n\n## getAccountServices\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getAccountServices({});\nconsole.log(response);\n```\n\n***\n\n## getExchangeFeeInfo\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getExchangeFeeInfo<any>();\nconsole.log(response);\nconsole.log(\n  response.raw_data[sdk.VipCatergory.ORDERBOOK_TRADING_FEES_STABLECOIN]\n);\n```\n\n***\n\n## getProtocolPortrait\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getProtocolPortrait();\nconsole.log(response);\n```\n\n***\n\n## getRecommendedMarkets\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getRecommendedMarkets();\nconsole.log(response);\n```\n\n***\n\n## getGasPrice\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getGasPrice();\nconsole.log(response);\n```\n\n***\n\n## getGasPriceRange\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getGasPriceRange();\nconsole.log(response);\n```\n\n***\n\n## getMarketTrades\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMarketTrades<any>({\n  market: \"ETH-USDT\",\n});\nconsole.log(response.raw_data.trades);\n```\n\n***\n\n## getRelayerCurrentTime\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getRelayerCurrentTime();\nconsole.log(response);\n```\n\n***\n\n## getFiatPriceUSD\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getFiatPrice({\n  legal: \"USD\",\n});\nconsole.log(response);\n```\n\n***\n\n## getFiatPriceCNY\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getFiatPrice({\n  legal: \"CNY\",\n});\nconsole.log(response);\n```\n\n***\n\n## getMarkets\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMarkets();\nconsole.log(response);\nconsole.log(response.pairs.LRC.tokenList);\n\nconsole.log(\n  \"hasMarket LRC-ETH:\",\n  sdk.hasMarket(response.marketArr, \"LRC-ETH\")\n);\nconsole.log(\n  \"market 1:\",\n  sdk.getExistedMarket(response.marketArr, \"LRC\", \"ETH\")\n);\nconsole.log(\n  \"market 2:\",\n  sdk.getExistedMarket(response.marketArr, \"ETH\", \"LRC\")\n);\n```\n\n***\n\n## getDepth\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getDepth({\n  market: \"LRC-ETH\",\n});\nconsole.log(response);\n```\n\n***\n\n## getTicker\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getTicker({\n  market: \"LRC-ETH\",\n});\nconsole.log(response);\n```\n\n***\n\n## getAllTickers\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getAllTickers();\nconsole.log(response);\n```\n\n***\n\n## getMixDepth\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMixDepth({\n  market: \"LRC-ETH\",\n});\nconsole.log(response);\nconsole.log(response.depth.bids);\n```\n\n***\n\n## getMixTicker\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMixTicker({\n  market: [\"LRC-ETH\", \"ETH-USDC\", \"DAI-USDT\"].join(\",\"),\n});\nconsole.log(response.tickMap[\"DAI-USDT\"]);\n```\n\n***\n\n## getAllMixTickers\n\n```ts\nconst response: any = await LoopringAPI.exchangeAPI.getAllMixTickers();\nconsole.log(response?.tickMap);\n```\n\n***\n\n## getMixCandlestickAMM\n\n```ts\nconst response = await LoopringAPI.exchangeAPI.getMixCandlestick({\n  market: \"AMM-LRC-ETH\",\n  interval: sdk.TradingInterval.min15,\n  limit: 96,\n});\nconsole.log(response);\n```\n\n});\n\n\n\n"
  },
  {
    "path": "src/tests/demo/exchange/exchange.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\nimport {\n  LoopringMap,\n  MarketInfo,\n  TokenAddress,\n  TokenInfo,\n  TokenRelatedInfo,\n} from \"../../../index\";\nimport { concatSig } from \"eth-sig-util\";\ndescribe(\"exchangeMain\", function () {\n  it(\n    \"getExchangeInfo\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getExchangeInfo();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getTokens\",\n    async () => {\n      const { tokensMap, coinMap, totalCoinMap, idIndex, addressIndex } =\n        await LoopringAPI.exchangeAPI.getTokens<any>();\n      console.log(\n        \"tokenMap:\",\n        tokensMap,\n        coinMap,\n        totalCoinMap,\n        idIndex,\n        addressIndex\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getMixMarkets\",\n    async () => {\n      const { markets, pairs, tokenArr, tokenArrStr, marketArr, marketArrStr } =\n        await LoopringAPI.exchangeAPI.getMixMarkets();\n      console.log(\"markets:\", markets);\n      console.log(\"pairs:\", pairs);\n      console.log(\"tokenArr:\", tokenArr);\n      console.log(\"tokenArrStr:\", tokenArrStr);\n      console.log(\"marketArr\", marketArr);\n      console.log(\"marketArrStr\", marketArrStr);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getAmmPoolConf\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolConf();\n      console.log(response.ammpools);\n      console.log(response.pairs);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getAvailableBroker\",\n    async () => {\n      const result = await LoopringAPI.exchangeAPI.getAvailableBroker({\n        type: 0,\n      });\n      console.log(result);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getTokenPrices\",\n    async () => {\n      const response = await LoopringAPI.walletAPI.getTokenPrices({\n        token: TOKEN_INFO.tokenMap.LRC.address,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getLatestTokenPrices\",\n    async () => {\n      const response = await LoopringAPI.walletAPI.getLatestTokenPrices();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getLatestTokenPrices_cny\",\n    async () => {\n      const response = await LoopringAPI.walletAPI.getLatestTokenPrices({\n        currency: sdk.Currency.cny,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getWithdrawalAgents\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getWithdrawalAgents({\n        tokenId: 1,\n        amount: \"10000000000\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getCandlestick\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getCandlestick({\n        market: \"LRC-ETH\",\n        interval: sdk.TradingInterval.min15,\n        limit: 96,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAccountServices\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getAccountServices({});\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getExchangeFeeInfo\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getExchangeFeeInfo<any>();\n      console.log(response);\n      console.log(\n        response.raw_data[sdk.VipCatergory.ORDERBOOK_TRADING_FEES_STABLECOIN]\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getProtocolPortrait\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getProtocolPortrait();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getRecommendedMarkets\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getRecommendedMarkets();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getGasPrice\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getGasPrice();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getGasPriceRange\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getGasPriceRange();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMarketTrades\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMarketTrades<any>({\n        market: \"ETH-USDT\",\n      });\n      console.log(response.raw_data.trades);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getRelayerCurrentTime\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getRelayerCurrentTime();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getFiatPriceUSD\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getFiatPrice({\n        legal: \"USD\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getFiatPriceCNY\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getFiatPrice({\n        legal: \"CNY\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMarkets\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMarkets();\n      console.log(response);\n      console.log(response.pairs.LRC.tokenList);\n\n      console.log(\n        \"hasMarket LRC-ETH:\",\n        sdk.hasMarket(response.marketArr, \"LRC-ETH\")\n      );\n      console.log(\n        \"market 1:\",\n        sdk.getExistedMarket(response.marketArr, \"LRC\", \"ETH\")\n      );\n      console.log(\n        \"market 2:\",\n        sdk.getExistedMarket(response.marketArr, \"ETH\", \"LRC\")\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getDepth\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getDepth({\n        market: \"LRC-ETH\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getTicker\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getTicker({\n        market: \"LRC-ETH\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAllTickers\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getAllTickers();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMixDepth\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixDepth({\n        market: \"LRC-ETH\",\n      });\n      console.log(response);\n      console.log(response.depth.bids);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMixTicker\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixTicker({\n        market: [\"LRC-ETH\", \"ETH-USDC\", \"DAI-USDT\"].join(\",\"),\n      });\n      console.log(response.tickMap[\"DAI-USDT\"]);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getAllMixTickers\",\n    async () => {\n      const response: any = await LoopringAPI.exchangeAPI.getAllMixTickers();\n      console.log(response?.tickMap);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMixCandlestickAMM\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixCandlestick({\n        market: \"AMM-LRC-ETH\",\n        interval: sdk.TradingInterval.min15,\n        limit: 96,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/exchange/webSocket.md",
    "content": "#WebSocket Command\nDefinition: Loopring L2 websocket \n\n### Loopring L2 websocket topic type: \nWsTopicType\n- `account`\n- `orderbook`\n- `mixorder`\n- `mixtrade`\n- `ticker`\n- `candlestick`\n- `ammpool`\n\n## getWsKey (required by account related socket)\n```ts \nconst response = await LoopringAPI.wsAPI.getWsKey();\nconsole.log(response);\n```\n## getOrderBookArg  \n```ts\nconst arg1 = sdk.getMixOrderArg({ market: \"LRC-ETH\", level: 50 });\nconsole.log(arg1);\n\nconst arg2 = sdk.getOrderBookArg({\n  market: \"LRC-ETH\",\n  level: 50,\n  count: 40,\n  snapshot: false,\n});\nconsole.log(arg2);\n```"
  },
  {
    "path": "src/tests/demo/exchange/webSocket.test.ts",
    "content": "import * as sdk from \"../../../index\";\nimport { DEFAULT_TIMEOUT, LoopringAPI } from \"../../MockData\";\n\n/**\n * @define WsTopicType\n *   `account`,\n *   `order`,\n *   `orderbook`,\n *   `mixorder`,\n *   `trade`,\n *   `ticker`,\n *   `candlestick`,\n *   `ammpool`,\n *\n */\ndescribe(\"websocket\", function () {\n  it(\n    \"getWsKey\",\n    async () => {\n      const response = await LoopringAPI.wsAPI.getWsKey();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getOrderBookArg\",\n    async () => {\n      const arg1 = sdk.getMixOrderArg({ market: \"LRC-ETH\", level: 50 });\n      console.log(arg1);\n\n      const arg2 = sdk.getOrderBookArg({\n        market: \"LRC-ETH\",\n        level: 50,\n        count: 40,\n        snapshot: false,\n      });\n      console.log(arg2);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/transfer/transferERC20.md",
    "content": "# Transfer ERC20 \nDefinition: Send ERC20 tokens to other account on Loopring L2, \n> trade value should with decimals `sdk.toBig(value).times(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)`\n\n***\n## Step 1. get account Info\n    const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n    const LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo;\n\n```ts\nconst { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n\n```\n***\n## Step 2. get eddsaKey\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n***\n## Step 3. get apikey\n```ts\nconst { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst { userBalances } = await LoopringAPI.userAPI.getUserBalances(\n  { accountId: LOOPRING_EXPORTED_ACCOUNT.accountId, tokens: \"\" },\n  apiKey\n);\n```\n\n***\n## Step 4. get storageId\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n ```\n\n***\n## Step 5. get fee\n```ts\nconst fee = await LoopringAPI.userAPI.getOffchainFeeAmt({\n  accountId: accInfo.accountId,\n  requestType: sdk.OffchainFeeReqType.TRANSFER,\n}, apiKey);\nconsole.log(\"fee:\", fee);\n```\n***\n## Step 6. transfer\n```ts\nconst transferResult = await LoopringAPI.userAPI.submitInternalTransfer({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    payerAddr: accInfo.owner,\n    payerId: accInfo.accountId,\n    payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n    payeeId: LOOPRING_EXPORTED_ACCOUNT.accountId2,\n    storageId: storageId.offchainId,\n    token: {\n      tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n      volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n    },\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    /*\n     * when payPayeeUpdateAccount = ture, will help payee active account,\n     * maxFee from should:\n     * const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n     *  {\n     *     accountId: accInfo.accountId,\n     *     requestType: sdk.OffchainFeeReqType.TRANSFER_AND_UPDATE_ACCOUNT,\n     *   },\n     *   apiKey\n     * );\n     */\n    payPayeeUpdateAccount: false,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Trezor,\n  eddsaKey: eddsaKey.sk,\n  apiKey: apiKey,\n});\nconsole.log(\"transferResult:\", transferResult);\n```"
  },
  {
    "path": "src/tests/demo/transfer/transferERC20.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n  web3,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\nimport * as sign_tools from \"../../../api/sign/sign_tools\";\nimport { myLog } from \"../../../utils/log_tools\";\ndescribe(\"Transfer\", function () {\n  it(\n    \"submitInternalTransfer\",\n    async () => {\n      /*\n       * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n       * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n       */\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. get storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n\n      // Step 5. get fee\n      const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.TRANSFER,\n        },\n        apiKey\n      );\n      console.log(\"fee:\", fee);\n      const request = {\n        exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        payerAddr: accInfo.owner,\n        payerId: accInfo.accountId,\n        payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n        payeeId: LOOPRING_EXPORTED_ACCOUNT.accountId2,\n        storageId: storageId.offchainId,\n        token: {\n          tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n          volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n        },\n        maxFee: {\n          tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n          volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n        },\n        validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n        /*\n         * when payPayeeUpdateAccount = ture, will help payee active account,\n         * maxFee from should:\n         * const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n         *  {\n         *     accountId: accInfo.accountId,\n         *     requestType: sdk.OffchainFeeReqType.TRANSFER_AND_UPDATE_ACCOUNT,\n         *   },\n         *   apiKey\n         * );\n         */\n        payPayeeUpdateAccount: false,\n      };\n      const hash = sign_tools.get_EddsaSig_Transfer(request, \"\").hash;\n      myLog(\"hash\", hash);\n      // Step 6. transfer\n      const transferResult = await LoopringAPI.userAPI.submitInternalTransfer({\n        request,\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        eddsaKey: eddsaKey.sk,\n        apiKey: apiKey,\n      });\n      console.log(\"transferResult:\", transferResult);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/transfer/transferNFT.md",
    "content": "# Transfer NFT\nDefinition: Send NFT to other account on Loopring L2\n\n***\n## Step 1. get account Info\n```ts\nconst { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\nconst LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo;\nconst { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\n```\n\n***\n## Step 2. get eddsaKey\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n## Step 3. get apiKey\n```ts\nconst { apiKey } = await LoopringAPI.userAPI.getUserApiKey({\n  accountId: accInfo.accountId}, eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\nconst { userNFTBalances } = await LoopringAPI.userAPI.getUserNFTBalances(\n  { accountId: accInfo.accountId, limit: 20 },\n  apiKey\n);\n```\n \n***\n##Step 4. get storageId\n```ts  \nconst storageId = await LoopringAPI.userAPI.getNextStorageId({\n  accountId: accInfo.accountId,\n  sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n}, apiKey);\n```\n\n***\n## Step 5. get fee\n```ts\nconst transferResult = await LoopringAPI.userAPI.submitNFTInTransfer({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    fromAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    fromAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n    toAccountId: 0, // toAccountId is not required, input 0 as default\n    toAddress: LOOPRING_EXPORTED_ACCOUNT.address2,\n    token: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    storageId: storageId.offchainId,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    /*\n     * when payPayeeUpdateAccount = ture, will help payee active account,\n     * maxFee from:\n     * const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n     *  {\n     *     accountId: accInfo.accountId,\n     *     requestType: sdk.OffchainFeeReqType.NFT_TRANSFER_AND_UPDATE_ACCOUNT,\n     *   },\n     *   apiKey\n     * );\n     */\n    payPayeeUpdateAccount: false,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"fee:\", fee);\n```\n\n***\n## Step 6. Transfer NFT\n```ts\nconst transferResult = await LoopringAPI.userAPI.submitNFTInTransfer({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    fromAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    fromAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n    toAccountId: 0, // toAccountId is not required, input 0 as default\n    toAddress: LOOPRING_EXPORTED_ACCOUNT.address2,\n    token: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    storageId: storageId.offchainId,\n    validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.Unknown,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"transfer Result:\", transferResult);\n```"
  },
  {
    "path": "src/tests/demo/transfer/transferNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\ndescribe(\"TransferNFT\", function () {\n  it(\n    \"submitNFTInTransfer\",\n    async () => {\n      /*\n       * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n       * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n       */\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n\n      // Step 5. fee\n      const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_TRANSFER,\n          amount: \"0\",\n        },\n        apiKey\n      );\n      console.log(\"fee:\", fee);\n\n      const transferResult = await LoopringAPI.userAPI.submitNFTInTransfer({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          fromAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          fromAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n          toAccountId: 0, // toAccountId is not required, input 0 as default\n          toAddress: LOOPRING_EXPORTED_ACCOUNT.address2,\n          token: {\n            tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n            nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n            amount: \"1\",\n          },\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n            amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n          },\n          storageId: storageId.offchainId,\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n          /*\n           * when payPayeeUpdateAccount = ture, will help payee active account,\n           * maxFee from:\n           * const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n           *  {\n           *     accountId: accInfo.accountId,\n           *     requestType: sdk.OffchainFeeReqType.NFT_TRANSFER_AND_UPDATE_ACCOUNT,\n           *   },\n           *   apiKey\n           * );\n           */\n          payPayeeUpdateAccount: false,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown,\n        eddsaKey: eddsaKey.sk,\n        apiKey,\n      });\n      console.log(\"transfer Result:\", transferResult);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/withdraw/withdrawERC20.md",
    "content": "# Withdraw ERC20\n\nDefinition: Loopring L2 withdraw ERC20 to Ethereum L1,\n> trade value should with decimals `sdk.toBig(value).times(\"1e\" + TOKEN_INFO.tokenMap.LRC.decimals)`\n\n***\n\n## Step 1. getAccount\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n```\n\n##Step 2.  eddsaKey\n\n```ts\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n```\n\n***\n\n## Step 3. apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey({\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n\n```\n\n***\n\n## Step 4. storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId({\n    accountId: accInfo.accountId,\n    sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n\n```\n\n***\n\n## Step 5. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getOffchainFeeAmt({\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainFeeReqType.OFFCHAIN_WITHDRAWAL,\n    tokenSymbol: TOKEN_INFO.tokenMap[\"LRC\"].symbol,\n  },\n  apiKey\n);\nconsole.log(\"fee:\", fee);\n\n```\n\n***\n\n## Step 6. withdraw\n\n```ts\nconst response = await LoopringAPI.userAPI.submitOffchainWithdraw({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    counterFactualInfo: undefined,\n    fastWithdrawalMode: false,\n    hashApproved: \"\",\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    minGas: 0,\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address,\n    storageId: 0,\n    token: {\n      tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n      volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n    },\n    validUntil: 0,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.MetaMask,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"response:\", response);\n```"
  },
  {
    "path": "src/tests/demo/withdraw/withdrawERC20.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\ndescribe(\"Withdraw\", function () {\n  beforeEach(async () => {\n    jest.setTimeout(DEFAULT_TIMEOUT * 3);\n  }, DEFAULT_TIMEOUT);\n\n  it(\n    \"submitWithdraw\",\n    async () => {\n      /*\n       * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n       * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n       */\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n\n      // Step 5. fee\n      const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.OFFCHAIN_WITHDRAWAL,\n          tokenSymbol: TOKEN_INFO.tokenMap[\"LRC\"].symbol,\n        },\n        apiKey\n      );\n      console.log(\"fee:\", fee);\n\n      // Step 6. withdraw\n      const response = await LoopringAPI.userAPI.submitOffchainWithdraw({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          counterFactualInfo: undefined,\n          fastWithdrawalMode: false,\n          hashApproved: \"\",\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n            volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n          },\n          minGas: 0,\n          owner: LOOPRING_EXPORTED_ACCOUNT.address,\n          to: LOOPRING_EXPORTED_ACCOUNT.address,\n          storageId: storageId.offchainId,\n          token: {\n            tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n            volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n          },\n          validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.Unknown, //sdk.ConnectorNames.MetaMask UT only support perosonal sign, no V4\n        eddsaKey: eddsaKey.sk,\n        apiKey,\n      });\n      console.log(\"response:\", response);\n    },\n    DEFAULT_TIMEOUT * 3\n  );\n});\n"
  },
  {
    "path": "src/tests/demo/withdraw/withdrawNFT.md",
    "content": "# Withdraw NFT\n\nDefinition:  Loopring L2 withdraw NFT to Ethereum L1\n\n***\n\n## Step 1. getAccount\n\n```ts\nconst {accInfo} = await LoopringAPI.exchangeAPI.getAccount({\n  owner: LOOPRING_EXPORTED_ACCOUNT.address,\n});\nconsole.log(\"accInfo:\", accInfo);\n```\n\n***\n\n## Step 2. eddsaKey\n\n```ts\n\nconst eddsaKey = await signatureKeyPairMock(accInfo);\nconsole.log(\"eddsaKey:\", eddsaKey.sk);\n\n```\n\n***\n\n## Step 3. apiKey\n\n```ts\nconst {apiKey} = await LoopringAPI.userAPI.getUserApiKey(\n  {\n    accountId: accInfo.accountId,\n  },\n  eddsaKey.sk\n);\nconsole.log(\"apiKey:\", apiKey);\n```\n\n***\n\n## Step 4. storageId\n\n```ts\nconst storageId = await LoopringAPI.userAPI.getNextStorageId(\n  {\n    accountId: accInfo.accountId,\n    sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  },\n  apiKey\n);\nconsole.log(\"storageId:\", storageId);\n\n//Step 5. getUserNFTBalances\nconst {userNFTBalances} = await LoopringAPI.userAPI.getUserNFTBalances(\n  {accountId: LOOPRING_EXPORTED_ACCOUNT.accountId},\n  apiKey\n);\nconst tokenInfo = userNFTBalances.find(\n  (item) =>\n    item.tokenAddress?.toLowerCase() ===\n    LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress.toLowerCase() &&\n    item.nftId &&\n    web3.utils.hexToNumberString(item.nftId) ===\n    LOOPRING_EXPORTED_ACCOUNT.nftTokenId.toString()\n);\n```\n\n***\n\n## Step 5. fee\n\n```ts\nconst fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n  {\n    accountId: accInfo.accountId,\n    requestType: sdk.OffchainNFTFeeReqType.NFT_WITHDRAWAL,\n    tokenAddress:  LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n    deployInWithdraw:\n      tokenInfo?.deploymentStatus === DEPLOYMENT_STATUS.NOT_DEPLOYED, // when token is not deploy the fee is diff\n  },\n  apiKey\n);\nconsole.log(\"fee:\", fee);\n```\n\n***\n\n## Step 6. withdraw\n\n```ts\nconst response = await LoopringAPI.userAPI.submitNFTWithdraw({\n  request: {\n    exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n    accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n    counterFactualInfo: undefined,\n    hashApproved: \"\",\n    maxFee: {\n      tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n    },\n    minGas: 0,\n    owner: LOOPRING_EXPORTED_ACCOUNT.address,\n    to: LOOPRING_EXPORTED_ACCOUNT.address,\n    storageId: 0,\n    token: {\n      tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n      nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n      amount: \"1\",\n    },\n    validUntil: 0,\n  },\n  web3,\n  chainId: sdk.ChainId.GOERLI,\n  walletType: sdk.ConnectorNames.MetaMask,\n  eddsaKey: eddsaKey.sk,\n  apiKey,\n});\nconsole.log(\"response:\", response);\n```"
  },
  {
    "path": "src/tests/demo/withdraw/withdrawNFT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\nimport { DEPLOYMENT_STATUS } from \"../../../index\";\n\ndescribe(\"WithdrawNFT\", function () {\n  it(\n    \"submitNFTWithdraw\",\n    async () => {\n      /*\n       * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n       * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n       */\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n\n      //Step 5. getUserNFTBalances\n      const { userNFTBalances } = await LoopringAPI.userAPI.getUserNFTBalances(\n        { accountId: LOOPRING_EXPORTED_ACCOUNT.accountId },\n        apiKey\n      );\n      const tokenInfo = userNFTBalances.find(\n        (item) =>\n          item.tokenAddress?.toLowerCase() ===\n            LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress.toLowerCase() &&\n          item.nftId &&\n          web3.utils.hexToNumberString(item.nftId) ===\n            LOOPRING_EXPORTED_ACCOUNT.nftTokenId.toString()\n      );\n\n      // Step 6. fee\n      const fee = await LoopringAPI.userAPI.getNFTOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainNFTFeeReqType.NFT_WITHDRAWAL,\n          tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n          deployInWithdraw:\n            tokenInfo?.deploymentStatus === DEPLOYMENT_STATUS.NOT_DEPLOYED, // when token is not deploy the fee is diff\n        },\n        apiKey\n      );\n      console.log(\"fee:\", fee);\n\n      // Step 6. withdraw\n      const response = await LoopringAPI.userAPI.submitNFTWithdraw({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          counterFactualInfo: undefined,\n          hashApproved: \"\",\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n            amount: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n          },\n          minGas: 0,\n          owner: LOOPRING_EXPORTED_ACCOUNT.address,\n          to: LOOPRING_EXPORTED_ACCOUNT.address,\n          storageId: 0,\n          token: {\n            tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n            nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n            amount: \"1\",\n          },\n          validUntil: 0,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.MetaMask,\n        eddsaKey: eddsaKey.sk,\n        apiKey,\n      });\n      console.log(\"response:\", response);\n    },\n    DEFAULT_TIMEOUT * 3\n  );\n});\n"
  },
  {
    "path": "src/tests/formatter.test.ts",
    "content": "import { IsMobile, LoopringErrorCode } from \"../defs\";\n// import fetch from \"node-fetch\";\n\nimport {\n  addHexPrefix,\n  clearHexPrefix,\n  convertPublicKey,\n  convertPublicKey2,\n  formatAddress,\n  formatEddsaKey,\n  formatKey,\n  fromGWEI,\n  getDisplaySymbol,\n  numberWithCommas,\n  padLeftEven,\n  PublicKey,\n  sleep,\n  toBig,\n  toBN,\n  toBuffer,\n  toFixed,\n  toGWEI,\n  toHex,\n  toNumber,\n  zeroPad,\n} from \"..\";\n\nimport * as fm from \"../utils/formatter\";\nimport { BigNumber } from \"bignumber.js\";\nimport { LOOPRING_EXPORTED_ACCOUNT, web3 } from \"./MockData\";\nconst NUMBER = 40244024;\nconst BUFFER = Buffer.from(\"40244024\", \"utf8\");\nconst BIG_NUMBER = new BigNumber(123.4567);\nconst TIMEOUT = 30000;\n\ndescribe(\"formatter test\", function () {\n  beforeEach(async () => {\n    return;\n  }, TIMEOUT);\n\n  it(\n    \"enum_test\",\n    async () => {\n      console.log(LoopringErrorCode[100000]);\n      console.log(LoopringErrorCode[200000]);\n    },\n    TIMEOUT\n  );\n  // it(\n  //   \"META_JSON\",\n  //   async () => {\n  //     const ipfs = \"QmayP595tA9L7D9XYhY6FzkixXWDPFZ3Y8Q3c9TUq3hqns\";\n  //     const value = await fetch(`https://localhost:8080/ipfs/${ipfs}`).then(\n  //       (response) => response.json()\n  //     );\n  //     console.log(`ipfsCid0ToNftID: meta: `, ipfs, value);\n  //   },\n  //   DEFAULT_TIMEOUT + 20000\n  // );\n\n  it(\n    \"formatter1\",\n    async () => {\n      const px = fm.formatEddsaKey(\n        \"4966334643155205117396087046889763297010019574817548934733242435404623801022\"\n      );\n      const py = fm.formatEddsaKey(\n        \"12336121800785994591019936445923899190012791232373302800087997800255990054103\"\n      );\n\n      const pk: PublicKey = {\n        x: px,\n        y: py,\n      };\n\n      console.log(px);\n      console.log(\"px.length:\", px.length);\n\n      console.log(py);\n      console.log(\"py.length:\", py.length);\n\n      console.log(convertPublicKey(pk));\n    },\n    TIMEOUT\n  );\n\n  it(\n    \"formatter2\",\n    async () => {\n      const px = fm.formatEddsaKey(\n        fm.toHex(\n          fm.toBig(\n            \"4966334643155205117396087046889763297010019574817548934733242435404623801022\"\n          )\n        )\n      );\n      const py = fm.formatEddsaKey(\n        fm.toHex(\n          fm.toBig(\n            \"12336121800785994591019936445923899190012791232373302800087997800255990054103\"\n          )\n        )\n      );\n\n      const pk: PublicKey = {\n        x: px,\n        y: py,\n      };\n\n      console.log(px);\n      console.log(\"px.length:\", px.length);\n\n      console.log(py);\n      console.log(\"py.length:\", py.length);\n\n      const bn = convertPublicKey(pk);\n\n      console.log(bn);\n      console.log(bn.toString(10));\n      console.log(fm.addHexPrefix(bn.toString(16)));\n    },\n    TIMEOUT\n  );\n\n  it(\n    \"formatter3\",\n    async () => {\n      const px =\n        \"4966334643155205117396087046889763297010019574817548934733242435404623801022\";\n      const py =\n        \"12336121800785994591019936445923899190012791232373302800087997800255990054103\";\n\n      const pk: PublicKey = {\n        x: px,\n        y: py,\n      };\n\n      console.log(px);\n      console.log(\"px.length:\", px.length);\n\n      console.log(py);\n      console.log(\"py.length:\", py.length);\n\n      const bn = convertPublicKey2(pk);\n\n      console.log(bn);\n      console.log(bn.toString(10));\n      console.log(fm.addHexPrefix(bn.toString(16)));\n    },\n    TIMEOUT\n  );\n  it(\n    \"formatter4\",\n    async () => {\n      const publicKey = {\n        x: \"0x01f9390f9ea86a9b98b180647f28454e2466bf14b4e28533161429f50a8fdea8\",\n        y: \"0x006b5e578ef145c7339f56a54443b31d77b33b469748d029bdbeabc4928df7\",\n      };\n\n      const publicKeyNo0 = {\n        x: \"0x1f9390f9ea86a9b98b180647f28454e2466bf14b4e28533161429f50a8fdea8\",\n        y: \"0x06b5e578ef145c7339f56a54443b31d77b33b469748d029bdbeabc4928df7\",\n      };\n      expect(fm.toBig(publicKey.x).eq(fm.toBig(publicKeyNo0.x))).toBe(true);\n      expect(fm.toBig(publicKey.y).eq(fm.toBig(publicKeyNo0.y))).toBe(true);\n    },\n    TIMEOUT\n  );\n\n  it(\"test toBuffer\", async () => {\n    console.log(toBuffer(\"420\")); // todo add assertion\n    console.log(toBuffer(BUFFER)); // todo add assertion\n  });\n\n  it(\"test zeroPad\", async () => {\n    console.log(zeroPad(\"420\", 0)); // todo add assertion\n  });\n\n  it(\"test toHex\", async () => {\n    expect(toHex(LOOPRING_EXPORTED_ACCOUNT.nftId)).toBe(\n      \"0xa0ce8990402955e559799af24ea765b14ffecc32dfa1cce2dadaf20016b074e6\"\n    );\n  });\n\n  it(\"test toNumber\", async () => {\n    expect(toNumber(\"69\")).toBe(69);\n    expect(toNumber(420)).toBe(420);\n    expect(toNumber(\"12345.6789\")).toBe(12345.6789);\n    expect(web3.utils.hexToNumberString(LOOPRING_EXPORTED_ACCOUNT.nftId)).toBe(\n      \"72734975696905790806441216757602251046556131108796431318619325611208980067558\"\n    );\n    expect(toNumber(BIG_NUMBER)).toBe(123.4567);\n  });\n\n  it(\"test padLeftEven\", async () => {\n    expect(padLeftEven(LOOPRING_EXPORTED_ACCOUNT.address)).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.address\n    );\n    expect(padLeftEven(LOOPRING_EXPORTED_ACCOUNT.testNotOx.slice(0, -1))).toBe(\n      \"0\" + LOOPRING_EXPORTED_ACCOUNT.testNotOx.slice(0, -1)\n    );\n  });\n\n  it(\"test getDisplaySymbol\", async () => {\n    expect(getDisplaySymbol(\"USD\")).toBe(\"$\");\n    expect(getDisplaySymbol(\"CNY\")).toBe(\"￥\");\n    expect(getDisplaySymbol(\"EUR\")).toBe(\"\");\n  });\n\n  it(\"test toBig\", async () => {\n    expect(toBig(\"0x\" + BUFFER)).toEqual(new BigNumber(\"0x\" + BUFFER));\n  });\n  it(\"test toBig \", async () => {\n    console.log(\n      toBig(\"426702000000000000000\")\n        .div(\"1e\" + 18)\n        .toString()\n    );\n  });\n\n  it(\"test toBN\", async () => {\n    // expect(toBN(\"0x\" + BIG_NUMBER)).toEqual(BIG_NUMBER);\n    expect(toBN(2).toString()).toEqual(\"2\");\n  });\n\n  it(\"test fromGWEI\", async () => {\n    expect(fromGWEI(420)).toEqual(new BigNumber(4.2e11));\n    expect(fromGWEI(420.0)).toEqual(new BigNumber(4.2e11));\n    expect(fromGWEI(\"420\")).toEqual(new BigNumber(4.2e11));\n  });\n\n  it(\"test toGWEI\", async () => {\n    expect(toGWEI(420)).toEqual(new BigNumber(4.2e-7));\n    expect(toGWEI(420.0)).toEqual(new BigNumber(4.2e-7));\n    expect(toGWEI(\"420\")).toEqual(new BigNumber(4.2e-7));\n  });\n\n  it(\"test formatKey\", async () => {\n    expect(formatKey(\"0x\" + BUFFER)).toBe(NUMBER.toString());\n    expect(formatKey(LOOPRING_EXPORTED_ACCOUNT.address.toLowerCase())).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.testNotOx\n    );\n    expect(formatKey(LOOPRING_EXPORTED_ACCOUNT.testNotOx)).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.testNotOx\n    );\n  });\n\n  // Missing test input data for Uint8Array\n  it(\"test formatAddress\", async () => {\n    expect(\n      formatAddress(LOOPRING_EXPORTED_ACCOUNT.testNotOx).toLowerCase()\n    ).toBe(LOOPRING_EXPORTED_ACCOUNT.address);\n    expect(formatAddress(LOOPRING_EXPORTED_ACCOUNT.address).toLowerCase()).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.address\n    );\n    expect(formatAddress(\"0x\" + BUFFER)).toBe(\"0x\" + BUFFER);\n  });\n\n  it(\"test addHexPrefix\", async () => {\n    expect(addHexPrefix(LOOPRING_EXPORTED_ACCOUNT.address)).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.address\n    );\n    expect(addHexPrefix(LOOPRING_EXPORTED_ACCOUNT.testNotOx)).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.address\n    );\n    expect(() => addHexPrefix(420)).toThrowError(\"Unsupported type\");\n  });\n\n  it(\"test clearHexPrefix\", async () => {\n    expect(clearHexPrefix(LOOPRING_EXPORTED_ACCOUNT.address)).toBe(\n      LOOPRING_EXPORTED_ACCOUNT.testNotOx\n    );\n    expect(() => clearHexPrefix(420)).toThrowError(\"Unsupported type\");\n  });\n\n  it(\"test toFixed\", async () => {\n    expect(toFixed(420, 0, 0)).toBe(\"420\");\n    expect(toFixed(420, 1, 0)).toBe(\"420.0\");\n    expect(toFixed(420, 2, 0)).toBe(\"420.00\");\n    expect(toFixed(421.421, 2, 1)).toBe(\"421.43\");\n    expect(toFixed(421.421, 1, 1)).toBe(\"421.5\");\n    expect(toFixed(421.421, 1, 0)).toBe(\"421.4\");\n\n    expect(toFixed(BIG_NUMBER, 1, 0)).toBe(\"123.4\");\n    expect(toFixed(BIG_NUMBER, 1, 1)).toBe(\"123.5\");\n    expect(toFixed(BIG_NUMBER, 2, 1)).toBe(\"123.46\");\n    expect(() => toFixed(\"wow\", 2, 1)).toThrowError(\"Unsupported type\");\n  });\n\n  it(\"test formatEddsaKey\", async () => {\n    expect(\n      formatEddsaKey(\n        \"027a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\"\n      )\n    ).toBe(\n      \"0x027a5b716c7309a30703ede3f1a218cdec857e424a31543f8a658e7d2208db33\"\n    );\n    expect(formatEddsaKey(\"1231dsab2\")).toBe(\n      \"0x00000000000000000000000000000000000000000000000000000001231dsab2\"\n    );\n  });\n\n  it(\"test numberWithCommas\", async () => {\n    expect(numberWithCommas(420)).toBe(\"420\");\n    expect(numberWithCommas(1000)).toBe(\"1,000\");\n    expect(numberWithCommas(\"10000\")).toBe(\"10,000\");\n    expect(numberWithCommas(\"1,000,000\")).toBe(\"1,000,000\");\n    expect(numberWithCommas(\"10.000.000\")).toBe(\"-\");\n    expect(numberWithCommas(null)).toBe(null);\n  });\n  it(\"sleep_test\", async () => {\n    console.log(new Date().getTime());\n    await sleep(5000);\n    console.log(new Date().getTime());\n  });\n\n  it(\"stringify_test\", async () => {\n    const demo: any = {\n      a: 5,\n      c: { d: 5, e: \"k\" },\n      b: \"ss\",\n    };\n\n    console.log(JSON.stringify(demo));\n\n    const keys = Object.keys(demo).sort();\n\n    console.log(keys);\n    console.log(JSON.stringify(demo, keys));\n\n    const demo2: any = {};\n\n    keys.forEach((item, index) => {\n      demo2[item] = demo[item];\n    });\n\n    console.log(demo2);\n\n    console.log(JSON.stringify(demo2));\n\n    const ordered = Object.keys(demo)\n      .sort()\n      .reduce((obj: any, key) => {\n        obj[key] = demo[key];\n        return obj;\n      }, {});\n\n    console.log(JSON.stringify(ordered));\n  });\n  it(\"isMobile\", () => {\n    console.log(\"isMobile\", IsMobile.any());\n  });\n  it(\"cid\", () => {\n    // // eslint-disable-next-line @typescript-eslint/no-var-requires\n    // const _CID = require(\"cids\");\n    // const _1cid = new _CID(\n    //   \"bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi\"\n    // );\n    // const _1hashHex = Buffer.from(_1cid.multihash.slice(2)).toString(\"hex\");\n    // const _1hashBN = new BN(_1hashHex.padStart(64, \"0\"), 16)\n    //   .toString(\"hex\")\n    //   .padStart(64, \"0\");\n    //\n    // const _cid = CID.parse(\n    //   \"bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi\"\n    // );\n    // const hashHex = _cid.toString(base16).padStart(64, \"0\");\n    // console.log(\n    //   \"no slice\",\n    //   new BN(Buffer.from(_1cid.multihash).toString(\"hex\"), 16)\n    //     .toString(\"hex\")\n    //     .padStart(64, \"0\"),\n    //   \"currentBuffer\",\n    //   _1hashBN,\n    //   \"hashHex\",\n    //   hashHex\n    // );\n    // // const CID = require(\"cids\");\n    // const hashBN = new BN(\n    //   \"0x01701220c3c4733ec8affd06cf9e9ff50ffc6bcd2ec85a6170004bb709669c31de94391a\"\n    //     // \"0xca4f3647b8a11f64ec3dbb64ab756f623044e9e066bb2a79aa4264a3eb265240\"\n    //     .replace(\"0x\", \"\"),\n    //   16\n    // );\n    // const hex = hashBN.toString(\"hex\").padStart(64, \"0\");\n    // // const buf = Buffer.from(\"1220\" + hex, \"hex\");\n    // console.log(\n    //   \"hashHex\",\n    //   hex\n    //   // _hashBN\n    // );\n    // const buf = Buffer.from(\"1220\" + hex, \"hex\");\n    // const cid = CID.parse(\"f\" + hashBN, base16).toString();\n    // myLog(cid);\n  });\n});\n\nexport default {};\n"
  },
  {
    "path": "src/tests/unitTest/account/account.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  signatureKeyPairMock,\n  TOKEN_INFO,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\n/*\n * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n */\ndescribe(\"AccountDemo\", function () {\n  it(\n    \"getAccount\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\"getWalletType\", async () => {\n    const [\n      { walletType: CFWalletType },\n      { walletType: EOAWalletType },\n      { walletType: ContractWalletType },\n    ] = await Promise.all([\n      LoopringAPI.walletAPI.getWalletType({\n        wallet: LOOPRING_EXPORTED_ACCOUNT.addressCF,\n      }),\n      LoopringAPI.walletAPI.getWalletType({\n        wallet: LOOPRING_EXPORTED_ACCOUNT.address,\n      }),\n      LoopringAPI.walletAPI.getWalletType({\n        wallet: LOOPRING_EXPORTED_ACCOUNT.addressContractWallet,\n      }),\n    ]);\n    console.log(\n      \"CFWalletType, EOAWalletType, ContractWalletType\",\n      CFWalletType,\n      EOAWalletType,\n      ContractWalletType\n    );\n  });\n\n  it(\n    \"getUserApiKey\",\n    async () => {\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n    },\n    DEFAULT_TIMEOUT * 10\n  );\n\n  it(\n    \"getEthNonce\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getEthNonce({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"getEthNonce:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"approveMax_LRC\",\n    async () => {\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n      const response = await sdk.approveMax(\n        web3,\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        TOKEN_INFO.tokenMap.LRC.address,\n        LOOPRING_EXPORTED_ACCOUNT.depositAddress,\n        LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n        LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n        sdk.ChainId.GOERLI,\n        nonce,\n        true\n      );\n\n      console.log(`nonce: ${nonce} approveMax: ${JSON.stringify(response)}`);\n    },\n    DEFAULT_TIMEOUT * 2\n  );\n\n  it(\n    \"approveZero_LRC\",\n    async () => {\n      const nonce = await sdk.getNonce(web3, LOOPRING_EXPORTED_ACCOUNT.address);\n      const response = await sdk.approveZero(\n        web3,\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        TOKEN_INFO.tokenMap.LRC.address,\n        LOOPRING_EXPORTED_ACCOUNT.depositAddress,\n        LOOPRING_EXPORTED_ACCOUNT.gasPrice,\n        LOOPRING_EXPORTED_ACCOUNT.gasLimit,\n        sdk.ChainId.GOERLI,\n        // @ts-ignor\n        nonce,\n        true\n      );\n\n      console.log(`nonce: ${nonce} approveZero: ${response}`);\n    },\n    DEFAULT_TIMEOUT * 2\n  );\n\n  it(\n    \"Layer1_ETH_Balance\",\n    async () => {\n      const { ethBalance } = await LoopringAPI.exchangeAPI.getEthBalances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(`Layer1 ethBalance: ${ethBalance}`);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"Layer1_ERC20_Balance\",\n    async () => {\n      const { tokenBalances } = await LoopringAPI.exchangeAPI.getTokenBalances({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n        token: [TOKEN_INFO.tokenMap.LRC.address],\n      });\n      console.log(\n        `Layer1 ERC20 Balance LRC: ${tokenBalances.get(\n          TOKEN_INFO.tokenMap.LRC.address as unknown as sdk.TokenAddress\n        )}`\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\"Layer1_getNFTBalance\", async () => {\n    const response = await LoopringAPI.nftAPI.getNFTBalance({\n      web3,\n      account: LOOPRING_EXPORTED_ACCOUNT.address,\n      tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n      nftId: LOOPRING_EXPORTED_ACCOUNT.nftId,\n      nftType: sdk.NFTType.ERC1155,\n    });\n    console.log(response);\n  });\n\n  it(\n    \"Layer2_getUserBalances\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. getUserBalances\n      const { userBalances } = await LoopringAPI.userAPI.getUserBalances(\n        { accountId: LOOPRING_EXPORTED_ACCOUNT.accountId, tokens: \"\" },\n        apiKey\n      );\n\n      console.log(`Layer2 ERC20 Balance: ${userBalances}`);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"Layer2_getUserNFTBalances\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. getUserNFTBalances\n      const { userNFTBalances } = await LoopringAPI.userAPI.getUserNFTBalances(\n        { accountId: accInfo.accountId, limit: 20 },\n        apiKey\n      );\n      console.log(`Layer2 NFT Balance: ${userNFTBalances}`);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getCounterFactualInfo\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getCounterFactualInfo({\n        accountId: LOOPRING_EXPORTED_ACCOUNT.accountIdCF,\n      });\n      console.log(\"getCounterFactualInfo\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/unitTest/account/sign_tools.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  signatureKeyPairMock,\n  testTypedData,\n  web3,\n} from '../../MockData'\nimport * as sdk from '../../../index'\nimport {\n  AccountInfo,\n  getEdDSASig,\n  getNftData,\n  NFTOrderRequestV3,\n  NFTTradeRequestV3,\n  NFTType,\n  SubmitOrderRequestV3,\n} from '../../../index'\nimport { myLog } from '../../../utils/log_tools'\nimport { performance } from 'perf_hooks'\n\nlet mockData:\n  | {\n      accInfo: AccountInfo\n      apiKey: string\n      eddsaKey: any\n    }\n  | undefined = undefined\ndescribe('signature', function () {\n  beforeEach(async () => {\n    // Step 1. getAccount\n    const accInfo = (\n      await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n    ).accInfo\n    const eddsaKey = await signatureKeyPairMock(accInfo)\n\n    // Step 3. apiKey\n    const apiKey = (\n      await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk,\n      )\n    ).apiKey\n\n    mockData = {\n      apiKey,\n      accInfo,\n      eddsaKey,\n    }\n  }, DEFAULT_TIMEOUT * 3)\n  it(\n    'generateKeyPair',\n    async () => {\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      })\n      const result = await signatureKeyPairMock(accInfo)\n      console.log(result.sk)\n    },\n    DEFAULT_TIMEOUT,\n  )\n  /**\n   * test case is not allow brock by Mock provider\n   */\n  // it(\n  //   \"getEcDSASig:eth_signTypedData_v4\",\n  //   async () => {\n  //     // test case is not allow brock by Mock provider\n  //     const result = await sdk.getEcDSASig(\n  //       web3,\n  //       testTypedData,\n  //       LOOPRING_EXPORTED_ACCOUNT.address,\n  //       sdk.GetEcDSASigType.HasDataStruct,\n  //       sdk.ChainId.GOERLI,\n  //       LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //       \"\",\n  //       sdk.ConnectorNames.Unknown\n  //     );\n  //     console.log(\n  //       \"getEcDSASig:eth_signTypedData_v4\",\n  //       result,\n  //       \"ecdsaSig+sdk.SigSuffix.Suffix02\",\n  //       result.ecdsaSig + sdk.SigSuffix.Suffix02\n  //     );\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n\n  it('getEcDSASig:WithoutDataStruct(personalSign)', async () => {\n    const result = await sdk.getEcDSASig(\n      web3,\n      testTypedData,\n      LOOPRING_EXPORTED_ACCOUNT.address,\n      sdk.GetEcDSASigType.WithoutDataStruct,\n      sdk.ChainId.GOERLI,\n      LOOPRING_EXPORTED_ACCOUNT.accountId,\n      '',\n      sdk.ConnectorNames.Unknown,\n    )\n    console.log('getEcDSASig:WithoutDataStruct(personalSign)', result)\n  })\n\n  it('genSigWithPadding', async () => {\n    // const sign = genSigWithPadding(\n    //   LOOPRING_EXPORTED_ACCOUNT.eddsaKey.sk,\n    //   '4802789675835142786409394599364863978702692874349325354528260268536567293213',\n    // )\n    // console.log(sign)\n  })\n  it('getEdDSASig', async () => {\n    if (mockData) {\n      const sign = await sdk.getEdDSASig(\n        'GET',\n        'https://uat2.loopring.io',\n        '/api/v3/apiKey/',\n        {\n          accountId: '10010',\n        },\n        mockData.eddsaKey.sk,\n      )\n      console.log(sign)\n    }\n  })\n  it('getEdDSASig_100', async () => {\n    if (mockData) {\n      performance.now()\n      for (let i = 100; i > 0; i--) {\n        const sign = await sdk.getEdDSASig(\n          'GET',\n          'https://uat2.loopring.io',\n          '/api/v3/apiKey/',\n          {\n            accountId: '10010',\n          },\n          mockData.eddsaKey.sk,\n        )\n        console.log(sign)\n      }\n      performance.now()\n    }\n  })\n  /**\n   * test case is not allow brock by Mock provider\n   */\n  // it(\"personalSign Contract\", async () => {\n  //   await sdk.getEcDSASig(\n  //     web3,\n  //     testTypedData,\n  //     LOOPRING_EXPORTED_ACCOUNT.address,\n  //     sdk.GetEcDSASigType.Contract,\n  //     sdk.ChainId.GOERLI,\n  //     LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //     \"\",\n  //     sdk.ConnectorNames.Unknown\n  //   );\n  // });\n  it('NFTAction Trade Hash', async () => {\n    try {\n      const makerOrder: NFTOrderRequestV3 = {\n        exchange: '0xD1221BA705B653d9Ea22569c911Bddf68264fAF4',\n        accountId: 10979,\n        storageId: 36,\n        sellToken: {\n          tokenId: 2,\n          nftData: '',\n          amount: '118117838',\n        },\n        buyToken: {\n          tokenId: 32769,\n          nftData: '0x26b32b508180c293e1a6581fd8a1ebff4734966578a008247c9f0bf9cdb5e492',\n          amount: '2',\n        },\n        allOrNone: false,\n        fillAmountBOrS: true,\n        validUntil: 1680332114,\n        maxFeeBips: 1000,\n      }\n      makerOrder.eddsaSignature =\n        '0x2553b338ce18a9bc4f51412ccf2c37ba04538ef26e4897fdcf244d0bcf71fe270a0ccebe65cc4a13a3c3e6f84c3de919f7d81434df0a50b8f583e4c7b350b2a203c01b8472e3474c6b2225de41da6ae67a781986d43063ce8008d5978cab3c1f'\n\n      const takerOrder: NFTOrderRequestV3 = {\n        exchange: '0xD1221BA705B653d9Ea22569c911Bddf68264fAF4',\n        accountId: 10092,\n        storageId: 2,\n        sellToken: {\n          tokenId: 32769,\n          nftData: '0x26b32b508180c293e1a6581fd8a1ebff4734966578a008247c9f0bf9cdb5e492',\n          amount: '1',\n        },\n        buyToken: {\n          tokenId: 2,\n          nftData: '',\n          amount: '59000000',\n        },\n        allOrNone: false,\n        fillAmountBOrS: false,\n        validUntil: 1680332114,\n        maxFeeBips: 1000,\n      }\n\n      takerOrder.eddsaSignature =\n        '0x28e1fef32e0e7d119d5f2a078bf9f0ad677f72eed18ef35d98326a389ebb5e900a92fe81cfd4fc0a2758dba3bbf55f79c073ac539490b5fc6e16a8046df946dd060025f14fc3d92ef72163639e4ec8cef629e335343c44a291aed5a6e8d646bf'\n\n      const tradeRequest: NFTTradeRequestV3 = {\n        maker: makerOrder,\n        makerFeeBips: 99,\n        taker: takerOrder,\n        takerFeeBips: 99,\n      }\n\n      const hash = await sdk.getNftTradeHash(tradeRequest)\n\n      // result should be 0x244b36f43e462167942bb336e180df74dcca5726742cfab9ae1b70b6dfe5f4a\n      console.log('NFT Trade hash is 0x' + hash)\n    } catch (err) {\n      console.log(err)\n    }\n  })\n  it('ERC20 Order Hash', async () => {\n    try {\n      const orderRequest: SubmitOrderRequestV3 = {\n        exchange: '0x2e76EBd1c7c0C8e7c2B875b6d505a260C525d25e',\n        accountId: 11040,\n        storageId: 10,\n        sellToken: {\n          tokenId: 1,\n          volume: '986000000000000000000',\n        },\n        buyToken: {\n          tokenId: 0,\n          volume: '74861064000000000',\n        },\n        maxFeeBips: 60,\n        validUntil: 1653995768,\n        fillAmountBOrS: false,\n        allOrNone: false,\n        eddsaSignature: '',\n      }\n\n      const hash = await sdk.getOrderHash(orderRequest)\n\n      // result should be : 0x15b965bbf0e01697939a5cd8be6e631f6cf4a3009ee9fb8631d193e0d5218b92\n      console.log('ERC20 order hash is 0x' + hash)\n    } catch (err) {\n      console.log(err)\n    }\n  })\n  it('getNftData', async () => {\n    const cid = 'QmNuqdeWUJ9iEiw5qZfJ2pJ9onqAS45ZffvV8JQSUzp7DQ'\n    const nftID = LoopringAPI.nftAPI.ipfsCid0ToNftID(cid)\n    const mintRequest = {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      minterId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      minterAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n      toAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      toAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n      nftType: NFTType.ERC1155,\n      tokenAddress: LOOPRING_EXPORTED_ACCOUNT.nftTokenAddress,\n      nftId: nftID, //nftId.toString(16),\n      amount: '1',\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      storageId: 9,\n      maxFee: {\n        tokenId: 1,\n        amount: '9400000000000000000',\n      },\n      royaltyPercentage: 5,\n      forceToMint: true, // suggest use as false, for here is just for run test\n    }\n    myLog('cid', cid, 'nftID', nftID, 'result is:')\n    getNftData({ ...mintRequest, nftId: nftID })\n    myLog('nftID', '0x1', 'result is:')\n    getNftData({ ...mintRequest, nftId: '0x1' })\n  })\n})\n\nexport default {}\n"
  },
  {
    "path": "src/tests/unitTest/appWallet/wallet.test.ts",
    "content": "import {\n  TOKEN_INFO,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  DEFAULT_TIMEOUT,\n  web3,\n} from '../../MockData'\nimport * as sdk from '../../../index'\nimport * as ethUtil from 'ethereumjs-util'\nimport { myLog } from '../../../utils/log_tools'\n\ndescribe('WalletApi', function () {\n  it(\n    'getUserAssets',\n    async () => {\n      const request: sdk.GetUserAssetsRequest = {\n        wallet: LOOPRING_EXPORTED_ACCOUNT.addressContractWallet,\n        offset: 10,\n        limit: 10,\n      }\n\n      const response = await LoopringAPI.walletAPI.getUserAssets(request)\n      console.log(response)\n    },\n    DEFAULT_TIMEOUT,\n  )\n\n  it(\n    'getTokenPrices',\n    async () => {\n      const response = await LoopringAPI.walletAPI.getTokenPrices({\n        token: TOKEN_INFO.tokenMap.LRC.address,\n      })\n      console.log(response)\n    },\n    DEFAULT_TIMEOUT,\n  )\n\n  it(\n    'getLatestTokenPrices',\n    async () => {\n      const response = await LoopringAPI.walletAPI.getLatestTokenPrices()\n      console.log(response)\n    },\n    DEFAULT_TIMEOUT,\n  )\n\n  it(\n    'getLatestTokenPrices_cny',\n    async () => {\n      const response = await LoopringAPI.walletAPI.getLatestTokenPrices({\n        currency: sdk.Currency.cny,\n      })\n      console.log(response)\n    },\n    DEFAULT_TIMEOUT,\n  )\n  // it(\n  //   'signHebaoApproveWithDataStructureForContract V1',\n  //   async () => {\n  //     const request: any = {\n  //       approveRecordId: 2325,\n  //       txAwareHash: '0x7de6db4d1eb828442404daa7a70ee10a5c7d69c3f9685a8a52dc069fd53575bb',\n  //       securityNumber: '403265',\n  //       signer: '0xff7d59d9316eba168837e3ef924bcdfd64b237d8',\n  //       signature: '',\n  //     }\n  //     const guardian: any = {\n  //       ens: 'testcmx1.loopring.eth',\n  //       address: '0xd4bd7c71b6d4a09217ccc713f740d6ed8f4ea0cd',\n  //       type: 'recovery',\n  //       id: 2325,\n  //       messageHash: '0x7de6db4d1eb828442404daa7a70ee10a5c7d69c3f9685a8a52dc069fd53575bb',\n  //       businessDataJson: {\n  //         value: {\n  //           value: {\n  //             wallet: '0xd4bd7c71b6d4a09217ccc713f740d6ed8f4ea0cd',\n  //             newOwner: '0x696c291239931ac87f5053bcb8e621a181fb3f08',\n  //             oldOwnerIsLocked: false,\n  //             newGuardians: [],\n  //           },\n  //         },\n  //       },\n  //       signedRequest: {\n  //         signers: '',\n  //         signatures: '',\n  //         validUntil: '1663646243',\n  //         wallet: '0xd4bd7c71b6d4a09217ccc713f740d6ed8f4ea0cd',\n  //       },\n  //       approveId: 2325,\n  //       wallet: '0xd4bd7c71b6d4a09217ccc713f740d6ed8f4ea0cd',\n  //       guardian: '0xff7d59d9316eba168837e3ef924bcdfd64b237d8',\n  //       metaTxType: 16,\n  //       txAwareHash: '0x7de6db4d1eb828442404daa7a70ee10a5c7d69c3f9685a8a52dc069fd53575bb',\n  //       createAt: 1658462243419,\n  //     }\n  //     // (\"0x46d4e3d3db8fcb401e5d4020b958755a3419b84b\");\n  //     // const walletModule = {\n  //     //   moduleName: \"FORWARDER_MODULE\",\n  //     //   moduleAddress: \"0x21e3143ef5677c465c2aba68ef7137f063933c7c\",\n  //     // };\n  //     const forwarderModuleAddress = '0x46d4e3d3db8fcb401e5d4020b958755a3419b84b' //walletModule.moduleAddress;\n  //     const newOwner = guardian.businessDataJson?.value.value.newOwner\n  //     const response = await LoopringAPI.walletAPI.signHebaoApproveWithDataStructureForContract(\n  //       web3,\n  //       request.signer,\n  //       guardian,\n  //       LOOPRING_EXPORTED_ACCOUNT.chainId,\n  //       newOwner,\n  //       undefined,\n  //       undefined,\n  //       forwarderModuleAddress,\n  //     )\n  //     // const hash\n  //     //   = ;\n  //\n  //     console.log(response)\n  //   },\n  //   DEFAULT_TIMEOUT,\n  // )\n\n  // it(\n  //   'signHebaoApproveWithDataStructureForContract V2 guardians=[]',\n  //   async () => {\n  //     const contractType = {\n  //       network: 'ETHEREUM',\n  //       contractVersion: 'V2_0_0',\n  //       masterCopy: '0x4b16684de50ebcc60fd54b0a5fd1ccfdc940bb27',\n  //       walletFactory: '0x8c3d4e1728f77abcd220323260da4a9306fb6433',\n  //       ens: '',\n  //       walletStatus: 5,\n  //       queueStatus: 3,\n  //       walletType: 0,\n  //       isCounterFactual: false,\n  //     }\n  //     const request: any = {\n  //       approveRecordId: 2323,\n  //       txAwareHash: '0xaeaf14dc427a0fbfa3e60887fd46b7263907d415ff8e392a4429279322fb97c2',\n  //       securityNumber: '514038',\n  //       signer: '0xff7d59d9316eba168837e3ef924bcdfd64b237d8',\n  //       signature: '',\n  //     }\n  //     const guardian: any = {\n  //       ens: '',\n  //       address: '0x98ee79ce59f84b16f394cbf89413a256c94e2c1c',\n  //       type: 'recovery',\n  //       id: 2323,\n  //       messageHash: '0xaeaf14dc427a0fbfa3e60887fd46b7263907d415ff8e392a4429279322fb97c2',\n  //       businessDataJson: {\n  //         value: {\n  //           value: {\n  //             wallet: '0x98ee79ce59f84b16f394cbf89413a256c94e2c1c',\n  //             newOwner: '0xa37f4dddc2389f26d17dc2a4045e905b657a00d8',\n  //             oldOwnerIsLocked: true,\n  //             request: {\n  //               signers: [\n  //                 '0xfcc50ae865cdcbd846f2f2ce5099d31f99bc6db1',\n  //                 '0xff7d59d9316eba168837e3ef924bcdfd64b237d8',\n  //               ],\n  //               signatures: [\n  //                 '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',\n  //                 '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',\n  //               ],\n  //               validUntil: '1663645929',\n  //               wallet: '0x98ee79ce59f84b16f394cbf89413a256c94e2c1c',\n  //             },\n  //             newGuardians: [],\n  //           },\n  //         },\n  //       },\n  //       signedRequest: {\n  //         signers: '',\n  //         signatures: '',\n  //         validUntil: '1663645929',\n  //         wallet: '0x98ee79ce59f84b16f394cbf89413a256c94e2c1c',\n  //       },\n  //       approveId: 2323,\n  //       wallet: '0x98ee79ce59f84b16f394cbf89413a256c94e2c1c',\n  //       guardian: '0xff7d59d9316eba168837e3ef924bcdfd64b237d8',\n  //       metaTxType: 16,\n  //       txAwareHash: '0xaeaf14dc427a0fbfa3e60887fd46b7263907d415ff8e392a4429279322fb97c2',\n  //       createAt: 1658461929755,\n  //     }\n  //     const newOwner = guardian.businessDataJson.value.value?.newOwner\n  //     // const guardiansBs = LoopringAPI.walletAPI.encodeAddressesPacked(\n  //     //   guardian.businessDataJson.value.value.newGuardians\n  //     // );\n  //     const newGuardians = ethUtil.keccak(\n  //       web3.eth.abi.encodeParameter(\n  //         'address[]',\n  //         guardian.businessDataJson.value.value.newGuardians,\n  //       ),\n  //     )\n  //     //   ethUtil.keccak(\n  //     //\n  //     // );\n  //     myLog('newGuardians', newGuardians)\n  //     // const guardiansHash = ethUtil.keccak(guardiansBs);\n  //     const response = await LoopringAPI.walletAPI.getA(\n  //       LOOPRING_EXPORTED_ACCOUNT.chainId,\n  //       contractType.masterCopy,\n  //       guardian.signedRequest.wallet,\n  //       guardian.signedRequest.validUntil,\n  //       newOwner,\n  //       newGuardians,\n  //     )\n  //     //0x7a5b52a82fc0814bb3400e1075ea5aad34ca210497ce5c7e581eea6ee0f75650\n  //     console.log(response, guardian.messageHash)\n  //   },\n  //   DEFAULT_TIMEOUT,\n  // )\n})\n"
  },
  {
    "path": "src/tests/unitTest/erc20Trade/amm.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\n\ndescribe(\"AmmpoolAPI test\", function () {\n  it(\n    \"getAmmPoolConf\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolConf();\n      console.log(response.ammpools);\n      console.log(response.pairs);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolUserRewards\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolUserRewards<\n        any[]\n      >({\n        owner: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      });\n      console.log(\"getAmmPoolUserRewards:\", response);\n      console.log(\n        \"getAmmPoolUserRewards feeRewards:\",\n        response.ammUserRewardMap\n      );\n      console.log(\n        \"getAmmPoolUserRewards feeRewards,extraRewards,currentRewards:\",\n        response.raw_data[0].feeRewards,\n        response.raw_data[0].extraRewards,\n        response.raw_data[0].currentRewards\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolUserRewards-LRC-ETH\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolUserRewards<\n        any[]\n      >({\n        owner: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        ammPoolMarkets: \"AMM-LRC-ETH\",\n      });\n      console.log(\"getAmmPoolUserRewards:\", response);\n      console.log(\n        \"getAmmPoolUserRewards feeRewards:\",\n        response.ammUserRewardMap\n      );\n      console.log(\n        \"getAmmPoolUserRewards feeRewards,extraRewards,currentRewards:\",\n        response.raw_data[0].feeRewards,\n        response.raw_data[0].extraRewards,\n        response.raw_data[0].currentRewards\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    'getAmmPoolUserRewards-LRC-ETH_ETH-USDT\"',\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolUserRewards<\n        any[]\n      >({\n        owner: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        ammPoolMarkets: \"AMM-LRC-ETH,AMM-ETH-USDT\",\n      });\n      console.log(\"getAmmPoolUserRewards:\", response);\n      console.log(\n        \"getAmmPoolUserRewards feeRewards:\",\n        response.ammUserRewardMap\n      );\n      console.log(\n        \"getAmmPoolUserRewards feeRewards,extraRewards,currentRewards:\",\n        response.raw_data[0].feeRewards,\n        response.raw_data[0].extraRewards,\n        response.raw_data[0].currentRewards\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolGameRank\",\n    async () => {\n      const response: any = await LoopringAPI.ammpoolAPI.getAmmPoolGameRank({\n        ammPoolMarket: \"UNI-ETH\",\n      });\n      console.log(\"getAmmPoolGameRank:\", response.raw_data);\n      console.log(\"totalRewards:\", response.totalRewards);\n      console.log(\"userRankList 1:\", response.userRankList[0]);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmAssetHistory\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmAssetHistory({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(\"getAmmAssetHistory dataSeries:\", response);\n      // console.log('getAmmAssetHistory:', response.raw_data.data[0].tokens)\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolGameUserRank\",\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. getAmmPoolGameUserRank\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolGameUserRank(\n        { owner: LOOPRING_EXPORTED_ACCOUNT.address, ammPoolMarket: \"LRC-ETH\" },\n        apiKey\n      );\n      console.log(\"getAmmPoolGameUserRank:\", response.raw_data);\n      console.log(\"userRank:\", response.userRank);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolActivityRules\",\n    async () => {\n      const {\n        activityInProgressRules,\n        activityDateMap,\n        groupByRuleType,\n        groupByActivityStatus,\n        groupByRuleTypeAndStatus,\n        raw_data,\n      } = await LoopringAPI.ammpoolAPI.getAmmPoolActivityRules();\n      console.log(\"activityInProgressRules\", activityInProgressRules);\n      console.log(\"activityDateMap\", activityDateMap);\n      console.log(\"groupByRuleType\", groupByRuleType);\n      console.log(\"groupByActivityStatus\", groupByActivityStatus);\n      console.log(\n        \"groupByRuleTypeAndStatus\",\n        groupByRuleTypeAndStatus,\n        JSON.stringify(groupByRuleTypeAndStatus)\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolStats\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolStats();\n      console.log(\"ammPoolStats:\", response.ammPoolStats);\n      console.log(\"rewards:\", response.ammPoolStats[\"AMM-BCDT-ETH\"]?.rewards);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolSnapshot\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolSnapshot<any>({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response);\n      console.log(response.raw_data.pooled);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getLiquidityMining\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      const response = await LoopringAPI.ammpoolAPI.getLiquidityMining(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          market: \"LRC-ETH\",\n          size: 120,\n        },\n        apiKey\n      );\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getLiquidityMiningUserHistory\",\n    async () => {\n      const response =\n        await LoopringAPI.ammpoolAPI.getLiquidityMiningUserHistory({\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          start: 0,\n          end: new Date().getTime(),\n        });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  // it(\n  //   \"getLiquidityMiningUserHistory_No_data\",\n  //   async () => {\n  //     const request: GetLiquidityMiningUserHistoryRequest = {\n  //       accountId: 10084,\n  //       start: 0,\n  //       end: new Date().getTime(),\n  //     };\n  //     const response =\n  //       await LoopringAPI.ammpoolAPI.getLiquidityMiningUserHistory(request);\n  //     console.log(response);\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n\n  it(\n    \"getAmmPoolSnapshot\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolSnapshot<any>({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response);\n      console.log(response.raw_data.pooled);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolBalances\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolBalances();\n      console.log(response.ammpoolsbalances);\n      console.log(response.ammpoolsbalances[\"AMM-LRC-ETH\"].poolAddress);\n      console.log(response.ammpoolsbalances[\"AMM-LRC-ETH\"].pooled);\n      console.log(response.ammpoolsbalances[\"AMM-LRC-ETH\"].lp);\n      console.log(response.ammpoolsbalances[\"AMM-LRC-ETH\"].pooledMap);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolTrades\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolTrades<any>({\n        ammPoolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response);\n      console.log(response.raw_data.trades[0]);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAmmPoolTxs\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolTxs({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(\n        \"getAmmPoolTxs\",\n        response.transactions[0]?.lpToken,\n        response.transactions[0]?.poolTokens\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getUserAmmPoolTxs\",\n    async () => {\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. getUserAmmPoolTxs\n      const response = await LoopringAPI.ammpoolAPI.getUserAmmPoolTxs<any>(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        },\n        apiKey\n      );\n      console.log(response);\n      console.log(response.raw_data.transactions[0]);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/unitTest/erc20Trade/amm_calc.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\nimport {\n  get_EddsaSig_ExitAmmPool,\n  getAmmExitEcdsaTypedData,\n} from \"../../../index\";\n\ndescribe(\"amm_calc\", function () {\n  it(\n    \"amm_calc_test\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolSnapshot<any>({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response.raw_data.pooled);\n\n      const covertVal = sdk.toBig(\"1e+20\").toFixed(0, 0);\n\n      const coinA_TV = response.ammPoolSnapshot?.pooled[0];\n      const coinB_TV = response.ammPoolSnapshot?.pooled[1];\n\n      const output = sdk.ammPoolCalc(\n        covertVal,\n        true,\n        coinA_TV as sdk.TokenVolumeV3,\n        coinB_TV as sdk.TokenVolumeV3\n      );\n\n      console.log(\n        \"covertVal:\",\n        covertVal,\n        \"output:\",\n        output,\n        \"ratio:\",\n        output.ratio.toString()\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"make_join_request\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolSnapshot<any>({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response.raw_data.pooled);\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      // Step 4. fees\n      const { fees } = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          requestType: sdk.OffchainFeeReqType.AMM_JOIN,\n          tokenSymbol: \"ETH\",\n        },\n        apiKey\n      );\n\n      console.log(\"---fees:\", fees);\n\n      const { tokensMap, idIndex } = await LoopringAPI.exchangeAPI.getTokens();\n\n      const { request: res } = sdk.makeJoinAmmPoolRequest(\n        \"100\",\n        true,\n        \"0.001\",\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        fees,\n        response.ammPoolSnapshot as sdk.AmmPoolSnapshot,\n        tokensMap,\n        idIndex,\n        0,\n        0\n      );\n\n      console.log(\"res:\", res);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"make_exit_request\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolSnapshot<any>({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response.raw_data.pooled);\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      // Step 4. fees\n      const { fees } = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          requestType: sdk.OffchainFeeReqType.AMM_JOIN,\n          tokenSymbol: \"ETH\",\n        },\n        apiKey\n      );\n\n      console.log(\"---fees:\", fees);\n\n      const { tokensMap, idIndex } = await LoopringAPI.exchangeAPI.getTokens();\n\n      const { request: res } = sdk.makeExitAmmPoolRequest2(\n        \"100\",\n        \"0.001\",\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        fees,\n        response.ammPoolSnapshot as sdk.AmmPoolSnapshot,\n        tokensMap,\n        idIndex,\n        0\n      );\n\n      console.log(\"res:\", res);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getEddsaSigExitAmmPool\",\n    async () => {\n      const response = await LoopringAPI.ammpoolAPI.getAmmPoolSnapshot<any>({\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n      });\n      console.log(response.raw_data.pooled);\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      // Step 4. fees\n      const { fees } = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          requestType: sdk.OffchainFeeReqType.AMM_JOIN,\n          tokenSymbol: \"ETH\",\n        },\n        apiKey\n      );\n\n      console.log(\"---fees:\", fees);\n\n      const { tokensMap, idIndex } = await LoopringAPI.exchangeAPI.getTokens();\n\n      const { request } = sdk.makeExitAmmPoolRequest2(\n        \"100\",\n        \"0.001\",\n        LOOPRING_EXPORTED_ACCOUNT.address,\n        fees,\n        response.ammPoolSnapshot as sdk.AmmPoolSnapshot,\n        tokensMap,\n        idIndex,\n        0\n      );\n      const patch: sdk.AmmPoolRequestPatch = {\n        chainId: LOOPRING_EXPORTED_ACCOUNT.chainId,\n        ammName: \"LRCETH-Pool\",\n        poolAddress: TOKEN_INFO.tokenMap[\"LP-LRC-ETH\"].address,\n        eddsaKey: eddsaKey.sk,\n      };\n\n      const res = {\n        ...request,\n        validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n      };\n\n      get_EddsaSig_ExitAmmPool(res, patch);\n      get_EddsaSig_ExitAmmPool(\n        {\n          ...res,\n          domainSeparator:\n            \"0x68561fa99d9c0532544589587b389976733591df662e3ca157dfdd30db83e966\",\n        },\n        patch\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n\nexport default {};\n"
  },
  {
    "path": "src/tests/unitTest/erc20Trade/defi.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\nimport { calcDefi, DefiAction } from \"../../../index\";\n\ndescribe(\"DefiAPI test\", function () {\n  it(\n    \"getDefiMarkets\",\n    async () => {\n      const response = await LoopringAPI.defiAPI.getDefiMarkets({defiType: undefined});\n      console.log(\n        \"getDefiMarkets\",\n        response.marketArr,\n        response.markets,\n        response.pairs\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getDefiToken\",\n    async () => {\n      const response = await LoopringAPI.defiAPI.getDefiToken();\n      console.log(\n        \"getDefiToken:\",\n        response.tokensMap,\n        response.idIndex,\n        response.addressIndex\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getDefiTransaction\",\n    async () => {\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n        },\n        LOOPRING_EXPORTED_ACCOUNT.privateKey\n      );\n      const response = await LoopringAPI.defiAPI.getDefiTransaction(\n        {\n          limit: 20, offset: 0,\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId\n        },\n        apiKey\n      );\n      console.log(\"getDefiTransaction:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"orderDefi\",\n    async () => {\n      // Step 1. get account info\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. get apikey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      const sellSymbol = \"ETH\",\n        buySymbol = \"WSTETH\",\n        sellValue = \"0.00005\",\n        isJoin = true,\n        isInputSell = true;\n      const testMarket = \"WSTETH-ETH\";\n      const {markets} = await LoopringAPI.defiAPI.getDefiMarkets({defiType: undefined});\n      const {tokensMap} = await LoopringAPI.defiAPI.getDefiToken();\n      const marketInfo = markets[ testMarket ];\n      const buyTokenBalanceVol = marketInfo.baseVolume;\n\n      const {fees} = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: isJoin\n            ? sdk.OffchainFeeReqType.DEFI_JOIN\n            : sdk.OffchainFeeReqType.DEFI_EXIT,\n          market: testMarket,\n        },\n        apiKey\n      );\n\n      const calcVol = calcDefi({\n        isJoin,\n        isInputSell,\n        sellAmount: sellValue,\n        feeVol: fees[buySymbol].fee,\n        marketInfo,\n        tokenSell: TOKEN_INFO.tokenMap[sellSymbol],\n        tokenBuy: tokensMap[buySymbol],\n        buyTokenBalanceVol,\n      });\n\n      console.log(\n        \"calcVol\",\n        calcVol,\n        calcVol.miniSellVol,\n        calcVol.maxSellVol,\n        calcVol.maxFeeBips\n      );\n\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap[sellSymbol].tokenId,\n        },\n        apiKey\n      );\n      const request = {\n        exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n        storageId: storageId.orderId,\n        accountId: accInfo.accountId,\n        sellToken: {\n          tokenId: TOKEN_INFO.tokenMap[sellSymbol].tokenId,\n          volume: calcVol.sellVol,\n        },\n        buyToken: {\n          tokenId: tokensMap[buySymbol].tokenId,\n          volume: calcVol.buyVol,\n        },\n        action: DefiAction.Deposit,\n        validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n        fee: fees[buySymbol].fee,\n        maxFeeBips: calcVol.maxFeeBips,\n        type: marketInfo.type,\n        fillAmountBOrS: false,\n      };\n      // @output calcVol UI use to validation data\n\n      const response = await LoopringAPI.defiAPI.orderDefi(\n        request,\n        eddsaKey.sk,\n        apiKey\n      );\n      console.log(\"orderDefi:\", response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/unitTest/exchange/exchange.test.ts",
    "content": "import { DEFAULT_TIMEOUT, LoopringAPI } from \"../../MockData\";\nimport * as sdk from \"../../../index\";\ndescribe(\"ExchangeAPI test\", function () {\n  it(\n    \"getExchangeInfo\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getExchangeInfo();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getWithdrawalAgents\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getWithdrawalAgents({\n        tokenId: 1,\n        amount: \"10000000000\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getCandlestick\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getCandlestick({\n        market: \"LRC-ETH\",\n        interval: sdk.TradingInterval.min15,\n        limit: 96,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAccountServices\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getAccountServices({});\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getExchangeFeeInfo\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getExchangeFeeInfo<any>();\n      console.log(response);\n      console.log(\n        response.raw_data[sdk.VipCatergory.ORDERBOOK_TRADING_FEES_STABLECOIN]\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getProtocolPortrait\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getProtocolPortrait();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getRecommendedMarkets\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getRecommendedMarkets();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getGasPrice\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getGasPrice();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getGasPriceRange\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getGasPriceRange();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMarketTrades\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMarketTrades<any>({\n        market: \"ETH-USDT\",\n      });\n      console.log(response.raw_data.trades);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getRelayerCurrentTime\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getRelayerCurrentTime();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getFiatPriceUSD\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getFiatPrice({\n        legal: \"USD\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getFiatPriceCNY\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getFiatPrice({\n        legal: \"CNY\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMarkets\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMarkets();\n      console.log(response);\n      console.log(response.pairs.LRC.tokenList);\n\n      console.log(\n        \"hasMarket LRC-ETH:\",\n        sdk.hasMarket(response.marketArr, \"LRC-ETH\")\n      );\n      console.log(\n        \"market 1:\",\n        sdk.getExistedMarket(response.marketArr, \"LRC\", \"ETH\")\n      );\n      console.log(\n        \"market 2:\",\n        sdk.getExistedMarket(response.marketArr, \"ETH\", \"LRC\")\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getTokens\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getTokens<any>();\n      console.log(response);\n      console.log(response.raw_data[0]);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getDepth\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getDepth({\n        market: \"LRC-ETH\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getTicker\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getTicker({\n        market: \"LRC-ETH\",\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getMixMarkets\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixMarkets();\n      console.log(response);\n      console.log(response.pairs.LRC.tokenList);\n      console.log(\n        \"hasMarket LRC-ETH:\",\n        sdk.hasMarket(response.marketArr, \"LRC-ETH\")\n      );\n      console.log(\n        \"market 1:\",\n        sdk.getExistedMarket(response.marketArr, \"LRC\", \"ETH\")\n      );\n      console.log(\n        \"market 2:\",\n        sdk.getExistedMarket(response.marketArr, \"ETH\", \"LRC\")\n      );\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getMixDepth\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixDepth({\n        market: \"LRC-ETH\",\n      });\n      console.log(response);\n      console.log(response.depth.bids);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMixTicker\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixTicker({\n        market: [\"LRC-ETH\", \"ETH-USDC\", \"DAI-USDT\"].join(\",\"),\n      });\n      console.log(response.tickMap[\"DAI-USDT\"]);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getAllMixTickers\",\n    async () => {\n      const response: any = await LoopringAPI.exchangeAPI.getAllMixTickers();\n      console.log(response?.tickMap);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAllTickers\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getAllTickers();\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getMarketTrades_err\",\n    async () => {\n      const req: sdk.GetMarketTradesRequest = {\n        market: \"LRC-ETH_Not_Existed\",\n      };\n      const response = await LoopringAPI.exchangeAPI.getMarketTrades<any>(req);\n      console.log(response);\n      console.log(response.raw_data.trades);\n    },\n    DEFAULT_TIMEOUT\n  );\n  it(\n    \"getAllMixTickers0\",\n    async () => {\n      const response: any = await LoopringAPI.exchangeAPI.getAllMixTickers();\n      console.log(response?.tickMap);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getAllMixTickers1\",\n    async () => {\n      const response: any = await LoopringAPI.exchangeAPI.getAllMixTickers(\n        \"AMM-LRC-ETH\"\n      );\n      console.log(response.tickMap);\n    },\n    DEFAULT_TIMEOUT\n  );\n\n  it(\n    \"getMixCandlestickAMM\",\n    async () => {\n      const response = await LoopringAPI.exchangeAPI.getMixCandlestick({\n        market: \"AMM-LRC-ETH\",\n        interval: sdk.TradingInterval.min15,\n        limit: 96,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n});\n"
  },
  {
    "path": "src/tests/unitTest/transfer/transferUT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n} from \"../../MockData\";\n\ndescribe(\"Transfer UT\", function () {\n  it(\n    \"getAccountWhitelisted\",\n    async () => {\n      const response = LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.whitelistedAddress,\n      });\n      console.log(response);\n    },\n    DEFAULT_TIMEOUT\n  );\n  // it(\n  //   \"get_EddsaSig_NFT_Transfer\",\n  //   async () => {\n  //     const request: sdk.OriginNFTTransferRequestV3 = {\n  //       exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n  //       fromAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //       fromAddress: LOOPRING_EXPORTED_ACCOUNT.address,\n  //       toAccountId: LOOPRING_EXPORTED_ACCOUNT.accountId2,\n  //       toAddress: LOOPRING_EXPORTED_ACCOUNT.address2,\n  //       token: {\n  //         tokenId: LOOPRING_EXPORTED_ACCOUNT.nftTokenId,\n  //         nftData: LOOPRING_EXPORTED_ACCOUNT.nftData,\n  //         amount: \"1\",\n  //       },\n  //       maxFee: {\n  //         tokenId: 2,\n  //         amount: \"311000000000000000000\",\n  //       },\n  //       storageId: 9,\n  //       validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  //       // memo: '',\n  //     };\n  //     const result = sdk.get_EddsaSig_NFT_Transfer(request, \"\");\n  //     console.log(`resultHash:`, result);\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n  // it(\n  //   \"getUserApiKeyWhitelisted\",\n  //   async () => {\n  //     // Step 1. get account info\n  //     const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  //       owner: LOOPRING_EXPORTED_ACCOUNT.whitelistedAddress,\n  //     });\n  //     console.log(\"accInfo:\", accInfo);\n  //\n  //     // Step 2. eddsaKey\n  //     const eddsaKey = await signatureKeyPairMock(accInfo);\n  //     console.log(\"eddsaKey:\", eddsaKey.sk);\n  //\n  //     // Step 3. get apikey\n  //     const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n  //       {\n  //         accountId: accInfo.accountId,\n  //       },\n  //       eddsaKey.sk\n  //     );\n  //     console.log(\"apiKey:\", apiKey);\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n  // it(\n  //   \"whitelistedAccTransfer\",\n  //   async () => {\n  //     // Step 1. get account info\n  //     const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  //       owner: LOOPRING_EXPORTED_ACCOUNT.whitelistedAddress,\n  //     });\n  //     console.log(\"accInfo:\", accInfo);\n  //\n  //     // Step 2. eddsaKey\n  //     // const eddsaKey = await signatureKeyPairMock(accInfo);\n  //     // console.log(\"eddsaKey:\", eddsaKey.sk);\n  //\n  //     // Step 3. get apikey\n  //     const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n  //       {\n  //         accountId: accInfo.accountId,\n  //       },\n  //       LOOPRING_EXPORTED_ACCOUNT.whitelistedEddkey\n  //     );\n  //     console.log(\"apiKey:\", apiKey);\n  //\n  //     // Step 4. get storageId\n  //     const storageId = await LoopringAPI.userAPI.getNextStorageId(\n  //       {\n  //         accountId: accInfo.accountId,\n  //         sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  //       },\n  //       apiKey\n  //     );\n  //\n  //     // Step 5. get fee\n  //     const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n  //       {\n  //         accountId: accInfo.accountId,\n  //         requestType: sdk.OffchainFeeReqType.TRANSFER,\n  //       },\n  //       apiKey\n  //     );\n  //     console.log(\"fee:\", fee);\n  //\n  //     // Step 6. transfer\n  //     const response =\n  //       await LoopringAPI.whitelistedUserAPI.submitInternalTransfer(\n  //         {\n  //           exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress, //exchangeInfo.exchangeAddress,\n  //           payerAddr: LOOPRING_EXPORTED_ACCOUNT.whitelistedAddress,\n  //           payerId: accInfo.accountId,\n  //           payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n  //           payeeId: 0,\n  //           storageId: storageId.offchainId,\n  //           token: {\n  //             tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n  //             volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n  //           },\n  //           maxFee: {\n  //             tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n  //             volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n  //           },\n  //           validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n  //         },\n  //         LOOPRING_EXPORTED_ACCOUNT.whitelistedEddkey,\n  //         apiKey\n  //       );\n  //\n  //     console.log(response);\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n});\n"
  },
  {
    "path": "src/tests/unitTest/withdraw/forceWithdrawls.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  signatureKeyPairMock,\n  TOKEN_INFO,\n  web3,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\nit(\n  \"submitForceWithdrawals\",\n  async () => {\n    // Step 1. getAccount\n    const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n      owner: LOOPRING_EXPORTED_ACCOUNT.address,\n    });\n    console.log(\"accInfo:\", accInfo);\n\n    // Step 2. eddsaKey\n    const eddsaKey = await signatureKeyPairMock(accInfo);\n    console.log(\"eddsaKey:\", eddsaKey.sk);\n\n    // Step 3. apiKey\n    const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n      {\n        accountId: accInfo.accountId,\n      },\n      eddsaKey.sk\n    );\n    console.log(\"apiKey:\", apiKey);\n\n    // Step 4. fee\n    const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n      {\n        accountId: accInfo.accountId,\n        requestType: sdk.OffchainFeeReqType.FORCE_WITHDRAWAL,\n        amount: \"0\",\n      },\n      apiKey\n    );\n    console.log(fee);\n\n    // Step 5. storageId\n    const storageId = await LoopringAPI.userAPI.getNextStorageId(\n      {\n        accountId: accInfo.accountId,\n        sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId, // same as Step 7. transfer->token->tokenId\n      },\n      apiKey\n    );\n\n    // Step 6. broker\n    const { broker } = await LoopringAPI.exchangeAPI.getAvailableBroker({\n      type: 1,\n    });\n\n    // Step 7. Build transfer & Deploy\n    const transfer = {\n      exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n      payerAddr: LOOPRING_EXPORTED_ACCOUNT.address,\n      payerId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n      payeeAddr: broker,\n      // payeeAddr: LOOPRING_EXPORTED_ACCOUNT.address2,\n      storageId: storageId.offchainId,\n      token: {\n        tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n        volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n      },\n      validUntil: LOOPRING_EXPORTED_ACCOUNT.validUntil,\n    };\n\n    const response = await LoopringAPI.userAPI.submitForceWithdrawals({\n      request: {\n        transfer,\n        withdrawAddress: \"0x7dF81E6683029011bBfefb5D57A1A364C3819110\", //test for withdraw\n        requesterAddress: accInfo.owner,\n        tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n      },\n      web3,\n      chainId: sdk.ChainId.GOERLI,\n      walletType: sdk.ConnectorNames.Unknown,\n      eddsaKey: eddsaKey.sk,\n      apiKey: apiKey,\n    });\n\n    console.log(response);\n  },\n  DEFAULT_TIMEOUT\n);\n"
  },
  {
    "path": "src/tests/unitTest/withdraw/withdrawUT.test.ts",
    "content": "import {\n  DEFAULT_TIMEOUT,\n  LOOPRING_EXPORTED_ACCOUNT,\n  LoopringAPI,\n  web3,\n  TOKEN_INFO,\n  signatureKeyPairMock,\n} from \"../../MockData\";\nimport * as sdk from \"../../../index\";\n\ndescribe(\"Withdraw NFTAction test\", function () {\n  // it(\n  //   \"get_EddsaSig_Withdraw\",\n  //   async () => {\n  //     const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n  //       owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  //     });\n  //     if (!accInfo) {\n  //       return;\n  //     }\n  //     /*\n  //      * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n  //      */\n  //     const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n  //\n  //     const request: sdk.OffChainWithdrawalRequestV3 = {\n  //       exchange: exchangeInfo.exchangeAddress,\n  //       accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n  //       counterFactualInfo: undefined,\n  //       fastWithdrawalMode: false,\n  //       hashApproved: \"\",\n  //       maxFee: {\n  //         tokenId: 1,\n  //         volume: \"100000000000000000000\",\n  //       },\n  //       minGas: 0,\n  //       owner: LOOPRING_EXPORTED_ACCOUNT.address,\n  //       to: LOOPRING_EXPORTED_ACCOUNT.address,\n  //       storageId: 0,\n  //       token: {\n  //         tokenId: 1,\n  //         volume: \"100000000000000000000\",\n  //       },\n  //       validUntil: 0,\n  //     };\n  //\n  //     const result = sdk.get_EddsaSig_OffChainWithdraw(request, \"\");\n  //     console.log(`resultHash:`, result);\n  //   },\n  //   DEFAULT_TIMEOUT\n  // );\n\n  it(\n    \"forceWithdraw\",\n    async () => {\n      /*\n       * @replace LOOPRING_EXPORTED_ACCOUNT.exchangeAddress =  exchangeInfo.exchangeAddress\n       * const { exchangeInfo } = await LoopringAPI.exchangeAPI.getExchangeInfo();\n       */\n      // Step 1. getAccount\n      const { accInfo } = await LoopringAPI.exchangeAPI.getAccount({\n        owner: LOOPRING_EXPORTED_ACCOUNT.address,\n      });\n      console.log(\"accInfo:\", accInfo);\n\n      // Step 2. eddsaKey\n      const eddsaKey = await signatureKeyPairMock(accInfo);\n      console.log(\"eddsaKey:\", eddsaKey.sk);\n\n      // Step 3. apiKey\n      const { apiKey } = await LoopringAPI.userAPI.getUserApiKey(\n        {\n          accountId: accInfo.accountId,\n        },\n        eddsaKey.sk\n      );\n      console.log(\"apiKey:\", apiKey);\n\n      // Step 4. storageId\n      const storageId = await LoopringAPI.userAPI.getNextStorageId(\n        {\n          accountId: accInfo.accountId,\n          sellTokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n        },\n        apiKey\n      );\n      console.log(\"storageId:\", storageId);\n\n      // Step 5. fee\n      const fee = await LoopringAPI.userAPI.getOffchainFeeAmt(\n        {\n          accountId: accInfo.accountId,\n          requestType: sdk.OffchainFeeReqType.FAST_OFFCHAIN_WITHDRAWAL,\n          tokenSymbol: TOKEN_INFO.tokenMap.LRC.symbol,\n          amount: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n        },\n        apiKey\n      );\n      console.log(\"fee:\", fee);\n\n      // Step 6. withdraw\n      const response = await LoopringAPI.userAPI.submitOffchainWithdraw({\n        request: {\n          exchange: LOOPRING_EXPORTED_ACCOUNT.exchangeAddress,\n          accountId: LOOPRING_EXPORTED_ACCOUNT.accountId,\n          counterFactualInfo: undefined,\n          fastWithdrawalMode: true,\n          hashApproved: \"\",\n          maxFee: {\n            tokenId: TOKEN_INFO.tokenMap[\"LRC\"].tokenId,\n            volume: fee.fees[\"LRC\"].fee ?? \"9400000000000000000\",\n          },\n          minGas: 0,\n          owner: LOOPRING_EXPORTED_ACCOUNT.address,\n          to: LOOPRING_EXPORTED_ACCOUNT.address,\n          storageId: 0,\n          token: {\n            tokenId: TOKEN_INFO.tokenMap.LRC.tokenId,\n            volume: LOOPRING_EXPORTED_ACCOUNT.tradeLRCValue.toString(),\n          },\n          validUntil: 0,\n        },\n        web3,\n        chainId: sdk.ChainId.GOERLI,\n        walletType: sdk.ConnectorNames.MetaMask,\n        eddsaKey: eddsaKey.sk,\n        apiKey,\n      });\n      console.log(\"response:\", response);\n    },\n    DEFAULT_TIMEOUT * 3\n  );\n});\n"
  },
  {
    "path": "src/types/eddsa.d.ts",
    "content": "declare module 'ffjavascript'\n\ndeclare module 'blake-hash'\n\ndeclare module 'circomlib'\n\ndeclare module \"blake2b\";\n"
  },
  {
    "path": "src/types.d.ts",
    "content": "declare global {\n  type Ethereum = any;\n  interface Window {\n    ethereum?: {\n      [key: string]: boolean;\n      isLoopring?: boolean;\n      isImToken?: boolean;\n      isMetaMask?: boolean;\n    } & Ethereum;\n    navigator: { userAgent: any } & any;\n    // socketEventMap: {[key:string]:any\n    // imageConfig:{[key:string]:any}|undefined\n  }\n}\n"
  },
  {
    "path": "src/utils/formatter.ts",
    "content": "import * as ethUtil from 'ethereumjs-util'\nimport BN from 'bn.js'\nimport BigNumber from 'bignumber.js'\nimport { Buffer } from 'buffer'\n\nimport {\n  AmmPoolInfoV3,\n  LOOPRING_URLs,\n  LoopringMap,\n  MarketInfo,\n  MarketStatus,\n  SEP,\n  SoursURL,\n  TokenAddress,\n  TokenInfo,\n  TOKENMAPLIST,\n  TokenRelatedInfo,\n} from '../defs'\nimport * as loopring_defs from '../defs/loopring_defs'\n\nBigNumber.config({\n  EXPONENTIAL_AT: 100,\n  RANGE: [-100000, 10000000],\n  ROUNDING_MODE: 1,\n})\n\n/**\n * Returns hex string with '0x' prefix\n * @param input\n * @returns {string}\n */\nexport function addHexPrefix(input: any) {\n  if (typeof input === 'string') {\n    return input.startsWith('0x') ? input : '0x' + input\n  }\n  throw new Error('Unsupported type')\n}\n\n/**\n *\n * @param mixed Buffer|number|string (hex string must be with '0x' prefix)\n * @returns {Buffer}\n */\nexport function toBuffer(mixed: any): Buffer {\n  if (mixed instanceof Buffer) {\n    return mixed\n  } else if (typeof mixed === 'string' && !mixed.startsWith('0x')) {\n    return Buffer.from(mixed)\n  } else {\n    return ethUtil.toBuffer(mixed) as Buffer\n  }\n}\n\n/**\n *\n * @param num number|string (hex string must be with '0x' prefix)\n * @param places number of zeros to pad\n * @returns {Buffer}\n */\nexport function zeroPad(num: any, places: any) {\n  return toBuffer(String(num).padStart(places, '0'))\n}\n\n/**\n *\n * @param mixed number | BigNumber |  BN  | Buffer | string | Uint8Array\n * @returns {string}\n */\nexport function toHex(mixed: number | BigNumber | BN | Buffer | string | Uint8Array | BigInt) {\n  if (typeof mixed === 'number') {\n    return addHexPrefix(toBig(mixed).toString(16))\n  }\n  if (mixed instanceof BigNumber || mixed instanceof BN) {\n    return addHexPrefix(mixed.toString(16))\n  }\n\n  if (mixed instanceof Buffer || mixed instanceof Uint8Array) {\n    return addHexPrefix((mixed as Buffer).toString('hex'))\n  }\n\n  if (typeof mixed === 'string') {\n    const regex = new RegExp(/^0x[0-9a-fA-F]*$/)\n    return regex.test(mixed) ? mixed : addHexPrefix(toBuffer(mixed).toString('hex'))\n  }\n  throw new Error('Unsupported type')\n}\n\n/**\n *\n * @param mixed number | BigNumber |  BN  | Buffer | string | Uint8Array\n * @returns {number}\n */\nexport function toNumber(mixed: number | BigNumber | BN | Buffer | string | Uint8Array) {\n  if (typeof mixed === 'number') {\n    return mixed\n  }\n\n  if (mixed instanceof BigNumber || mixed instanceof BN) {\n    return mixed.toNumber()\n  }\n\n  if (typeof mixed === 'string') {\n    return Number(mixed)\n  }\n\n  if (mixed instanceof Buffer || mixed instanceof Uint8Array) {\n    return Number((mixed as Buffer).toString('hex'))\n  }\n\n  throw new Error('Unsupported type')\n}\n\n/**\n *\n * @param mixed number | BigNumber |  BN  | Buffer | string | Uint8Array\n * @returns {BigNumber}\n */\nexport function toBig(mixed: number | BigNumber | BN | Buffer | string | Uint8Array) {\n  if (BigNumber.isBigNumber(mixed)) {\n    return mixed\n  }\n\n  if (typeof mixed === 'number') {\n    return new BigNumber(mixed.toString())\n  }\n\n  if (typeof mixed === 'string') {\n    return new BigNumber(mixed)\n  }\n  if (mixed instanceof Buffer || mixed instanceof Uint8Array) {\n    return new BigNumber((mixed as Buffer).toString('hex'))\n  }\n\n  throw new Error('Unsupported type')\n}\n\n/**\n *\n * @param mixed number | BigNumber |  BN  | Buffer | string\n * @returns {BN}\n */\nexport function toBN(mixed: any) {\n  return mixed instanceof BN ? mixed : new BN(toBig(mixed).toString(10), 10)\n}\n\n/**\n *\n * @param value number | BigNumber | Buffer | string\n * @returns {BN}\n */\nexport function fromGWEI(value: any) {\n  return new BigNumber(toBig(value).times(1e9).toFixed(0))\n}\n\n/**\n *\n * @param value number | BigNumber | Buffer | string\n * @returns {BN}\n */\nexport function toGWEI(value: any) {\n  return toBig(value).div(1e9)\n}\n\n/**\n * Returns formatted hex string of a given private key\n * @param mixed Buffer | string | Uint8Array\n * @returns {string}\n */\nexport function formatKey(mixed: Buffer | string | Uint8Array) {\n  if (mixed instanceof Buffer || mixed instanceof Uint8Array) {\n    return (mixed as Buffer).toString('hex')\n  }\n\n  if (typeof mixed === 'string') {\n    return mixed.startsWith('0x') ? mixed.slice(2) : mixed\n  }\n  throw new Error('Unsupported type')\n}\n\n/**\n * Returns hex string of a given address\n * @param mixed Buffer | string |Uint8Array\n * @returns {string}\n */\nexport function formatAddress(mixed: Buffer | string | Uint8Array) {\n  if (mixed instanceof Buffer || mixed instanceof Uint8Array) {\n    return ethUtil.toChecksumAddress('0x' + (mixed as Buffer).toString('hex'))\n  }\n\n  if (typeof mixed === 'string') {\n    return ethUtil.toChecksumAddress(mixed.startsWith('0x') ? mixed : '0x' + mixed)\n  }\n  throw new Error('Unsupported type')\n}\n\n/**\n * Returns hex string without '0x' prefix\n * @param input string\n * @returns {string}\n */\nexport function clearHexPrefix(input: any) {\n  if (typeof input === 'string') {\n    return input.startsWith('0x') ? input.slice(2) : input\n  }\n  throw new Error('Unsupported type')\n}\n\n/**\n *\n * @param hex\n * @returns {string}\n */\nexport function padLeftEven(hex: any) {\n  return hex.length % 2 !== 0 ? `0${hex}` : hex\n}\n\n/**\n * Returns symbol of a given kind of currency\n * @param settingsCurrency\n * @returns {*}\n */\nexport function getDisplaySymbol(settingsCurrency: any) {\n  switch (settingsCurrency) {\n    case 'CNY':\n      return '￥'\n    case 'USD':\n      return '$'\n    default:\n      return ''\n  }\n}\n\n/**\n * Returns number in string with a given precision\n * @param number number | BigNumber\n * @param precision number\n * @param ceil bool  round up\n * @returns {string}\n */\nexport function toFixed(number: any, precision: any, ceil: any) {\n  precision = precision || 0\n  if (number instanceof BigNumber) {\n    const rm = ceil ? 0 : 1\n    return number.toFixed(precision, rm)\n  }\n\n  if (typeof number === 'number') {\n    return ceil\n      ? (Math.ceil(number * Number('1e' + precision)) / Number('1e' + precision)).toFixed(precision)\n      : (Math.floor(number * Number('1e' + precision)) / Number('1e' + precision)).toFixed(\n          precision,\n        )\n  }\n\n  throw new Error('Unsupported type')\n}\n\nexport function formatEddsaKey(key: any) {\n  const hexKey = clearHexPrefix(key)\n  return addHexPrefix(String(hexKey).padStart(64, '0'))\n}\n\n/**\n * Returns a number with commas as thousands separators\n * @param number number\n * @returns {*}\n */\nexport function numberWithCommas(number: any) {\n  if (number) {\n    number = number.toString().replace(/,/g, '')\n    if (isNaN(Number(number))) {\n      return '-'\n    }\n    try {\n      const parts = number.toString().split('.')\n      parts[0] = parts[0].replace(/\\B(?=(\\d{3})+(?!\\d))/g, ',')\n      return parts.join('.')\n    } catch (err) {\n      return '-'\n    }\n  } else {\n    return number\n  }\n}\n\nexport function sortObjDictionary(obj: { [key: string]: any }): Map<string, any> {\n  const dataToSig: Map<string, any> = new Map()\n  if (obj) {\n    Reflect.ownKeys(obj)\n      .sort((a, b) => a.toString().localeCompare(b.toString()))\n      .forEach((key) => {\n        dataToSig.set(key.toString(), obj[key.toString()])\n      })\n  }\n  return dataToSig\n}\nexport function makeMarket<R extends TokenInfo = TokenInfo>(raw_data: R[]): TOKENMAPLIST {\n  const coinMap: LoopringMap<{\n    icon?: string\n    name: string\n    simpleName: string\n    description?: string\n    company: string\n  }> = {}\n  const totalCoinMap: LoopringMap<{\n    icon?: string\n    name: string\n    simpleName: string\n    description?: string\n    company: string\n  }> = {}\n  const addressIndex: LoopringMap<TokenAddress> = {}\n  const idIndex: LoopringMap<string> = {}\n  const tokensMap: LoopringMap<TokenInfo> = {}\n  if (raw_data instanceof Array) {\n    raw_data.forEach((item) => {\n      if (item?.symbol.startsWith('LP-')) {\n        item.isLpToken = true\n      } else {\n        item.isLpToken = false\n      }\n      tokensMap[item.symbol] = item\n\n      const coinInfo = {\n        icon: SoursURL + `ethereum/assets/${item.address}/logo.png`,\n        name: item.name,\n        simpleName: item.symbol,\n        description: item.type,\n        company: item.name,\n      }\n      if (!item.symbol.startsWith('LP-')) {\n        coinMap[item.symbol] = coinInfo\n      }\n      totalCoinMap[item.symbol] = coinInfo\n      addressIndex[item.address.toLowerCase()] = item.symbol\n      // @ts-ignore\n      idIndex[/vault/gi.test(item.type?.toLowerCase()) ? item?.vaultTokenId : item.tokenId] =\n        item.symbol\n    })\n  }\n  return {\n    tokensMap,\n    coinMap,\n    totalCoinMap,\n    idIndex,\n    addressIndex,\n  }\n}\nexport function makeAmmPool<R>(raw_data: any): {\n  ammpools: LoopringMap<AmmPoolInfoV3>\n  pairs: LoopringMap<TokenRelatedInfo>\n} {\n  const ammpools: LoopringMap<AmmPoolInfoV3> = {}\n  const pairs: LoopringMap<TokenRelatedInfo> = {}\n  if (raw_data?.pools instanceof Array) {\n    raw_data.pools.forEach((item: any) => {\n      const market: string = item.market\n      ammpools[market] = item\n      let base = '',\n        quote = ''\n      const ind = market.indexOf('-')\n      const ind2 = market.lastIndexOf('-')\n      base = market.substring(ind + 1, ind2)\n      quote = market.substring(ind2 + 1, market.length)\n\n      if (!pairs[base]) {\n        pairs[base] = {\n          tokenId: item.tokens.pooled[0],\n          tokenList: [quote],\n        }\n      } else {\n        pairs[base].tokenList = [...pairs[base].tokenList, quote]\n      }\n\n      if (!pairs[quote]) {\n        pairs[quote] = {\n          tokenId: item.tokens.pooled[1],\n          tokenList: [base],\n        }\n      } else {\n        pairs[quote].tokenList = [...pairs[quote].tokenList, base]\n      }\n    })\n  }\n  return {\n    ammpools,\n    pairs,\n  }\n}\n\nexport function makeMarkets<R, C extends MarketInfo>(\n  raw_data: any,\n  url: string = LOOPRING_URLs.GET_MARKETS,\n): {\n  markets: LoopringMap<C>\n  pairs: LoopringMap<TokenRelatedInfo>\n  tokenArr: string[]\n  tokenArrStr: string\n  marketArr: string[]\n  marketArrStr: string\n} {\n  const markets: LoopringMap<C> = {}\n\n  const pairs: LoopringMap<TokenRelatedInfo> = {}\n\n  const isMix = url === LOOPRING_URLs.GET_MIX_MARKETS\n\n  if (raw_data?.markets instanceof Array) {\n    raw_data.markets.forEach((item: any) => {\n      const marketInfo: C = {\n        ...item,\n        baseTokenId: item.baseTokenId,\n        enabled: item.enabled,\n        market: item.market,\n        orderbookAggLevels: item.orderbookAggLevels,\n        precisionForPrice: item.precisionForPrice,\n        quoteTokenId: item.quoteTokenId,\n      }\n\n      if (isMix) {\n        marketInfo.status = item.status as MarketStatus\n        marketInfo.isSwapEnabled =\n          marketInfo.status === MarketStatus.ALL || marketInfo.status === MarketStatus.AMM\n        marketInfo.createdAt = parseInt(item.createdAt)\n      }\n\n      markets[item.market] = marketInfo\n\n      if (item.enabled) {\n        const market: string = item.market\n        const ind = market.indexOf('-')\n        const base = market.substring(0, ind)\n        const quote = market.substring(ind + 1, market.length)\n\n        if (!pairs[base]) {\n          pairs[base] = {\n            tokenId: item.baseTokenId,\n            tokenList: [quote],\n          }\n        } else {\n          pairs[base].tokenList = [...pairs[base].tokenList, quote]\n        }\n\n        if (!pairs[quote]) {\n          pairs[quote] = {\n            tokenId: item.quoteTokenId,\n            tokenList: [base],\n          }\n        } else {\n          pairs[quote].tokenList = [...pairs[quote].tokenList, base]\n        }\n      }\n    })\n  }\n\n  const marketArr: string[] = Reflect.ownKeys(markets) as string[]\n\n  const tokenArr: string[] = Reflect.ownKeys(pairs) as string[]\n\n  return {\n    markets,\n    pairs,\n    tokenArr,\n    tokenArrStr: tokenArr.join(SEP),\n    marketArr,\n    marketArrStr: marketArr.join(SEP),\n  }\n}\n\nexport function makeMarketsWithIdIndex<C extends MarketInfo>(\n  raw_data: any,\n  url: string = LOOPRING_URLs.GET_MARKETS,\n  idIndex: any\n): {\n  markets: LoopringMap<C>\n  pairs: LoopringMap<TokenRelatedInfo>\n  tokenArr: string[]\n  tokenArrStr: string\n  marketArr: string[]\n  marketArrStr: string\n} {\n  const markets: LoopringMap<C> = {}\n\n  const pairs: LoopringMap<TokenRelatedInfo> = {}\n\n  const isMix = url === LOOPRING_URLs.GET_MIX_MARKETS\n\n  if (raw_data?.markets instanceof Array) {\n    raw_data.markets.forEach((item: any) => {\n      const marketInfo: C = {\n        ...item,\n        baseTokenId: item.baseTokenId,\n        enabled: item.enabled,\n        market: item.market,\n        orderbookAggLevels: item.orderbookAggLevels,\n        precisionForPrice: item.precisionForPrice,\n        quoteTokenId: item.quoteTokenId,\n      }\n\n      if (isMix) {\n        marketInfo.status = item.status as MarketStatus\n        marketInfo.isSwapEnabled =\n          marketInfo.status === MarketStatus.ALL || marketInfo.status === MarketStatus.AMM\n        marketInfo.createdAt = parseInt(item.createdAt)\n      }\n\n      const base = idIndex[item.baseTokenId]\n      const quote = idIndex[item.quoteTokenId]\n\n      markets[`${base}-${quote}`] = {\n        ...marketInfo,\n        market: `${base}-${quote}`,\n      }\n\n      if (item.enabled) {\n        if (!pairs[base]) {\n          pairs[base] = {\n            tokenId: item.baseTokenId,\n            tokenList: [quote],\n          }\n        } else {\n          pairs[base].tokenList = [...pairs[base].tokenList, quote]\n        }\n\n        if (!pairs[quote]) {\n          pairs[quote] = {\n            tokenId: item.quoteTokenId,\n            tokenList: [base],\n          }\n        } else {\n          pairs[quote].tokenList = [...pairs[quote].tokenList, base]\n        }\n      }\n    })\n  }\n\n  const marketArr: string[] = Reflect.ownKeys(markets) as string[]\n\n  const tokenArr: string[] = Reflect.ownKeys(pairs) as string[]\n\n  return {\n    markets,\n    pairs,\n    tokenArr,\n    tokenArrStr: tokenArr.join(SEP),\n    marketArr,\n    marketArrStr: marketArr.join(SEP),\n  }\n}\n\nexport function makeInvestMarkets<C extends loopring_defs.DefiMarketInfo>(\n  raw_data: any,\n  types?: string[],\n): {\n  markets: LoopringMap<C>\n  pairs: LoopringMap<TokenRelatedInfo>\n  tokenArr: string[]\n  tokenArrStr: string\n  marketArr: string[]\n  marketArrStr: string\n} {\n  let markets: loopring_defs.LoopringMap<C> = {}\n\n  let pairs: loopring_defs.LoopringMap<TokenRelatedInfo> = {}\n  // const isMix = url === LOOPRING_URLs.GET_MIX_MARKETS;\n\n  if (raw_data?.markets instanceof Array) {\n    let _markets = []\n    if (types) {\n      _markets = raw_data.markets.filter((item: C) => types.includes(item.type?.toUpperCase()))\n    } else {\n      _markets = raw_data.markets\n    }\n    _markets.forEach((item: any) => {\n      const marketInfo: C = {\n        ...item,\n      }\n\n      markets[item.market] = marketInfo\n\n      if (item.enabled) {\n        const [_markets, type, base, quote] = item.market.match(/^(\\w+-)?(\\w+)-(\\w+)$/i)\n        if (type === 'DUAL-' && base && quote) {\n          if (!pairs[base]) {\n            pairs[base] = {\n              tokenId: item.baseTokenId,\n              tokenList: [quote],\n            }\n          } else {\n            pairs[base].tokenList = [...pairs[base].tokenList, quote]\n          }\n          if (!pairs[quote]) {\n            pairs[quote] = {\n              tokenId: item.baseTokenId,\n              tokenList: [base],\n            }\n          } else {\n            pairs[quote].tokenList = [...pairs[quote].tokenList, base]\n          }\n        } else if (base && quote) {\n          const market: string = item.market\n          // const ind = market.indexOf(\"-\");\n          // const base = market.substring(0, ind);\n          // const quote = market.substring(ind + 1, market.length);\n\n          if (!pairs[base]) {\n            pairs[base] = {\n              tokenId: item.baseTokenId,\n              tokenList: [quote],\n            }\n          } else {\n            pairs[base].tokenList = [...pairs[base].tokenList, quote]\n          }\n        }\n      }\n    })\n  }\n  const marketArr: string[] = Reflect.ownKeys(markets) as string[]\n  const tokenArr: string[] = Reflect.ownKeys(pairs) as string[]\n  return {\n    markets,\n    pairs,\n    tokenArr,\n    tokenArrStr: tokenArr.join(SEP),\n    marketArr,\n    marketArrStr: marketArr.join(SEP),\n  }\n}\n"
  },
  {
    "path": "src/utils/index.ts",
    "content": "export * from \"./network_tools\";\nexport * from \"./symbol_tools\";\nexport * from \"./formatter\";\nexport * from \"./swap_calc_utils\";\nexport type RequiredPart<T, K> = Required<{ [K in keyof T]: Pick<T, K> }> & T;\n"
  },
  {
    "path": "src/utils/log_tools.ts",
    "content": "/* eslint-disable no-console, @typescript-eslint/ban-ts-comment */\nlet _myLog;\n\nif (\n  process.env.NODE_ENV !== \"production\" ||\n  // @ts-ignore\n  (typeof window !== \"undefined\" && window?.___OhTrustDebugger___)\n) {\n  _myLog = console.log;\n} else {\n  _myLog = function (message?: any, ...optionalParams: any[]) {\n    return \"\";\n  };\n}\nlet _myError;\nif (\n  process.env.NODE_ENV !== \"production\" ||\n  // @ts-ignore\n  (typeof window !== \"undefined\" && window?.___OhTrustDebugger___)\n) {\n  _myError = console.error;\n} else {\n  _myError = function (message?: any, ...optionalParams: any[]) {\n    return \"\";\n  };\n}\nexport const myLog = _myLog;\nexport const myError = _myError;\n"
  },
  {
    "path": "src/utils/network_tools.ts",
    "content": "/* eslint-disable no-console  */\nexport const dumpError400 = (reason: any, src = '') => {\n  if (src) {\n    console.debug('src:', src)\n  }\n  if (reason && reason.response) {\n    console.error(reason.response.data)\n  } else {\n    console.error(reason.message)\n  }\n}\n\nexport function sleep(milliseconds: number) {\n  return new Promise((resolve) => setTimeout(resolve, milliseconds))\n}\n"
  },
  {
    "path": "src/utils/obj_tools.ts",
    "content": "export const sortObject = (o: any) =>\n  Object.keys(o)\n    .sort()\n    .reduce((r: any, k) => ((r[k] = o[k]), r), {});\n"
  },
  {
    "path": "src/utils/swap_calc_utils.ts",
    "content": "import * as fm from './formatter'\nimport { toBig } from './formatter'\nimport {\n  ABInfo,\n  AmmPoolSnapshot,\n  CalDualResult,\n  BTRADE_MARKET,\n  BtradeResult,\n  ConnectorError,\n  DefiMarketInfo,\n  DepthData,\n  DUAL_TYPE,\n  DualBalance,\n  DualIndex,\n  DualProductAndPrice,\n  DualRulesCoinsInfo,\n  ExitAmmPoolRequest,\n  JoinAmmPoolRequest,\n  LoopringErrorCode,\n  LoopringMap,\n  MarketInfo,\n  OffchainFeeInfo,\n  TokenInfo,\n  TokenVolumeV3,\n  XOR,\n  VaultMarket,\n} from '../defs'\n\nimport { getExistedMarket, getTokenInfoBySymbol } from './symbol_tools'\nimport BigNumber from 'bignumber.js'\nimport { myLog } from './log_tools'\n\nconst BIG0 = fm.toBig(0)\n\nconst BIG1 = fm.toBig(1)\n\nconst BIG10 = fm.toBig(10)\n\nconst BIG10K = fm.toBig(10000)\n\nexport const getToken = (tokens: any, token: any) => {\n  if (!tokens) {\n    throw Error('no tokens list!')\n  }\n  return tokens[token]\n}\n\nexport const getTokenInfoByToken = (ammBalance: any, tokens: any, token: any) => {\n  const tokenInfo = getToken(tokens, token)\n\n  const tokenVol = ammBalance.pooledMap[tokenInfo.tokenId].volume\n  const reserve = fm.toBig(tokenVol)\n\n  return {\n    tokenInfo,\n    tokenVol,\n    reserve,\n  }\n}\n\nexport function fromWEI(tokens: any, symbol: any, valueInWEI: any, precision?: any, ceil?: any) {\n  try {\n    const tokenInfo = getToken(tokens, symbol)\n    const precisionToFixed = precision ? precision : tokenInfo.precision\n    const value = fm.toBig(valueInWEI).div('1e' + tokenInfo.decimals)\n    return fm.toFixed(value, precisionToFixed, ceil)\n  } catch (err) {\n    return undefined\n  }\n  return '0'\n}\n\nexport function toWEI(tokens: any, symbol: any, value: any, rm: any = undefined) {\n  const tokenInfo = getToken(tokens, symbol)\n  if (typeof tokenInfo === 'undefined') {\n    return '0'\n  }\n\n  const bigN = fm.toBig(value).times('1e' + tokenInfo.decimals)\n\n  return rm === undefined ? bigN.toString() : bigN.toFixed(0, rm)\n}\n\nexport function isEmpty(input: any) {\n  if (!input || input.trim() === '') {\n    return true\n  }\n\n  return false\n}\n\nfunction getAmountOutWithFeeBips(\n  amountIn: string,\n  feeBips: string,\n  reserveIn: string,\n  reserveOut: string,\n) {\n  const amountInBig = fm.toBig(amountIn)\n  const reserveInBig = fm.toBig(reserveIn)\n  const reserveOutBig = fm.toBig(reserveOut)\n\n  if (amountInBig.lt(BIG0) || reserveInBig.lt(BIG0) || reserveOutBig.lt(BIG0)) {\n    return BIG0\n  }\n\n  const feeBipsBig = fm.toBig(feeBips)\n\n  const amountInWithFee = amountInBig.times(BIG10K.minus(feeBipsBig))\n  const numerator = amountInWithFee.times(reserveOutBig)\n  const denominator = reserveInBig.times(BIG10K).plus(amountInWithFee)\n\n  return numerator.div(denominator)\n}\n\nfunction getAmountInWithFeeBips(\n  amountOut: string,\n  feeBips: string,\n  reserveIn: string,\n  reserveOut: string,\n) {\n  const amountOutBig = fm.toBig(amountOut)\n  const reserveInBig = fm.toBig(reserveIn)\n  const reserveOutBig = fm.toBig(reserveOut)\n\n  if (amountOutBig.lt(BIG0) || reserveInBig.lt(BIG0) || reserveOutBig.lt(BIG0)) {\n    return BIG0\n  }\n\n  const feeBipsBig = fm.toBig(feeBips)\n\n  const numerator = reserveInBig.times(amountOutBig).times(BIG10K)\n  const denominator = reserveOutBig.minus(amountOutBig).times(BIG10K.minus(feeBipsBig))\n\n  return numerator.div(denominator).plus(BIG1)\n}\n\nfunction getOutputOrderbook(\n  input: string,\n  baseToken: TokenInfo | undefined,\n  quoteToken: TokenInfo | undefined,\n  feeBips: string,\n  isAtoB: boolean,\n  isReverse: boolean,\n  depth: DepthData,\n) {\n  let output = '0'\n  let remain: string = input\n\n  const bids = depth.bids // .reverse()\n\n  // console.log('bids:', bids[0])\n  // console.log('bids last:', bids[bids.length - 1])\n  // console.log('asks:', depth.asks[0])\n  // console.log('asks last:', depth.asks[depth.asks.length - 1])\n\n  // console.log(`isAtoB:${isAtoB} isReverse:${isReverse}`)\n\n  if (!baseToken || !quoteToken) {\n    return output\n  }\n  // myLog(baseToken, ' ', quoteToken)\n\n  //amt is size(base ETH). vol is volume(quote USDT)\n\n  if (isAtoB) {\n    if (!isReverse) {\n      //ETH -> USDT\n\n      remain = fm\n        .toBig(remain)\n        .times('1e' + baseToken.decimals)\n        .toString()\n\n      for (let i = bids.length - 1; i >= 0; i--) {\n        const abInfo: ABInfo = bids[i]\n        if (fm.toBig(abInfo.amt).lte(BIG0)) {\n          continue\n        }\n        // console.log(`i:${i} abInfo:`, abInfo, `decimals:${baseToken.decimals} ${quoteToken.decimals}`)\n\n        const consume: string = fm.toBig(remain).gte(fm.toBig(abInfo.amt)) ? abInfo.amt : remain\n\n        if (fm.toBig(consume).lte(BIG0)) {\n          break\n        }\n\n        const volValue = fm.toBig(abInfo.vol).div('1e' + quoteToken.decimals)\n\n        if (fm.toBig(consume).eq(fm.toBig(abInfo.amt))) {\n          output = fm.toBig(output).plus(volValue).toString()\n        } else {\n          const ratio = fm.toBig(consume).div(fm.toBig(abInfo.amt))\n          // myLog('got ratio:', ratio.toString(), consume, abInfo.amt)\n          output = fm.toBig(output).plus(ratio.times(volValue)).toString()\n        }\n\n        // myLog('1__ ', i, ' output:', output, ' remain:', remain, ' abInfo.amt:', abInfo.amt, ' abInfo.vol:', abInfo.vol, ' volValue:', volValue.toString())\n\n        remain = fm.toBig(remain).minus(fm.toBig(consume)).toString()\n      }\n    } else {\n      // USDT -> ETH\n      // isAtoB = true, isReverse = false\n\n      remain = fm.toBig(remain).times(BIG10.pow(baseToken.decimals)).toString()\n\n      for (let i = 0; i < depth.asks.length; i++) {\n        const abInfo: ABInfo = depth.asks[i]\n        if (fm.toBig(abInfo.amt).lte(BIG0)) {\n          continue\n        }\n        // const placed: string = fm.toBig(abInfo.vol).div(BIG10.pow(quoteToken.decimals)).toString()\n        const consume: string = fm.toBig(remain).gte(fm.toBig(abInfo.vol)) ? abInfo.vol : remain\n\n        if (fm.toBig(consume).lte(BIG0)) {\n          // console.log('return 22222')\n          break\n        }\n\n        // console.log(`i:${i} abInfo:`, abInfo, `decimals:${baseToken.decimals} ${quoteToken.decimals}`)\n\n        // console.log('remain:', remain, ' abInfo.vol:', abInfo.vol, ' consume:', consume)\n\n        const amtValue = fm.toBig(abInfo.amt).div('1e' + quoteToken.decimals)\n\n        if (fm.toBig(consume).eq(fm.toBig(abInfo.vol))) {\n          output = fm.toBig(output).plus(amtValue).toString()\n        } else {\n          const ratio = fm.toBig(consume).div(fm.toBig(abInfo.vol))\n          output = fm.toBig(output).plus(ratio.times(amtValue)).toString()\n        }\n\n        remain = fm.toBig(remain).minus(fm.toBig(consume)).toString()\n\n        // myLog('2__ ', i, ' output:', output, ' abInfo.vol:', abInfo.vol, ' remain:', remain)\n      }\n    }\n  } else {\n    if (!isReverse) {\n      // ETH <- USDT\n\n      remain = fm.toBig(remain).times(BIG10.pow(quoteToken.decimals)).toString()\n\n      for (let i = bids.length - 1; i >= 0; i--) {\n        const abInfo: ABInfo = bids[i]\n        // const placed: string = fm.toBig(abInfo.vol).div(BIG10.pow(quoteToken.decimals)).toString()\n\n        const consume: string = fm.toBig(remain).gte(fm.toBig(abInfo.vol)) ? abInfo.vol : remain\n\n        if (fm.toBig(consume).lte(BIG0)) {\n          break\n        }\n\n        // myLog(`i:${i} abInfo:`, abInfo, `decimals:${baseToken.decimals} ${quoteToken.decimals}`)\n\n        // myLog('remain:', remain, 'abInfo.vol:', abInfo.vol, ' consume:', consume)\n\n        const amtValue = fm.toBig(abInfo.amt).div(BIG10.pow(baseToken.decimals))\n\n        if (fm.toBig(consume).eq(abInfo.vol)) {\n          output = fm.toBig(output).plus(fm.toBig(amtValue)).toString()\n        } else {\n          const ratio = fm.toBig(consume).div(fm.toBig(abInfo.vol))\n          output = fm.toBig(output).plus(ratio.times(amtValue)).toString()\n        }\n\n        remain = fm.toBig(remain).minus(fm.toBig(consume)).toString()\n\n        // myLog('3__', i, ' output:', output, ' abInfo.vol:', abInfo.vol, ' remain:', remain)\n      }\n    } else {\n      // USDT <- ETH\n\n      remain = fm.toBig(remain).times(BIG10.pow(quoteToken.decimals)).toString()\n\n      for (let i = 0; i < depth.asks.length; i++) {\n        const abInfo: ABInfo = depth.asks[i]\n\n        // myLog(`i:${i} abInfo:`, abInfo, `decimals:${baseToken.decimals} ${quoteToken.decimals}`)\n\n        const consume: string = fm.toBig(remain).gte(fm.toBig(abInfo.amt)) ? abInfo.amt : remain\n\n        if (fm.toBig(consume).lte(BIG0)) {\n          break\n        }\n\n        const volValue = fm.toBig(abInfo.vol).div(BIG10.pow(baseToken.decimals))\n\n        if (fm.toBig(consume).eq(fm.toBig(abInfo.amt))) {\n          output = fm.toBig(output).plus(volValue).toString()\n        } else {\n          const ratio = fm.toBig(consume).div(fm.toBig(abInfo.amt))\n          output = fm.toBig(output).plus(ratio.times(volValue)).toString()\n        }\n\n        // myLog('4__', i, ' output:', output, ' abInfo.vol:', abInfo.vol, ' volValue:', volValue.toString())\n\n        remain = fm.toBig(remain).minus(fm.toBig(consume)).toString()\n      }\n    }\n  }\n\n  return output\n}\n\nexport function getReserveInfo(\n  sell: string,\n  buy: string,\n  marketArr: string[],\n  tokenMap: LoopringMap<TokenInfo>,\n  marketMap: LoopringMap<MarketInfo>,\n  ammPoolSnapshot: AmmPoolSnapshot | undefined = undefined,\n) {\n  const { market, amm, baseShow, quoteShow } = getExistedMarket(marketArr, sell, buy)\n\n  if (isEmpty(market) || isEmpty(amm) || Object.keys(marketMap).indexOf(market) < 0) {\n    return undefined\n  }\n\n  const marketInfo: MarketInfo = marketMap[market]\n\n  const sellToken = getTokenInfoBySymbol(tokenMap, sell)\n  const buyToken = getTokenInfoBySymbol(tokenMap, buy)\n\n  let isReverse = false\n\n  const coinA = ammPoolSnapshot?.pooled[0]\n\n  const coinB = ammPoolSnapshot?.pooled[1]\n\n  let reserveIn = '0'\n  let reserveOut = '0'\n\n  if (\n    sellToken?.tokenId !== undefined &&\n    buyToken?.tokenId !== undefined &&\n    coinA?.tokenId !== undefined &&\n    coinB?.tokenId !== undefined\n  ) {\n    if (sellToken?.tokenId === coinA?.tokenId) {\n      reserveIn = coinA.volume\n      reserveOut = coinB.volume\n    } else {\n      reserveIn = coinB.volume\n      reserveOut = coinA.volume\n      isReverse = true\n    }\n  } else {\n    if (market === `${buy}-${sell}`) {\n      isReverse = true\n    }\n  }\n\n  return {\n    reserveIn,\n    reserveOut,\n    sellToken,\n    buyToken,\n    coinA,\n    coinB,\n    isReverse,\n    marketInfo,\n  }\n}\n\nfunction getPriceImpactStr(curPrice: string, toPrice: string) {\n  if (!curPrice || !toPrice) {\n    return '0'\n  }\n\n  const toPriceBig = fm.toBig(toPrice)\n\n  if (toPriceBig.eq(BIG0)) {\n    return '0'\n  }\n\n  const percent = fm.toBig(toPriceBig).div(curPrice)\n\n  return BIG1.minus(percent).abs().toString()\n}\n\nexport function getCurPrice(reserveIn: string, reserveOut: string) {\n  if (!reserveIn || !reserveOut) {\n    return '0'\n  }\n\n  reserveIn = reserveIn.trim()\n  reserveOut = reserveOut.trim()\n\n  const reserveInBig = fm.toBig(reserveIn)\n  const reserveOutBig = fm.toBig(reserveOut)\n\n  if (reserveInBig.eq(BIG0)) {\n    return '0'\n  }\n\n  return reserveOutBig.div(reserveInBig).toString()\n}\n\nexport function getToPrice(amountS: string, amountB: string) {\n  if (!amountS || !amountB) {\n    return '0'\n  }\n\n  amountS = amountS.trim()\n  amountB = amountB.trim()\n\n  const amountSBig = fm.toBig(amountS)\n  const amountBBig = fm.toBig(amountB)\n\n  if (amountSBig.eq(BIG0)) {\n    return '0'\n  }\n\n  return amountBBig.div(amountSBig).toString()\n}\n\nexport function getPriceImpact(\n  reserveIn: string,\n  reserveOut: string,\n  amountS: string,\n  feeBips: string,\n  takerFee: string,\n) {\n  let amountB: BigNumber = getAmountOutWithFeeBips(amountS, feeBips, reserveIn, reserveOut)\n  amountB = amountB.times(BIG10K.minus(fm.toBig(takerFee))).div(BIG10K)\n  const curPrice = getCurPrice(reserveIn, reserveOut)\n  const toPrice = getToPrice(amountS, amountB.toString())\n\n  return getPriceImpactStr(curPrice, toPrice)\n}\n\nexport function updatePriceImpact_new(\n  reverseIn: string,\n  reverseOut: string,\n  amountS: string,\n  sellDecimal: number,\n  amountBOut: string,\n  buyDecimal: number,\n  feeBips: string,\n  takerFee: string,\n  isAtoB: boolean,\n  isReversed: boolean,\n  exceedDepth: boolean,\n  depth: DepthData,\n) {\n  let priceImpact = '0'\n\n  if (isEmpty(reverseIn) || isEmpty(reverseOut) || isEmpty(feeBips)) {\n    return '0'\n  }\n\n  if (exceedDepth) {\n    priceImpact = getPriceImpact(reverseIn, reverseOut, amountS, feeBips, '0')\n  } else {\n    if (!depth.mid_price) {\n      return '0'\n    }\n\n    // LRC / ETH !isReversed isAtoB\n    const coinADecimal = !isReversed ? sellDecimal : buyDecimal\n    const coinBDecimal = !isReversed ? buyDecimal : sellDecimal\n    const curPrice = fm\n      .toBig(depth.mid_price)\n      .times('1e' + coinBDecimal)\n      .div('1e' + coinADecimal)\n      .toString()\n    const toPrice = !isReversed ? getToPrice(amountS, amountBOut) : getToPrice(amountBOut, amountS)\n    // console.log('updatePriceImpact_new isReversed:', isReversed, ' amountS:', amountS, ' amountBOut:', amountBOut)\n    // console.log('updatePriceImpact_new toPrice:', toPrice, ' curPrice:', curPrice)\n\n    priceImpact = getPriceImpactStr(curPrice, toPrice)\n  }\n\n  return priceImpact\n}\n\nexport function getMinReceived(amountBOut: string, minimumDecimal: number, slipBips: string) {\n  const minReceived = fm\n    .toBig(amountBOut)\n    .times(BIG10K.minus(fm.toBig(slipBips)))\n    .div(BIG10K)\n  return {\n    minReceived: minReceived.toFixed(0, 0),\n    minReceivedVal: minReceived.div('1e' + minimumDecimal).toString(),\n    minimumDecimal,\n  }\n}\n\nexport function getOutputAmount({\n  input,\n  sell,\n  buy,\n  isAtoB,\n  marketArr,\n  tokenMap,\n  marketMap,\n  depth,\n  ammPoolSnapshot,\n  feeBips,\n  takerRate,\n  slipBips,\n}: {\n  input: string\n  sell: string\n  buy: string\n  isAtoB: boolean\n  marketArr: string[]\n  tokenMap: LoopringMap<TokenInfo>\n  marketMap: LoopringMap<MarketInfo>\n  depth: DepthData\n  ammPoolSnapshot: AmmPoolSnapshot | undefined\n  feeBips: string\n  takerRate: string\n  slipBips: string\n}):\n  | {\n      exceedDepth: boolean\n      isReverse: boolean\n      isAtoB: boolean\n      slipBips: string\n      takerRate: string\n      feeBips: string\n      output: any\n      sellAmt: string\n      buyAmt: string\n      amountS: string\n      amountBOut: string\n      amountBOutWithoutFee: string\n      amountBOutSlip: {\n        minReceived: string\n        minReceivedVal: string\n        minimumDecimal: number\n      }\n      priceImpact: string\n    }\n  | undefined {\n  // console.log('enter getOutputAmount:', input, base, quote, isAtoB, marketArr, tokenMap, marketMap, depth, ammPoolSnapshot, feeBips, takerRate, slipBips)\n\n  // console.log(`getOutputAmount market: ${base} / ${quote}`)\n\n  // console.log('ammPoolSnapshot:', ammPoolSnapshot)\n\n  const reserveInfo = getReserveInfo(sell, buy, marketArr, tokenMap, marketMap, ammPoolSnapshot)\n\n  if (!reserveInfo) {\n    return undefined\n  }\n\n  const { reserveIn, reserveOut, sellToken, buyToken, isReverse, marketInfo } = reserveInfo\n\n  if (!sellToken || !buyToken) {\n    return undefined\n  }\n\n  input = input.trim()\n\n  let exceedDepth = false\n\n  let output: any = '0'\n\n  let amountS = '0'\n\n  let amountBOutWithoutFee = '0'\n\n  let amountBOut = '0'\n\n  let sellAmt = '0'\n  let buyAmt = '0'\n\n  let minimumDecimal = 0\n\n  if (isAtoB) {\n    // bids_amtTotal -> bidsSizeShown\n    // asks_volTotal -> asksQuoteSizeShown\n    const amountInWei = toWEI(tokenMap, sell, input, 0)\n\n    // console.log('isAtoB amountInWei:', amountInWei)\n\n    if (isEmpty(depth.bids_amtTotal) || isEmpty(depth.asks_volTotal)) {\n      exceedDepth = true\n    } else {\n      if (!isReverse) {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.bids_amtTotal))\n        // console.log('3 amountInWei:', amountInWei, ' bids_amtTotal:', depth.bids_amtTotal)\n      } else {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.asks_volTotal))\n        // console.log('4 amountInWei:', amountInWei, ' asks_volTotal:', depth.asks_volTotal)\n      }\n    }\n    // console.log(`a2b(input:${input})  exceedDepth:`, exceedDepth, ' isSwapEnabled:', marketInfo.isSwapEnabled)\n\n    if (exceedDepth) {\n      if (marketInfo.isSwapEnabled) {\n        const amountB = getAmountOutWithFeeBips(amountInWei, feeBips, reserveIn, reserveOut)\n        output = fromWEI(tokenMap, buy, amountB.toFixed(0, 0))\n      }\n    } else {\n      output = getOutputOrderbook(input, sellToken, buyToken, feeBips, isAtoB, isReverse, depth)\n    }\n\n    amountBOutWithoutFee = toWEI(tokenMap, buy, output, 0)\n\n    const leftRatio = BIG10K.minus(fm.toBig(takerRate)).div(BIG10K)\n\n    // console.log('amountBOutWithoutFee:', amountBOutWithoutFee, ' leftRatio:', leftRatio.toString())\n\n    amountBOut = toWEI(tokenMap, buy, fm.toBig(output).times(leftRatio).toString(), 0)\n\n    amountS = toWEI(tokenMap, sell, input, 0)\n\n    sellAmt = input\n    buyAmt = output\n  } else {\n    // asks_amtTotal -> asksSizeShown\n    // bids_volTotal -> bidsQuoteSizeShown\n\n    if (isEmpty(depth.bids_volTotal) || isEmpty(depth.asks_amtTotal)) {\n      exceedDepth = true\n    } else {\n      const amountInWei = toWEI(tokenMap, buy, input, 0)\n\n      if (!isReverse) {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.bids_volTotal))\n      } else {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.asks_amtTotal))\n      }\n    }\n\n    let amountSBint = BIG0\n\n    const amountB: string = toWEI(tokenMap, buy, input, 0)\n\n    // console.log(`b2a(input:${input}) exceedDepth:${exceedDepth} amountB:${amountB}`)\n\n    if (exceedDepth) {\n      if (marketInfo.isSwapEnabled) {\n        amountSBint = getAmountInWithFeeBips(amountB, feeBips, reserveIn, reserveOut)\n      }\n    } else {\n      const outputOrderbook = getOutputOrderbook(\n        input,\n        sellToken,\n        buyToken,\n        feeBips,\n        isAtoB,\n        isReverse,\n        depth,\n      )\n      amountSBint = fm.toBig(toWEI(tokenMap, sell, outputOrderbook))\n    }\n\n    if (amountSBint.gt(BIG0)) {\n      output = fromWEI(tokenMap, sell, amountSBint.toString())\n\n      amountBOutWithoutFee = fm.toBig(amountB).toFixed(0, 0)\n      // amountBOutWithoutFee = amountB\n      const leftRatio = BIG10K.minus(fm.toBig(takerRate)).div(BIG10K)\n      amountBOut = fm.toBig(amountB).times(leftRatio).toFixed(0, 0)\n    }\n\n    amountS = amountSBint.toFixed(0, 0)\n\n    // console.log('got amountSBint:', amountSBint.toString(), amountSBint.gt(BIG0), ' amountBOut:', amountBOut.toString())\n\n    sellAmt = output\n    buyAmt = input\n  }\n\n  minimumDecimal = buyToken.decimals\n\n  const amountBOutSlip = getMinReceived(amountBOut, minimumDecimal, slipBips)\n\n  const priceImpact = updatePriceImpact_new(\n    reserveIn,\n    reserveOut,\n    amountS,\n    sellToken.decimals,\n    amountBOut,\n    buyToken.decimals,\n    feeBips,\n    takerRate,\n    isAtoB,\n    isReverse,\n    exceedDepth,\n    depth,\n  )\n\n  return {\n    exceedDepth,\n    isReverse,\n    isAtoB,\n\n    slipBips,\n    takerRate,\n    feeBips,\n\n    output,\n\n    sellAmt,\n    buyAmt,\n\n    amountS,\n\n    amountBOut,\n    amountBOutWithoutFee,\n\n    amountBOutSlip,\n\n    priceImpact,\n  }\n}\n\nexport function ammPoolCalc(\n  rawVal: string,\n  isAtoB: boolean,\n  coinA: TokenVolumeV3,\n  coinB: TokenVolumeV3,\n) {\n  const coinA_Vol_BIG = fm.toBig(coinA.volume)\n  const coinB_Vol_BIG = fm.toBig(coinB.volume)\n\n  let output = BIG0\n\n  let ratio = BIG0\n\n  if (isAtoB) {\n    if (!coinA_Vol_BIG.eq(BIG0)) {\n      ratio = fm.toBig(rawVal).div(coinA_Vol_BIG)\n      output = ratio.times(coinB_Vol_BIG)\n    }\n  } else {\n    if (!coinB_Vol_BIG.eq(BIG0)) {\n      ratio = fm.toBig(rawVal).div(coinB_Vol_BIG)\n      output = ratio.times(coinA_Vol_BIG)\n    }\n  }\n\n  return {\n    output: output.toFixed(0, 0),\n    ratio,\n  }\n}\n\n/**\n *\n * @param rawVal\n * @param isAtoB\n * @param slippageTolerance\n * @param owner\n * @param fees\n * @param ammPoolSnapshot\n * @param tokenMap\n * @param idIdx\n * @param coinAOffchainId\n * @param coinBOffchainId\n * @param rawValMatchForRawVal first time add to pool\n */\nexport function makeJoinAmmPoolRequest(\n  rawVal: string,\n  isAtoB: boolean,\n  slippageTolerance: string,\n  owner: string,\n  fees: LoopringMap<OffchainFeeInfo>,\n  ammPoolSnapshot: AmmPoolSnapshot,\n  tokenMap: LoopringMap<TokenInfo>,\n  idIdx: LoopringMap<string>,\n  coinAOffchainId = 0,\n  coinBOffchainId = 0,\n  rawValMatchForRawVal?: string,\n) {\n  const coinA: TokenVolumeV3 = ammPoolSnapshot.pooled[0]\n  const coinB: TokenVolumeV3 = ammPoolSnapshot.pooled[1]\n\n  const baseToken: TokenInfo = tokenMap[idIdx[coinA.tokenId]]\n  const quoteToken: TokenInfo = tokenMap[idIdx[coinB.tokenId]]\n\n  const fee =\n    fees && fees[quoteToken.symbol] && fees[quoteToken.symbol].fee\n      ? fees[quoteToken.symbol].fee\n      : '0'\n\n  rawVal = fm\n    .toBig(rawVal)\n    .times(BIG10.pow(isAtoB ? baseToken.decimals : quoteToken.decimals))\n    .toFixed(0, 0)\n\n  // eslint-disable-next-line prefer-const\n  let { output, ratio } = ammPoolCalc(rawVal, isAtoB, coinA, coinB)\n  let volLp\n  if (output === '0' && rawValMatchForRawVal) {\n    output = fm\n      .toBig(rawValMatchForRawVal)\n      .times(BIG10.pow(isAtoB ? quoteToken.decimals : baseToken.decimals))\n      .toFixed(0, 0)\n    // ratio = fm.toBig(\"1\");\n    volLp = '1'\n  } else {\n    const rest = BIG1.minus(fm.toBig(slippageTolerance))\n    volLp = fm.toBig(ammPoolSnapshot.lp.volume).times(ratio).times(rest).toFixed(0, 0)\n  }\n  const volA = isAtoB ? rawVal : output\n  const volB = isAtoB ? output : rawVal\n\n  const request: JoinAmmPoolRequest = {\n    owner,\n    poolAddress: ammPoolSnapshot.poolAddress,\n    joinTokens: {\n      pooled: [\n        { tokenId: coinA.tokenId, volume: volA },\n        { tokenId: coinB.tokenId, volume: volB },\n      ],\n      minimumLp: { tokenId: ammPoolSnapshot.lp.tokenId, volume: volLp },\n    },\n    storageIds: [coinAOffchainId, coinBOffchainId],\n    fee,\n  }\n\n  return {\n    request,\n  }\n}\nexport function makeExitAmmPoolMini(\n  rawVal: string,\n  ammPoolSnapshot: AmmPoolSnapshot,\n  tokenMap: LoopringMap<TokenInfo>,\n  idIdx: LoopringMap<string>,\n  RatioDecimal = 10,\n) {\n  const lpTokenVol: TokenVolumeV3 = ammPoolSnapshot.lp\n  const lpToken: TokenInfo = tokenMap[idIdx[lpTokenVol.tokenId]]\n  const miniLpVol = fm //minLP Volume big number\n    .toBig(lpTokenVol.volume)\n    .times(2)\n    .div('1e' + RatioDecimal)\n  return {\n    miniLpVol: miniLpVol.toString(),\n    miniLpVal: fm\n      .toBig(miniLpVol)\n      .div('1e' + lpToken.decimals)\n      .toString(),\n  }\n}\nexport function makeExitAmmCoverFeeLP(\n  fees: LoopringMap<OffchainFeeInfo>,\n  ammPoolSnapshot: AmmPoolSnapshot,\n  tokenMap: LoopringMap<TokenInfo>,\n  idIdx: LoopringMap<string>,\n  slippageTolerance = '0.001',\n) {\n  const lpTokenVol: TokenVolumeV3 = ammPoolSnapshot.lp\n  const lpToken: TokenInfo = tokenMap[idIdx[lpTokenVol.tokenId]]\n  const quote: TokenVolumeV3 = ammPoolSnapshot.pooled[1]\n  const quoteToken: TokenInfo = tokenMap[idIdx[quote.tokenId]]\n  const quoteVolume = quote.volume\n\n  const maxFee = fees && fees[quoteToken.symbol] ? fees[quoteToken.symbol].fee : '0'\n  // feeLp = fee /snap.quote*snap.lp\n  const feeLp = fm.toBig(maxFee).times(lpTokenVol.volume).div(quoteVolume).plus(1)\n  // feeLp = feeLp / (1-slippageTolerance)  slippageTolerance default is 0.001\n  const feeLpWithSlippage = feeLp.div(BIG1.minus(fm.toBig(slippageTolerance)))\n  return {\n    feeLp: feeLp.toString(),\n    feeLpWithSlippage: feeLpWithSlippage.toString(),\n    miniFeeLpWithSlippageVal: fm\n      .toBig(feeLpWithSlippage)\n      .div('1e' + lpToken.decimals)\n      .toString(),\n    feeLpVal: fm\n      .toBig(feeLp)\n      .div('1e' + lpToken.decimals)\n      .toString(),\n  }\n}\n\nexport function makeExitAmmPoolRequest2(\n  rawVal: string,\n  slippageTolerance: string,\n  owner: string,\n  fees: LoopringMap<OffchainFeeInfo>,\n  ammPoolSnapshot: AmmPoolSnapshot,\n  tokenMap: LoopringMap<TokenInfo>,\n  idIdx: LoopringMap<string>,\n  offchainId = 0,\n  minDecimal = 10,\n) {\n  const lpTokenVol: TokenVolumeV3 = ammPoolSnapshot.lp\n  const lpToken: TokenInfo = tokenMap[idIdx[lpTokenVol.tokenId]]\n\n  const burnedVol = fm\n    .toBig(rawVal)\n    .times('1e' + lpToken.decimals)\n    .toFixed(0, 0)\n\n  const ratio = fm\n    .toBig(burnedVol)\n    .times('1e' + minDecimal)\n    .div(lpTokenVol.volume)\n    .toFixed(0, 1)\n\n  const coinA: TokenVolumeV3 = ammPoolSnapshot.pooled[0]\n  const coinB: TokenVolumeV3 = ammPoolSnapshot.pooled[1]\n\n  const rest = BIG1.minus(fm.toBig(slippageTolerance))\n\n  const volA = toBig(ratio)\n    .times(coinA.volume)\n    .div('1e' + minDecimal)\n    .times(rest)\n    .toFixed(0, 0)\n\n  const volB = toBig(ratio)\n    .times(coinB.volume)\n    .div('1e' + minDecimal)\n    .times(rest)\n    .toFixed(0, 0)\n\n  const baseToken: TokenInfo = tokenMap[idIdx[coinA.tokenId]]\n  const quoteToken: TokenInfo = tokenMap[idIdx[coinB.tokenId]]\n\n  const maxFee = fees && fees[quoteToken.symbol] ? fees[quoteToken.symbol].fee : '0'\n\n  const request: ExitAmmPoolRequest = {\n    owner,\n    poolAddress: ammPoolSnapshot.poolAddress,\n    exitTokens: {\n      unPooled: [\n        { tokenId: coinA.tokenId, volume: volA },\n        { tokenId: coinB.tokenId, volume: volB },\n      ],\n      burned: { tokenId: ammPoolSnapshot.lp.tokenId, volume: burnedVol },\n    },\n    storageId: offchainId,\n    maxFee,\n  }\n\n  return {\n    ratio,\n    volA,\n    volB,\n    volA_show: fm\n      .toBig(volA)\n      .div('1e' + baseToken.decimals)\n      .toString(),\n    volB_show: fm\n      .toBig(volB)\n      .div('1e' + quoteToken.decimals)\n      .toString(),\n    request,\n  }\n}\n\n/**\n * calcDefi\n * @param isJoin {boolean} true is join, false is exit\n * @param isInputSell {boolean} user input sell of buy\n * @param XOR<sellAmount,buyAmount> user input sell amount number (without decimals)\n * @param feeVol fee Volume from server-side (decimals)\n * @param marketInfo {DefiMarketInfo} DefiMarketInfo from sever-side\n * @param tokenSell {TokenInfo} token Config information\n * @param tokenBuy {TokenInfo} token Config information\n * @param buyTokenBalanceVol   buy Token Balance server-side (decimals)\n * @return {sellVol} sell Volume (decimals);\n * @return {buyVol} buy Volume (decimals);\n * @return {maxSellVol} max Sell Volume (decimals); please use ceil for view\n * @return {miniSellVol} min Sell Volume (decimals); please use round for view\n * @return {maxFeeBips} number maxFeeBips;\n * @return {isJoin} boolean;\n * @return {isInputSell} boolean;\n */\nexport function calcDefi({\n  isJoin,\n  isInputSell,\n  sellAmount,\n  buyAmount,\n  defaultFee,\n  maxFeeBips,\n  marketInfo,\n  tokenSell,\n  tokenBuy,\n  buyTokenBalanceVol,\n  withdrawFeeBips,\n}: {\n  isJoin: boolean\n  isInputSell: boolean\n  maxFeeBips: number\n  defaultFee: string\n  marketInfo: DefiMarketInfo\n  tokenSell: TokenInfo\n  tokenBuy: TokenInfo\n  buyTokenBalanceVol: string\n  withdrawFeeBips?: string | undefined\n  // feeVol\n} & XOR<{ sellAmount: string }, { buyAmount: string }>): {\n  sellVol: string\n  buyVol: string\n  maxSellVol: string\n  feeVol: string\n  maxFeeBips: number\n  miniSellVol: string\n  isJoin: boolean\n  isInputSell: boolean\n} {\n  /** isDeposit calc sellPrice & buyPrice */\n  const [sellPrice] = isJoin ? [marketInfo.depositPrice] : [marketInfo.withdrawPrice]\n  /** calc MiniSellVol & MaxSellVol**/\n  const dustToken = tokenBuy\n  const maxSellVol = fm.toBig(buyTokenBalanceVol).div(sellPrice)\n  /** calc MiniSellVol & MaxSellVol END**/\n  // debugger;\n  /** View input calc sellVol & buyVol */\n  let sellVol, buyVol\n  if (isInputSell) {\n    sellVol = fm.toBig(sellAmount ? sellAmount : 0).times('1e' + tokenSell.decimals)\n    buyVol = sellVol.times(sellPrice)\n  } else {\n    buyVol = fm.toBig(buyAmount ? buyAmount : 0).times('1e' + tokenBuy.decimals)\n    sellVol = buyVol.div(sellPrice)\n  }\n  /** View input calc sellVol & buyVol END */\n  let feeVol\n\n  /** calc current maxFeeBips **/\n  let cosFeeBips: any = buyVol.gt(0)\n    ? fm.toBig(defaultFee).times(10000).div(buyVol).toFixed(0, BigNumber.ROUND_CEIL)\n    : 0\n  let _maxFeeBips: any = BigNumber.max(cosFeeBips, 5, maxFeeBips)\n  if (!isJoin && withdrawFeeBips) {\n    _maxFeeBips = fm\n      .toBig(_maxFeeBips)\n      .plus(withdrawFeeBips ?? 0)\n      .toString()\n  }\n  feeVol = fm.toBig(_maxFeeBips).div(10000).times(buyVol).toString()\n  // defaultFee\n  const minVolBuy = BigNumber.max(fm.toBig(feeVol).times(2), dustToken.orderAmounts.dust)\n  const miniSellVol = BigNumber.max(minVolBuy.div(sellPrice), tokenSell.orderAmounts.dust)\n  return {\n    sellVol: sellVol.toString(),\n    buyVol: buyVol.toString(),\n    maxSellVol: maxSellVol.toString(),\n    feeVol,\n    isJoin,\n    isInputSell,\n    maxFeeBips: Number(_maxFeeBips),\n    miniSellVol: miniSellVol.toString(),\n  }\n}\n\n/**\n *\n * @param info\n * @param index\n * @param rule\n * @param balance\n * @param feeVol\n * @param sellToken\n * @param buyToken\n * @param sellAmount\n * @param currentPrice\n */\nexport function calcDual({\n  info,\n  index,\n  rule,\n  balance,\n  feeVol,\n  sellToken,\n  // dualViewInfo,\n  buyToken,\n  sellAmount,\n  dualMarket,\n}: {\n  sellAmount: string | undefined\n  info: DualProductAndPrice\n  index: DualIndex\n  rule: DualRulesCoinsInfo\n  balance: { [key: string]: DualBalance }\n  sellToken: TokenInfo\n  buyToken: TokenInfo\n\n  // dualViewInfo:R\n  feeVol?: string | undefined\n  dualMarket: DefiMarketInfo\n}): CalDualResult {\n  const sellVol = fm.toBig(sellAmount ? sellAmount : 0).times('1e' + sellToken.decimals)\n  let lessEarnVol,\n    lessEarnTokenSymbol,\n    greaterEarnVol,\n    greaterEarnTokenSymbol,\n    maxSellAmount,\n    miniSellVol,\n    feeTokenSymbol,\n    quota,\n    maxFeeBips\n  let { base } = info\n  let {\n    extra: { quoteAssetSymbol },\n  } = dualMarket\n  const settleRatio = fm.toBig(info.profit).times(info.ratio).toFixed(6, BigNumber.ROUND_DOWN)\n  if (info.dualType === DUAL_TYPE.DUAL_BASE) {\n    lessEarnVol = toBig(sellVol)\n    lessEarnTokenSymbol = sellToken.symbol\n    greaterEarnVol = toBig(\n      toBig(sellAmount ? sellAmount : 0)\n        .times(info.strike)\n        .toFixed(buyToken.precision, BigNumber.ROUND_CEIL),\n    ).times('1e' + buyToken.decimals)\n    // myLog('greaterEarnVol',toBig(settleRatio).plus(1).times(sellAmount ?sellAmount: 0)\n    // \t.times(info.strike).toFixed(buyToken.precision,BigNumber.ROUND_CEIL).toString(), greaterEarnVol.toString())\n    greaterEarnTokenSymbol = buyToken.symbol\n    miniSellVol = BigNumber.max(\n      dualMarket.baseLimitAmount,\n      toBig(rule.baseMin).times('1e' + sellToken.decimals),\n    ) // rule.baseMin;\n    quota = BigNumber.min(info.baseSize, balance ? balance[base]?.free : 0)\n    // quota = BigNumber.min(100, balance ? balance[ base ]?.free : 0)\n    maxSellAmount = BigNumber.min(rule.baseMax ? rule.baseMax : 0, quota)\n    feeTokenSymbol = buyToken.symbol\n    maxFeeBips = 5\n    //info.dualPrice.dualBid[ 0 ].baseQty;\n  } else {\n    lessEarnVol = toBig(\n      toBig(sellAmount ? sellAmount : 0)\n        // .times(1 + info.ratio)\n        .div(info.strike)\n        .toFixed(buyToken.precision, BigNumber.ROUND_CEIL),\n    ).times('1e' + buyToken.decimals)\n\n    // sellVol.times(1 + info.ratio).div(dualViewInfo.strike); //.times(1 + dualViewInfo.settleRatio);\n    lessEarnTokenSymbol = buyToken.symbol\n    greaterEarnVol = toBig(sellVol)\n    //.div(dualViewInfo.strike);\n    greaterEarnTokenSymbol = sellToken.symbol\n    miniSellVol = BigNumber.max(\n      dualMarket.quoteLimitAmount,\n      toBig(rule.currencyMin).times('1e' + sellToken.decimals),\n    ) // rule.baseMin;\n    quota = BigNumber.min(\n      toBig(info.baseSize).times(info.strike).toString(),\n      balance[quoteAssetSymbol].free,\n    )\n    maxSellAmount = BigNumber.min(rule.currencyMax, quota)\n    /** calc current maxFeeBips **/\n    feeTokenSymbol = buyToken.symbol\n    maxFeeBips = 5\n  }\n  myLog(\n    'settleRatio',\n    settleRatio,\n    lessEarnVol.toString(),\n    greaterEarnVol.toString(),\n    'strike',\n    info.strike,\n  )\n  return {\n    quota: quota.toString(),\n    sellVol: sellVol.toString(),\n    lessEarnVol: lessEarnVol.toString(),\n    lessEarnTokenSymbol,\n    greaterEarnVol: greaterEarnVol.toString(),\n    greaterEarnTokenSymbol,\n    miniSellVol: miniSellVol.toString(),\n    sellToken,\n    maxSellAmount: maxSellAmount ? maxSellAmount?.toString() : '',\n    maxFeeBips: maxFeeBips,\n    // dualViewInfo: dualViewInfo as unknown as R,\n    feeVol,\n    feeTokenSymbol,\n  }\n}\n\n/**\n *\n * @param info  BTRADE_MARKET\n * @param index\n * @param rule\n * @param balance\n * @param feeVol\n * @param sellToken\n * @param buyToken\n * @param sellAmount\n * @param currentPrice\n */\nexport function calcDex<R = BTRADE_MARKET | VaultMarket>({\n  info,\n  input,\n  sell,\n  buy,\n  isAtoB,\n  marketArr,\n  tokenMap,\n  marketMap,\n  depth,\n  feeBips,\n  slipBips,\n}: {\n  info: R\n  input: string\n  sell: string\n  buy: string\n  isAtoB: boolean\n  marketArr: string[]\n  tokenMap: LoopringMap<TokenInfo>\n  marketMap: LoopringMap<MarketInfo>\n  depth: DepthData\n  feeBips: string\n  slipBips: string\n}): BtradeResult<R> | undefined {\n  const sellToken = tokenMap[sell]\n  const buyToken = tokenMap[buy]\n  const reserveInfo = getReserveInfo(sell, buy, marketArr, tokenMap, marketMap)\n  if (!reserveInfo) {\n    throw {\n      message: ConnectorError.BTRADE_NO_PRODUCT,\n      msg: ConnectorError.BTRADE_NO_PRODUCT,\n      code: LoopringErrorCode.BTRADE_NO_PRODUCT,\n    }\n  }\n  const { isReverse } = reserveInfo\n  let sellVol, buyVol, amountB, amountS, exceedDepth, amountBSlipped\n  if (isAtoB) {\n    amountS = input\n    sellVol = fm.toBig(input ? input : 0).times('1e' + sellToken.decimals)\n    const amountInWei = sellVol\n    if (isEmpty(depth.bids_amtTotal) || isEmpty(depth.asks_volTotal)) {\n      throw {\n        message: ConnectorError.BTRADE_NO_DEPTH_ERROR,\n        msg: ConnectorError.BTRADE_NO_DEPTH_ERROR,\n        code: LoopringErrorCode.BTRADE_NO_DEPTH_ERROR,\n      }\n    } else {\n      if (!isReverse) {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.bids_amtTotal))\n      } else {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.asks_volTotal))\n      }\n      let outputOrderbook\n      if (exceedDepth) {\n        outputOrderbook = fm\n          .toBig(amountS)\n          .times(!isReverse ? depth.mid_price : 1 / depth.mid_price)\n\n        amountB = outputOrderbook.toString()\n        buyVol = fm.toBig(amountB).times('1e' + buyToken.decimals)\n      } else {\n        outputOrderbook = getOutputOrderbook(\n          input,\n          sellToken,\n          buyToken,\n          feeBips,\n          isAtoB,\n          isReverse,\n          depth,\n        ).toString()\n        amountB = outputOrderbook\n        buyVol = toWEI(tokenMap, buy, outputOrderbook)\n      }\n    }\n  } else {\n    amountB = input\n    buyVol = fm.toBig(input ? input : 0).times('1e' + buyToken.decimals)\n    const amountInWei = buyVol\n\n    if (isEmpty(depth.bids_volTotal) || isEmpty(depth.asks_amtTotal)) {\n      throw {\n        message: ConnectorError.BTRADE_NO_DEPTH_ERROR,\n        msg: ConnectorError.BTRADE_NO_DEPTH_ERROR,\n        code: LoopringErrorCode.BTRADE_NO_DEPTH_ERROR,\n      }\n    } else {\n      if (!isReverse) {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.bids_volTotal))\n      } else {\n        exceedDepth = fm.toBig(amountInWei).gt(fm.toBig(depth.asks_amtTotal))\n      }\n      let outputOrderbook\n      if (exceedDepth) {\n        outputOrderbook = fm.toBig(buyVol).times(!isReverse ? 1 / depth.mid_price : depth.mid_price)\n        amountS = outputOrderbook.toString()\n        sellVol = fm\n          .toBig(amountS)\n          .times('1e' + sellToken.decimals)\n          .toString()\n      } else {\n        outputOrderbook = getOutputOrderbook(\n          input,\n          sellToken,\n          buyToken,\n          feeBips,\n          isAtoB,\n          isReverse,\n          depth,\n        )\n        myLog(outputOrderbook.toString())\n        // sellVol = outputOrderbook;\n        sellVol = toWEI(tokenMap, sell, outputOrderbook)\n        amountS = fm\n          .toBig(sellVol ?? 0)\n          .div('1e' + sellToken.decimals)\n          .toString()\n      }\n    } // console.log(`b2a(input:${input}) exceedDepth:${exceedDepth} amountB:${amountB}`)\n  }\n  if (buyVol) {\n    amountBSlipped = getMinReceived(buyVol.toString(), buyToken.decimals, slipBips)\n    // amountBMiniReceiveCutFee = amountBSlipped.minReceived - feeBips\n  }\n  return {\n    feeBips,\n    info,\n    isAtoB,\n    isReverse,\n    sellVol: sellVol.toString(),\n    buyVol: buyVol.toString(),\n    amountB: amountB?.toString(),\n    amountS: amountS?.toString(),\n    amountBSlipped,\n    exceedDepth,\n  }\n}\n"
  },
  {
    "path": "src/utils/symbol_tools.ts",
    "content": "import { TokenInfo } from \"defs\";\n\nconst specialSymbols = [\"ETH2x-FIL\"];\n\nexport function getBaseQuote(symbol: string) {\n  if (!symbol) {\n    return {\n      base: undefined,\n      quote: undefined,\n    };\n  }\n\n  if (symbol.startsWith(\"AMM-\")) {\n    symbol = symbol.substr(4);\n  }\n\n  if (specialSymbols.length > 0) {\n    for (let i = 0; i < specialSymbols.length; i++) {\n      const ind = symbol.indexOf(specialSymbols[i]);\n      if (ind >= 0) {\n        if (ind === 0) {\n          return {\n            base: specialSymbols[i],\n            quote: symbol.substr(symbol.lastIndexOf(\"-\") + 1),\n          };\n        } else {\n          return {\n            base: symbol.substr(0, symbol.indexOf(\"-\")),\n            quote: specialSymbols[i],\n          };\n        }\n      }\n    }\n  }\n\n  const base = symbol.substr(0, symbol.indexOf(\"-\"));\n  const quote = symbol.substr(symbol.indexOf(\"-\") + 1);\n\n  return {\n    base,\n    quote,\n  };\n}\n\nexport const getTokenInfoBySymbol = (\n  tokenSymbolMap: { [key: string]: TokenInfo },\n  symbol: string\n) => {\n  if (!tokenSymbolMap) {\n    return undefined;\n  }\n  try {\n    return tokenSymbolMap[symbol];\n  } catch (err) {\n    return undefined;\n  }\n  return undefined;\n};\n\nexport const getTokenInfoById = (\n  tokenIdMap: { [key: number]: TokenInfo },\n  id: number\n) => {\n  if (!tokenIdMap) {\n    return undefined;\n  }\n  try {\n    return tokenIdMap[id];\n  } catch (err) {\n    return undefined;\n  }\n  return undefined;\n};\n\nexport const hasMarket = (marketArr: any, market: string) => {\n  if (!marketArr) {\n    return false;\n  }\n\n  if (marketArr.includes(market)) {\n    return true;\n  }\n  return false;\n};\n\nexport const getExistedMarket = (\n  marketArr: any,\n  base: string | undefined,\n  quote: string | undefined\n) => {\n  let market: any = undefined;\n  let baseShow: any = undefined;\n  let quoteShow: any = undefined;\n\n  if (base && quote) {\n    market = `${base}-${quote}`;\n    baseShow = base;\n    quoteShow = quote;\n    if (!hasMarket(marketArr, market)) {\n      market = `${quote}-${base}`;\n      if (hasMarket(marketArr, market)) {\n        baseShow = quote;\n        quoteShow = base;\n      } else {\n        market = undefined;\n        baseShow = undefined;\n        quoteShow = undefined;\n      }\n    }\n  }\n\n  const amm = market ? `AMM-${market}` : undefined;\n\n  return {\n    market,\n    amm,\n    baseShow,\n    quoteShow,\n  };\n};\nexport const getPair = (marketArr: any, market: string) => {\n  const { base, quote } = getBaseQuote(market);\n\n  return getExistedMarket(marketArr, base, quote);\n};\n"
  },
  {
    "path": "src/utils/window_utils.ts",
    "content": "export const getWindowSafely = () => {\n  if (typeof global.window === 'undefined' || typeof window === 'undefined') {\n    return undefined\n  } else {\n    return window\n  }\n}\n\nexport const getNavigatorSafely = () => {\n  if (typeof global.navigator === 'undefined' || typeof navigator === 'undefined') {\n    return undefined\n  } else {\n    return navigator\n  }\n}"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"baseUrl\": \"./src\",\n    \"rootDir\": \"./src\",\n    \"outDir\": \"./dist\",\n    \"module\": \"esnext\",\n    \"target\": \"ES2022\",\n    \"lib\": [\n      \"es2020\",\n      \"es5\"  ,\n      \"dom\"\n    ],\n    \"composite\": true,\n    \"sourceMap\": true,\n    \"allowJs\": true,\n    \"skipLibCheck\": true,\n    \"esModuleInterop\": true,\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"esModuleInterop\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"noImplicitAny\": true,\n    \"strict\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"moduleResolution\": \"node\",\n    \"resolveJsonModule\": true,\n    \"isolatedModules\": true,\n    \"noEmit\": true\n  },\n  \"include\": [\n    \"src\",\n    \"src/**/*.json\",\n    \"src/*\"\n  ],\n  \"exclude\": [\n    \"node_modules\",\n    \"dist\",\n    \".idea\"\n  ]\n}\n"
  }
]